├── deploy.sh ├── src ├── test │ ├── resources │ │ └── org.robolectric.Config.properties │ └── java │ │ └── com │ │ └── android │ │ └── volley │ │ ├── mock │ │ ├── ShadowSystemClock.java │ │ ├── MockCache.java │ │ ├── MockResponseDelivery.java │ │ ├── MockNetwork.java │ │ ├── MockHttpURLConnection.java │ │ ├── MockHttpStack.java │ │ ├── WaitableQueue.java │ │ ├── MockRequest.java │ │ ├── MockHttpClient.java │ │ └── TestRequest.java │ │ ├── utils │ │ ├── ImmediateResponseDelivery.java │ │ └── CacheTestUtils.java │ │ ├── toolbox │ │ ├── RequestFutureTest.java │ │ ├── StringRequestTest.java │ │ ├── CacheTest.java │ │ ├── RequestQueueTest.java │ │ ├── ResponseTest.java │ │ ├── JsonRequestTest.java │ │ ├── ByteArrayPoolTest.java │ │ ├── NetworkImageViewTest.java │ │ ├── PoolingByteArrayOutputStreamTest.java │ │ ├── BasicNetworkTest.java │ │ ├── RequestTest.java │ │ ├── ImageLoaderTest.java │ │ ├── AndroidAuthenticatorTest.java │ │ ├── JsonRequestCharsetTest.java │ │ ├── HttpClientStackTest.java │ │ └── DiskBasedCacheTest.java │ │ ├── ResponseDeliveryTest.java │ │ ├── RequestQueueTest.java │ │ ├── RequestTest.java │ │ ├── NetworkDispatcherTest.java │ │ └── CacheDispatcherTest.java └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── android │ └── volley │ ├── RedirectError.java │ ├── TimeoutError.java │ ├── ServerError.java │ ├── NoConnectionError.java │ ├── ParseError.java │ ├── Network.java │ ├── NetworkError.java │ ├── toolbox │ ├── Authenticator.java │ ├── NoCache.java │ ├── HttpStack.java │ ├── ClearCacheRequest.java │ ├── StringRequest.java │ ├── PoolingByteArrayOutputStream.java │ ├── JsonRequest.java │ ├── AndroidAuthenticator.java │ ├── RequestFuture.java │ ├── Volley.java │ ├── JsonObjectRequest.java │ ├── ByteArrayPool.java │ ├── JsonArrayRequest.java │ └── HttpHeaderParser.java │ ├── ResponseDelivery.java │ ├── InternalUtils.java │ ├── RetryPolicy.java │ ├── VolleyError.java │ ├── AuthFailureError.java │ ├── NetworkResponse.java │ ├── Response.java │ ├── Cache.java │ ├── DefaultRetryPolicy.java │ ├── ExecutorDelivery.java │ └── NetworkDispatcher.java ├── rules.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── custom_rules.xml ├── proguard-project.txt ├── gradle.properties ├── Android.mk ├── proguard.cfg ├── README.md ├── gradlew.bat ├── gradlew └── pom.xml /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./gradlew -x test clean assembleRelease uploadArchives 3 | -------------------------------------------------------------------------------- /src/test/resources/org.robolectric.Config.properties: -------------------------------------------------------------------------------- 1 | manifest=src/main/AndroidManifest.xml 2 | -------------------------------------------------------------------------------- /rules.gradle: -------------------------------------------------------------------------------- 1 | // See build.gradle for an explanation of what this file is. 2 | 3 | apply plugin: 'com.android.library' 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcxiaoke/android-volley/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Feb 13 14:10:23 CST 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.6-bin.zip 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .gradle 3 | gen 4 | bin 5 | local.properties 6 | *.apk 7 | .*.swp 8 | .idea 9 | gen-external-apklibs 10 | target 11 | classes 12 | project.properties 13 | *.iml 14 | .DS_Store 15 | out 16 | .gradle 17 | build 18 | .settings 19 | target 20 | *.iml 21 | .idea 22 | local.properties 23 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/ShadowSystemClock.java: -------------------------------------------------------------------------------- 1 | package com.android.volley.mock; 2 | 3 | import android.os.SystemClock; 4 | import org.robolectric.annotation.Implements; 5 | 6 | @Implements(value = SystemClock.class, callThroughByDefault = true) 7 | public class ShadowSystemClock { 8 | public static long elapsedRealtime() { 9 | return 0; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /custom_rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/RedirectError.java: -------------------------------------------------------------------------------- 1 | package com.android.volley; 2 | 3 | /** 4 | * Indicates that there was a redirection. 5 | */ 6 | public class RedirectError extends VolleyError { 7 | 8 | public RedirectError() { 9 | } 10 | 11 | public RedirectError(final Throwable cause) { 12 | super(cause); 13 | } 14 | 15 | public RedirectError(final NetworkResponse response) { 16 | super(response); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/utils/ImmediateResponseDelivery.java: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | 3 | package com.android.volley.utils; 4 | 5 | import com.android.volley.ExecutorDelivery; 6 | 7 | import java.util.concurrent.Executor; 8 | 9 | /** 10 | * A ResponseDelivery for testing that immediately delivers responses 11 | * instead of posting back to the main thread. 12 | */ 13 | public class ImmediateResponseDelivery extends ExecutorDelivery { 14 | 15 | public ImmediateResponseDelivery() { 16 | super(new Executor() { 17 | @Override 18 | public void execute(Runnable command) { 19 | command.run(); 20 | } 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 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 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME=1.0.19 2 | VERSION_CODE=20 3 | GROUP=com.mcxiaoke.volley 4 | 5 | POM_DESCRIPTION=Volley is a network library from Android source code. 6 | POM_URL=https://github.com/mcxiaoke/android-volley 7 | POM_SCM_URL=https://github.com/mcxiaoke/android-volley 8 | POM_SCM_CONNECTION=scm:git:git@github.com:mcxiaoke/android-volley.git 9 | POM_SCM_DEV_CONNECTION=scm:git:git@github.com:mcxiaoke/android-volley.git 10 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 11 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 12 | POM_LICENCE_DIST=repo 13 | POM_DEVELOPER_ID=mcxiaoke 14 | POM_DEVELOPER_NAME=Xiaoke Zhang 15 | POM_DEVELOPER_EMAIL=support@mcxiaoke.com 16 | 17 | ANDROID_BUILD_TARGET_SDK_VERSION=22 18 | ANDROID_BUILD_TOOLS_VERSION=22.0.1 19 | ANDROID_BUILD_SDK_VERSION=22 20 | 21 | POM_NAME=Android-Volley Library 22 | POM_ARTIFACT_ID=library 23 | POM_PACKAGING=aar 24 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/TimeoutError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Indicates that the connection or the socket timed out. 21 | */ 22 | @SuppressWarnings("serial") 23 | public class TimeoutError extends VolleyError { } 24 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/ServerError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Indicates that the server responded with an error response. 21 | */ 22 | @SuppressWarnings("serial") 23 | public class ServerError extends VolleyError { 24 | public ServerError(NetworkResponse networkResponse) { 25 | super(networkResponse); 26 | } 27 | 28 | public ServerError() { 29 | super(); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/NoConnectionError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Error indicating that no connection could be established when performing a Volley request. 21 | */ 22 | @SuppressWarnings("serial") 23 | public class NoConnectionError extends NetworkError { 24 | public NoConnectionError() { 25 | super(); 26 | } 27 | 28 | public NoConnectionError(Throwable reason) { 29 | super(reason); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/ParseError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Indicates that the server's response could not be parsed. 21 | */ 22 | @SuppressWarnings("serial") 23 | public class ParseError extends VolleyError { 24 | public ParseError() { } 25 | 26 | public ParseError(NetworkResponse networkResponse) { 27 | super(networkResponse); 28 | } 29 | 30 | public ParseError(Throwable cause) { 31 | super(cause); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2011 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 | LOCAL_PATH := $(call my-dir) 18 | 19 | include $(CLEAR_VARS) 20 | 21 | LOCAL_MODULE := volley 22 | LOCAL_SDK_VERSION := 17 23 | LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java) 24 | 25 | include $(BUILD_STATIC_JAVA_LIBRARY) 26 | 27 | # Include this library in the build server's output directory 28 | # TODO: Not yet. 29 | #$(call dist-for-goals, dist_files, $(LOCAL_BUILT_MODULE):volley.jar) 30 | 31 | # Include build files in subdirectories 32 | include $(call all-makefiles-under,$(LOCAL_PATH)) 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/Network.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * An interface for performing requests. 21 | */ 22 | public interface Network { 23 | /** 24 | * Performs the specified request. 25 | * @param request Request to process 26 | * @return A {@link NetworkResponse} with data and caching metadata; will never be null 27 | * @throws VolleyError on errors 28 | */ 29 | public NetworkResponse performRequest(Request request) throws VolleyError; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/NetworkError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Indicates that there was a network error when performing a Volley request. 21 | */ 22 | @SuppressWarnings("serial") 23 | public class NetworkError extends VolleyError { 24 | public NetworkError() { 25 | super(); 26 | } 27 | 28 | public NetworkError(Throwable cause) { 29 | super(cause); 30 | } 31 | 32 | public NetworkError(NetworkResponse networkResponse) { 33 | super(networkResponse); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/Authenticator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.AuthFailureError; 20 | 21 | /** 22 | * An interface for interacting with auth tokens. 23 | */ 24 | public interface Authenticator { 25 | /** 26 | * Synchronously retrieves an auth token. 27 | * 28 | * @throws AuthFailureError If authentication did not succeed 29 | */ 30 | public String getAuthToken() throws AuthFailureError; 31 | 32 | /** 33 | * Invalidates the provided auth token. 34 | */ 35 | public void invalidateAuthToken(String authToken); 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/RequestFutureTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Request; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.robolectric.RobolectricTestRunner; 23 | 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | @RunWith(RobolectricTestRunner.class) 27 | public class RequestFutureTest { 28 | 29 | @Test 30 | public void publicMethods() throws Exception { 31 | // Catch-all test to find API-breaking changes. 32 | assertNotNull(RequestFuture.class.getMethod("newFuture")); 33 | assertNotNull(RequestFuture.class.getMethod("setRequest", Request.class)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/ResponseDelivery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | public interface ResponseDelivery { 20 | /** 21 | * Parses a response from the network or cache and delivers it. 22 | */ 23 | public void postResponse(Request request, Response response); 24 | 25 | /** 26 | * Parses a response from the network or cache and delivers it. The provided 27 | * Runnable will be executed after delivery. 28 | */ 29 | public void postResponse(Request request, Response response, Runnable runnable); 30 | 31 | /** 32 | * Posts an error for the given request. 33 | */ 34 | public void postError(Request request, VolleyError error); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/NoCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Cache; 20 | 21 | /** 22 | * A cache that doesn't. 23 | */ 24 | public class NoCache implements Cache { 25 | @Override 26 | public void clear() { 27 | } 28 | 29 | @Override 30 | public Entry get(String key) { 31 | return null; 32 | } 33 | 34 | @Override 35 | public void put(String key, Entry entry) { 36 | } 37 | 38 | @Override 39 | public void invalidate(String key, boolean fullExpire) { 40 | } 41 | 42 | @Override 43 | public void remove(String key) { 44 | } 45 | 46 | @Override 47 | public void initialize() { 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/InternalUtils.java: -------------------------------------------------------------------------------- 1 | package com.android.volley; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | /** 8 | * User: mcxiaoke 9 | * Date: 15/3/17 10 | * Time: 14:47 11 | */ 12 | class InternalUtils { 13 | 14 | // http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-java 15 | private final static char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); 16 | 17 | private static String convertToHex(byte[] bytes) { 18 | char[] hexChars = new char[bytes.length * 2]; 19 | for (int j = 0; j < bytes.length; j++) { 20 | int v = bytes[j] & 0xFF; 21 | hexChars[j * 2] = HEX_CHARS[v >>> 4]; 22 | hexChars[j * 2 + 1] = HEX_CHARS[v & 0x0F]; 23 | } 24 | return new String(hexChars); 25 | } 26 | 27 | public static String sha1Hash(String text) { 28 | String hash = null; 29 | try { 30 | final MessageDigest digest = MessageDigest.getInstance("SHA-1"); 31 | final byte[] bytes = text.getBytes("UTF-8"); 32 | digest.update(bytes, 0, bytes.length); 33 | hash = convertToHex(digest.digest()); 34 | } catch (NoSuchAlgorithmException e) { 35 | e.printStackTrace(); 36 | } catch (UnsupportedEncodingException e) { 37 | e.printStackTrace(); 38 | } 39 | return hash; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/RetryPolicy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Retry policy for a request. 21 | */ 22 | public interface RetryPolicy { 23 | 24 | /** 25 | * Returns the current timeout (used for logging). 26 | */ 27 | public int getCurrentTimeout(); 28 | 29 | /** 30 | * Returns the current retry count (used for logging). 31 | */ 32 | public int getCurrentRetryCount(); 33 | 34 | /** 35 | * Prepares for the next retry by applying a backoff to the timeout. 36 | * @param error The error code of the last attempt. 37 | * @throws VolleyError In the event that the retry could not be performed (for example if we 38 | * ran out of attempts), the passed in error is thrown. 39 | */ 40 | public void retry(VolleyError error) throws VolleyError; 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/utils/CacheTestUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | 3 | package com.android.volley.utils; 4 | 5 | import com.android.volley.Cache; 6 | 7 | import java.util.Random; 8 | 9 | public class CacheTestUtils { 10 | 11 | /** 12 | * Makes a random cache entry. 13 | * @param data Data to use, or null to use random data 14 | * @param isExpired Whether the TTLs should be set such that this entry is expired 15 | * @param needsRefresh Whether the TTLs should be set such that this entry needs refresh 16 | */ 17 | public static Cache.Entry makeRandomCacheEntry( 18 | byte[] data, boolean isExpired, boolean needsRefresh) { 19 | Random random = new Random(); 20 | Cache.Entry entry = new Cache.Entry(); 21 | if (data != null) { 22 | entry.data = data; 23 | } else { 24 | entry.data = new byte[random.nextInt(1024)]; 25 | } 26 | entry.etag = String.valueOf(random.nextLong()); 27 | entry.lastModified = random.nextLong(); 28 | entry.ttl = isExpired ? 0 : Long.MAX_VALUE; 29 | entry.softTtl = needsRefresh ? 0 : Long.MAX_VALUE; 30 | return entry; 31 | } 32 | 33 | /** 34 | * Like {@link #makeRandomCacheEntry(byte[], boolean, boolean)} but 35 | * defaults to an unexpired entry. 36 | */ 37 | public static Cache.Entry makeRandomCacheEntry(byte[] data) { 38 | return makeRandomCacheEntry(data, false, false); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/StringRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Response; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.robolectric.RobolectricTestRunner; 23 | 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | @RunWith(RobolectricTestRunner.class) 27 | public class StringRequestTest { 28 | 29 | @Test 30 | public void publicMethods() throws Exception { 31 | // Catch-all test to find API-breaking changes. 32 | assertNotNull(StringRequest.class.getConstructor(String.class, Response.Listener.class, 33 | Response.ErrorListener.class)); 34 | assertNotNull(StringRequest.class.getConstructor(int.class, String.class, 35 | Response.Listener.class, Response.ErrorListener.class)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/CacheTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Cache; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.robolectric.RobolectricTestRunner; 23 | 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | @RunWith(RobolectricTestRunner.class) 27 | public class CacheTest { 28 | 29 | @Test 30 | public void publicMethods() throws Exception { 31 | // Catch-all test to find API-breaking changes. 32 | assertNotNull(Cache.class.getMethod("get", String.class)); 33 | assertNotNull(Cache.class.getMethod("put", String.class, Cache.Entry.class)); 34 | assertNotNull(Cache.class.getMethod("initialize")); 35 | assertNotNull(Cache.class.getMethod("invalidate", String.class, boolean.class)); 36 | assertNotNull(Cache.class.getMethod("remove", String.class)); 37 | assertNotNull(Cache.class.getMethod("clear")); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/HttpStack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.AuthFailureError; 20 | import com.android.volley.Request; 21 | 22 | import org.apache.http.HttpResponse; 23 | 24 | import java.io.IOException; 25 | import java.util.Map; 26 | 27 | /** 28 | * An HTTP stack abstraction. 29 | */ 30 | public interface HttpStack { 31 | /** 32 | * Performs an HTTP request with the given parameters. 33 | * 34 | *

A GET request is sent if request.getPostBody() == null. A POST request is sent otherwise, 35 | * and the Content-Type header is set to request.getPostBodyContentType().

36 | * 37 | * @param request the request to perform 38 | * @param additionalHeaders additional headers to be sent together with 39 | * {@link Request#getHeaders()} 40 | * @return the HTTP response 41 | */ 42 | public HttpResponse performRequest(Request request, Map additionalHeaders) 43 | throws IOException, AuthFailureError; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/VolleyError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Exception style class encapsulating Volley errors 21 | */ 22 | @SuppressWarnings("serial") 23 | public class VolleyError extends Exception { 24 | public final NetworkResponse networkResponse; 25 | private long networkTimeMs; 26 | 27 | public VolleyError() { 28 | networkResponse = null; 29 | } 30 | 31 | public VolleyError(NetworkResponse response) { 32 | networkResponse = response; 33 | } 34 | 35 | public VolleyError(String exceptionMessage) { 36 | super(exceptionMessage); 37 | networkResponse = null; 38 | } 39 | 40 | public VolleyError(String exceptionMessage, Throwable reason) { 41 | super(exceptionMessage, reason); 42 | networkResponse = null; 43 | } 44 | 45 | public VolleyError(Throwable cause) { 46 | super(cause); 47 | networkResponse = null; 48 | } 49 | 50 | /* package */ void setNetworkTimeMs(long networkTimeMs) { 51 | this.networkTimeMs = networkTimeMs; 52 | } 53 | 54 | public long getNetworkTimeMs() { 55 | return networkTimeMs; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import com.android.volley.Cache; 20 | 21 | public class MockCache implements Cache { 22 | 23 | public boolean clearCalled = false; 24 | @Override 25 | public void clear() { 26 | clearCalled = true; 27 | } 28 | 29 | public boolean getCalled = false; 30 | private Entry mFakeEntry = null; 31 | 32 | public void setEntryToReturn(Entry entry) { 33 | mFakeEntry = entry; 34 | } 35 | 36 | @Override 37 | public Entry get(String key) { 38 | getCalled = true; 39 | return mFakeEntry; 40 | } 41 | 42 | public boolean putCalled = false; 43 | public String keyPut = null; 44 | public Entry entryPut = null; 45 | 46 | @Override 47 | public void put(String key, Entry entry) { 48 | putCalled = true; 49 | keyPut = key; 50 | entryPut = entry; 51 | } 52 | 53 | @Override 54 | public void invalidate(String key, boolean fullExpire) { 55 | } 56 | 57 | @Override 58 | public void remove(String key) { 59 | } 60 | 61 | @Override 62 | public void initialize() { 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockResponseDelivery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import com.android.volley.Request; 20 | import com.android.volley.Response; 21 | import com.android.volley.ResponseDelivery; 22 | import com.android.volley.VolleyError; 23 | 24 | public class MockResponseDelivery implements ResponseDelivery { 25 | 26 | public boolean postResponse_called = false; 27 | public boolean postError_called = false; 28 | 29 | public boolean wasEitherResponseCalled() { 30 | return postResponse_called || postError_called; 31 | } 32 | 33 | public Response responsePosted = null; 34 | @Override 35 | public void postResponse(Request request, Response response) { 36 | postResponse_called = true; 37 | responsePosted = response; 38 | } 39 | 40 | @Override 41 | public void postResponse(Request request, Response response, Runnable runnable) { 42 | postResponse_called = true; 43 | responsePosted = response; 44 | runnable.run(); 45 | } 46 | 47 | @Override 48 | public void postError(Request request, VolleyError error) { 49 | postError_called = true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/AuthFailureError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import android.content.Intent; 20 | 21 | /** 22 | * Error indicating that there was an authentication failure when performing a Request. 23 | */ 24 | @SuppressWarnings("serial") 25 | public class AuthFailureError extends VolleyError { 26 | /** An intent that can be used to resolve this exception. (Brings up the password dialog.) */ 27 | private Intent mResolutionIntent; 28 | 29 | public AuthFailureError() { } 30 | 31 | public AuthFailureError(Intent intent) { 32 | mResolutionIntent = intent; 33 | } 34 | 35 | public AuthFailureError(NetworkResponse response) { 36 | super(response); 37 | } 38 | 39 | public AuthFailureError(String message) { 40 | super(message); 41 | } 42 | 43 | public AuthFailureError(String message, Exception reason) { 44 | super(message, reason); 45 | } 46 | 47 | public Intent getResolutionIntent() { 48 | return mResolutionIntent; 49 | } 50 | 51 | @Override 52 | public String getMessage() { 53 | if (mResolutionIntent != null) { 54 | return "User needs to (re)enter credentials."; 55 | } 56 | return super.getMessage(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockNetwork.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import com.android.volley.Network; 20 | import com.android.volley.NetworkResponse; 21 | import com.android.volley.Request; 22 | import com.android.volley.ServerError; 23 | import com.android.volley.VolleyError; 24 | 25 | public class MockNetwork implements Network { 26 | public final static int ALWAYS_THROW_EXCEPTIONS = -1; 27 | 28 | private int mNumExceptionsToThrow = 0; 29 | private byte[] mDataToReturn = null; 30 | 31 | /** 32 | * @param numExceptionsToThrow number of times to throw an exception or 33 | * {@link #ALWAYS_THROW_EXCEPTIONS} 34 | */ 35 | public void setNumExceptionsToThrow(int numExceptionsToThrow) { 36 | mNumExceptionsToThrow = numExceptionsToThrow; 37 | } 38 | 39 | public void setDataToReturn(byte[] data) { 40 | mDataToReturn = data; 41 | } 42 | 43 | public Request requestHandled = null; 44 | 45 | @Override 46 | public NetworkResponse performRequest(Request request) throws VolleyError { 47 | if (mNumExceptionsToThrow > 0 || mNumExceptionsToThrow == ALWAYS_THROW_EXCEPTIONS) { 48 | if (mNumExceptionsToThrow != ALWAYS_THROW_EXCEPTIONS) { 49 | mNumExceptionsToThrow--; 50 | } 51 | throw new ServerError(); 52 | } 53 | 54 | requestHandled = request; 55 | return new NetworkResponse(mDataToReturn); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/RequestQueueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.*; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.robolectric.RobolectricTestRunner; 23 | 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | @RunWith(RobolectricTestRunner.class) 27 | public class RequestQueueTest { 28 | 29 | @Test 30 | public void publicMethods() throws Exception { 31 | // Catch-all test to find API-breaking changes. 32 | assertNotNull(RequestQueue.class.getConstructor(Cache.class, Network.class, int.class, 33 | ResponseDelivery.class)); 34 | assertNotNull(RequestQueue.class.getConstructor(Cache.class, Network.class, int.class)); 35 | assertNotNull(RequestQueue.class.getConstructor(Cache.class, Network.class)); 36 | 37 | assertNotNull(RequestQueue.class.getMethod("start")); 38 | assertNotNull(RequestQueue.class.getMethod("stop")); 39 | assertNotNull(RequestQueue.class.getMethod("getSequenceNumber")); 40 | assertNotNull(RequestQueue.class.getMethod("getCache")); 41 | assertNotNull(RequestQueue.class.getMethod("cancelAll", RequestQueue.RequestFilter.class)); 42 | assertNotNull(RequestQueue.class.getMethod("cancelAll", Object.class)); 43 | assertNotNull(RequestQueue.class.getMethod("add", Request.class)); 44 | assertNotNull(RequestQueue.class.getDeclaredMethod("finish", Request.class)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## DEPRECATED 2 | 3 | ### Please note, this project is deprecated and no longer being maintained, please use official version [volley](https://github.com/google/volley). 4 | 5 | ---------- 6 | 7 | # Intro 8 | 9 | This is an unofficial mirror (with some minor bugfix) for [volley](https://android.googlesource.com/platform/frameworks/volley). 10 | 11 | * [![Maven Central](http://img.shields.io/badge/2015.09.08-com.mcxiaoke.volley:library:1.0.19-brightgreen.svg)](http://search.maven.org/#artifactdetails%7Ccom.mcxiaoke.volley%7Clibrary%7C1.0.19%7Cjar) 12 | 13 | ## Gradle 14 | 15 | ``` groovy 16 | compile 'com.mcxiaoke.volley:library:1.0.19' 17 | ``` 18 | 19 | ## Contacts 20 | 21 | * Blog: 22 | * Github: 23 | * Email: [github@mcxiaoke.com](mailto:github@mcxiaoke.com) 24 | 25 | ## Projects 26 | 27 | * Awesome-Kotlin: 28 | * Kotlin-Koi: 29 | * Android-Next: 30 | * Packer-Ng: 31 | * Gradle-Packer: 32 | * xBus: 33 | * RxJava Docs: 34 | * MQTT-CN: 35 | * Minicat App: 36 | * Fanfou App: 37 | 38 | ## License 39 | 40 | 41 | Copyright (C) 2014,2015,2016 Xiaoke Zhang 42 | Copyright (C) 2011 The Android Open Source Project 43 | 44 | Licensed under the Apache License, Version 2.0 (the "License"); 45 | you may not use this file except in compliance with the License. 46 | You may obtain a copy of the License at 47 | 48 | http://www.apache.org/licenses/LICENSE-2.0 49 | 50 | Unless required by applicable law or agreed to in writing, software 51 | distributed under the License is distributed on an "AS IS" BASIS, 52 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 53 | See the License for the specific language governing permissions and 54 | limitations under the License. 55 | 56 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockHttpURLConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.mock; 18 | 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.IOException; 21 | import java.io.OutputStream; 22 | import java.net.HttpURLConnection; 23 | import java.net.MalformedURLException; 24 | import java.net.URL; 25 | 26 | public class MockHttpURLConnection extends HttpURLConnection { 27 | 28 | private boolean mDoOutput; 29 | private String mRequestMethod; 30 | private OutputStream mOutputStream; 31 | 32 | public MockHttpURLConnection() throws MalformedURLException { 33 | super(new URL("http://foo.com")); 34 | mDoOutput = false; 35 | mRequestMethod = "GET"; 36 | mOutputStream = new ByteArrayOutputStream(); 37 | } 38 | 39 | @Override 40 | public void setDoOutput(boolean flag) { 41 | mDoOutput = flag; 42 | } 43 | 44 | @Override 45 | public boolean getDoOutput() { 46 | return mDoOutput; 47 | } 48 | 49 | @Override 50 | public void setRequestMethod(String method) { 51 | mRequestMethod = method; 52 | } 53 | 54 | @Override 55 | public String getRequestMethod() { 56 | return mRequestMethod; 57 | } 58 | 59 | @Override 60 | public OutputStream getOutputStream() { 61 | return mOutputStream; 62 | } 63 | 64 | @Override 65 | public void disconnect() { 66 | } 67 | 68 | @Override 69 | public boolean usingProxy() { 70 | return false; 71 | } 72 | 73 | @Override 74 | public void connect() throws IOException { 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/ResponseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Cache; 20 | import com.android.volley.NetworkResponse; 21 | import com.android.volley.Response; 22 | import com.android.volley.VolleyError; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.robolectric.RobolectricTestRunner; 26 | 27 | import java.util.Map; 28 | 29 | import static org.junit.Assert.assertNotNull; 30 | 31 | @RunWith(RobolectricTestRunner.class) 32 | public class ResponseTest { 33 | 34 | @Test 35 | public void publicMethods() throws Exception { 36 | // Catch-all test to find API-breaking changes. 37 | assertNotNull(Response.class.getMethod("success", Object.class, Cache.Entry.class)); 38 | assertNotNull(Response.class.getMethod("error", VolleyError.class)); 39 | assertNotNull(Response.class.getMethod("isSuccess")); 40 | 41 | assertNotNull(Response.Listener.class.getDeclaredMethod("onResponse", Object.class)); 42 | 43 | assertNotNull(Response.ErrorListener.class.getDeclaredMethod("onErrorResponse", 44 | VolleyError.class)); 45 | 46 | assertNotNull(NetworkResponse.class.getConstructor(int.class, byte[].class, Map.class, 47 | boolean.class, long.class)); 48 | assertNotNull(NetworkResponse.class.getConstructor(int.class, byte[].class, Map.class, 49 | boolean.class)); 50 | assertNotNull(NetworkResponse.class.getConstructor(byte[].class)); 51 | assertNotNull(NetworkResponse.class.getConstructor(byte[].class, Map.class)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/JsonRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Response; 20 | import org.json.JSONArray; 21 | import org.json.JSONObject; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.robolectric.RobolectricTestRunner; 25 | 26 | import static org.junit.Assert.assertNotNull; 27 | 28 | @RunWith(RobolectricTestRunner.class) 29 | public class JsonRequestTest { 30 | 31 | @Test 32 | public void publicMethods() throws Exception { 33 | // Catch-all test to find API-breaking changes. 34 | assertNotNull(JsonRequest.class.getConstructor(String.class, String.class, 35 | Response.Listener.class, Response.ErrorListener.class)); 36 | assertNotNull(JsonRequest.class.getConstructor(int.class, String.class, String.class, 37 | Response.Listener.class, Response.ErrorListener.class)); 38 | 39 | assertNotNull(JsonArrayRequest.class.getConstructor(String.class, 40 | Response.Listener.class, Response.ErrorListener.class)); 41 | assertNotNull(JsonArrayRequest.class.getConstructor(int.class, String.class, JSONArray.class, 42 | Response.Listener.class, Response.ErrorListener.class)); 43 | 44 | assertNotNull(JsonObjectRequest.class.getConstructor(String.class, JSONObject.class, 45 | Response.Listener.class, Response.ErrorListener.class)); 46 | assertNotNull(JsonObjectRequest.class.getConstructor(int.class, String.class, 47 | JSONObject.class, Response.Listener.class, Response.ErrorListener.class)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/ClearCacheRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Cache; 20 | import com.android.volley.NetworkResponse; 21 | import com.android.volley.Request; 22 | import com.android.volley.Response; 23 | 24 | import android.os.Handler; 25 | import android.os.Looper; 26 | 27 | /** 28 | * A synthetic request used for clearing the cache. 29 | */ 30 | public class ClearCacheRequest extends Request { 31 | private final Cache mCache; 32 | private final Runnable mCallback; 33 | 34 | /** 35 | * Creates a synthetic request for clearing the cache. 36 | * @param cache Cache to clear 37 | * @param callback Callback to make on the main thread once the cache is clear, 38 | * or null for none 39 | */ 40 | public ClearCacheRequest(Cache cache, Runnable callback) { 41 | super(Method.GET, null, null); 42 | mCache = cache; 43 | mCallback = callback; 44 | } 45 | 46 | @Override 47 | public boolean isCanceled() { 48 | // This is a little bit of a hack, but hey, why not. 49 | mCache.clear(); 50 | if (mCallback != null) { 51 | Handler handler = new Handler(Looper.getMainLooper()); 52 | handler.postAtFrontOfQueue(mCallback); 53 | } 54 | return true; 55 | } 56 | 57 | @Override 58 | public Priority getPriority() { 59 | return Priority.IMMEDIATE; 60 | } 61 | 62 | @Override 63 | protected Response parseNetworkResponse(NetworkResponse response) { 64 | return null; 65 | } 66 | 67 | @Override 68 | protected void deliverResponse(Object response) { 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockHttpStack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import com.android.volley.AuthFailureError; 20 | import com.android.volley.Request; 21 | import com.android.volley.toolbox.HttpStack; 22 | 23 | import org.apache.http.HttpResponse; 24 | 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | public class MockHttpStack implements HttpStack { 29 | 30 | private HttpResponse mResponseToReturn; 31 | 32 | private String mLastUrl; 33 | 34 | private Map mLastHeaders; 35 | 36 | private byte[] mLastPostBody; 37 | 38 | public String getLastUrl() { 39 | return mLastUrl; 40 | } 41 | 42 | public Map getLastHeaders() { 43 | return mLastHeaders; 44 | } 45 | 46 | public byte[] getLastPostBody() { 47 | return mLastPostBody; 48 | } 49 | 50 | public void setResponseToReturn(HttpResponse response) { 51 | mResponseToReturn = response; 52 | } 53 | 54 | @Override 55 | public HttpResponse performRequest(Request request, Map additionalHeaders) 56 | throws AuthFailureError { 57 | mLastUrl = request.getUrl(); 58 | mLastHeaders = new HashMap(); 59 | if (request.getHeaders() != null) { 60 | mLastHeaders.putAll(request.getHeaders()); 61 | } 62 | if (additionalHeaders != null) { 63 | mLastHeaders.putAll(additionalHeaders); 64 | } 65 | try { 66 | mLastPostBody = request.getBody(); 67 | } catch (AuthFailureError e) { 68 | mLastPostBody = null; 69 | } 70 | return mResponseToReturn; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/ByteArrayPoolTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.toolbox; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | 24 | import static org.junit.Assert.*; 25 | 26 | public class ByteArrayPoolTest { 27 | @Test public void reusesBuffer() { 28 | ByteArrayPool pool = new ByteArrayPool(32); 29 | 30 | byte[] buf1 = pool.getBuf(16); 31 | byte[] buf2 = pool.getBuf(16); 32 | 33 | pool.returnBuf(buf1); 34 | pool.returnBuf(buf2); 35 | 36 | byte[] buf3 = pool.getBuf(16); 37 | byte[] buf4 = pool.getBuf(16); 38 | assertTrue(buf3 == buf1 || buf3 == buf2); 39 | assertTrue(buf4 == buf1 || buf4 == buf2); 40 | assertTrue(buf3 != buf4); 41 | } 42 | 43 | @Test public void obeysSizeLimit() { 44 | ByteArrayPool pool = new ByteArrayPool(32); 45 | 46 | byte[] buf1 = pool.getBuf(16); 47 | byte[] buf2 = pool.getBuf(16); 48 | byte[] buf3 = pool.getBuf(16); 49 | 50 | pool.returnBuf(buf1); 51 | pool.returnBuf(buf2); 52 | pool.returnBuf(buf3); 53 | 54 | byte[] buf4 = pool.getBuf(16); 55 | byte[] buf5 = pool.getBuf(16); 56 | byte[] buf6 = pool.getBuf(16); 57 | 58 | assertTrue(buf4 == buf2 || buf4 == buf3); 59 | assertTrue(buf5 == buf2 || buf5 == buf3); 60 | assertTrue(buf4 != buf5); 61 | assertTrue(buf6 != buf1 && buf6 != buf2 && buf6 != buf3); 62 | } 63 | 64 | @Test public void returnsBufferWithRightSize() { 65 | ByteArrayPool pool = new ByteArrayPool(32); 66 | 67 | byte[] buf1 = pool.getBuf(16); 68 | pool.returnBuf(buf1); 69 | 70 | byte[] buf2 = pool.getBuf(17); 71 | assertNotSame(buf2, buf1); 72 | 73 | byte[] buf3 = pool.getBuf(15); 74 | assertSame(buf3, buf1); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/WaitableQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Request; 21 | import com.android.volley.Response; 22 | 23 | import java.util.concurrent.PriorityBlockingQueue; 24 | import java.util.concurrent.Semaphore; 25 | import java.util.concurrent.TimeUnit; 26 | import java.util.concurrent.TimeoutException; 27 | 28 | // TODO: the name of this class sucks 29 | @SuppressWarnings("serial") 30 | public class WaitableQueue extends PriorityBlockingQueue> { 31 | private final Request mStopRequest = new MagicStopRequest(); 32 | private final Semaphore mStopEvent = new Semaphore(0); 33 | 34 | // TODO: this isn't really "until empty" it's "until next call to take() after empty" 35 | public void waitUntilEmpty(long timeoutMillis) 36 | throws TimeoutException, InterruptedException { 37 | add(mStopRequest); 38 | if (!mStopEvent.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS)) { 39 | throw new TimeoutException(); 40 | } 41 | } 42 | 43 | @Override 44 | public Request take() throws InterruptedException { 45 | Request item = super.take(); 46 | if (item == mStopRequest) { 47 | mStopEvent.release(); 48 | return take(); 49 | } 50 | return item; 51 | } 52 | 53 | private static class MagicStopRequest extends Request { 54 | public MagicStopRequest() { 55 | super(Request.Method.GET, "", null); 56 | } 57 | 58 | @Override 59 | public Priority getPriority() { 60 | return Priority.LOW; 61 | } 62 | 63 | @Override 64 | protected Response parseNetworkResponse(NetworkResponse response) { 65 | return null; 66 | } 67 | 68 | @Override 69 | protected void deliverResponse(Object response) { 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/ResponseDeliveryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import com.android.volley.mock.MockRequest; 20 | import com.android.volley.utils.CacheTestUtils; 21 | import com.android.volley.utils.ImmediateResponseDelivery; 22 | 23 | import org.junit.After; 24 | import org.junit.Before; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.robolectric.RobolectricTestRunner; 28 | 29 | import static org.junit.Assert.*; 30 | 31 | @RunWith(RobolectricTestRunner.class) 32 | public class ResponseDeliveryTest { 33 | 34 | private ExecutorDelivery mDelivery; 35 | private MockRequest mRequest; 36 | private Response mSuccessResponse; 37 | 38 | @Before public void setUp() throws Exception { 39 | // Make the delivery just run its posted responses immediately. 40 | mDelivery = new ImmediateResponseDelivery(); 41 | mRequest = new MockRequest(); 42 | mRequest.setSequence(1); 43 | byte[] data = new byte[16]; 44 | Cache.Entry cacheEntry = CacheTestUtils.makeRandomCacheEntry(data); 45 | mSuccessResponse = Response.success(data, cacheEntry); 46 | } 47 | 48 | @Test public void postResponseCallsDeliverResponse() { 49 | mDelivery.postResponse(mRequest, mSuccessResponse); 50 | assertTrue(mRequest.deliverResponse_called); 51 | assertFalse(mRequest.deliverError_called); 52 | } 53 | 54 | @Test public void postResponseSuppressesCanceled() { 55 | mRequest.cancel(); 56 | mDelivery.postResponse(mRequest, mSuccessResponse); 57 | assertFalse(mRequest.deliverResponse_called); 58 | assertFalse(mRequest.deliverError_called); 59 | } 60 | 61 | @Test public void postErrorCallsDeliverError() { 62 | Response errorResponse = Response.error(new ServerError()); 63 | 64 | mDelivery.postResponse(mRequest, errorResponse); 65 | assertTrue(mRequest.deliverError_called); 66 | assertFalse(mRequest.deliverResponse_called); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/RequestQueueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import com.android.volley.mock.ShadowSystemClock; 20 | import com.android.volley.toolbox.NoCache; 21 | import com.android.volley.utils.ImmediateResponseDelivery; 22 | import org.junit.Before; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.mockito.Mock; 26 | import org.robolectric.RobolectricTestRunner; 27 | import org.robolectric.annotation.Config; 28 | 29 | import static org.junit.Assert.*; 30 | import static org.mockito.Mockito.*; 31 | import static org.mockito.MockitoAnnotations.initMocks; 32 | 33 | /** 34 | * Unit tests for RequestQueue, with all dependencies mocked out 35 | */ 36 | @RunWith(RobolectricTestRunner.class) 37 | @Config(shadows = {ShadowSystemClock.class}) 38 | public class RequestQueueTest { 39 | 40 | private ResponseDelivery mDelivery; 41 | @Mock private Network mMockNetwork; 42 | 43 | @Before public void setUp() throws Exception { 44 | mDelivery = new ImmediateResponseDelivery(); 45 | initMocks(this); 46 | } 47 | 48 | @Test public void cancelAll_onlyCorrectTag() throws Exception { 49 | RequestQueue queue = new RequestQueue(new NoCache(), mMockNetwork, 0, mDelivery); 50 | Object tagA = new Object(); 51 | Object tagB = new Object(); 52 | Request req1 = mock(Request.class); 53 | when(req1.getTag()).thenReturn(tagA); 54 | Request req2 = mock(Request.class); 55 | when(req2.getTag()).thenReturn(tagB); 56 | Request req3 = mock(Request.class); 57 | when(req3.getTag()).thenReturn(tagA); 58 | Request req4 = mock(Request.class); 59 | when(req4.getTag()).thenReturn(tagA); 60 | 61 | queue.add(req1); // A 62 | queue.add(req2); // B 63 | queue.add(req3); // A 64 | queue.cancelAll(tagA); 65 | queue.add(req4); // A 66 | 67 | verify(req1).cancel(); // A cancelled 68 | verify(req3).cancel(); // A cancelled 69 | verify(req2, never()).cancel(); // B not cancelled 70 | verify(req4, never()).cancel(); // A added after cancel not cancelled 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/NetworkResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import org.apache.http.HttpStatus; 20 | 21 | import java.io.Serializable; 22 | import java.util.Collections; 23 | import java.util.Map; 24 | 25 | /** 26 | * Data and headers returned from {@link Network#performRequest(Request)}. 27 | */ 28 | public class NetworkResponse implements Serializable{ 29 | private static final long serialVersionUID = -20150728102000L; 30 | 31 | /** 32 | * Creates a new network response. 33 | * @param statusCode the HTTP status code 34 | * @param data Response body 35 | * @param headers Headers returned with this response, or null for none 36 | * @param notModified True if the server returned a 304 and the data was already in cache 37 | * @param networkTimeMs Round-trip network time to receive network response 38 | */ 39 | public NetworkResponse(int statusCode, byte[] data, Map headers, 40 | boolean notModified, long networkTimeMs) { 41 | this.statusCode = statusCode; 42 | this.data = data; 43 | this.headers = headers; 44 | this.notModified = notModified; 45 | this.networkTimeMs = networkTimeMs; 46 | } 47 | 48 | public NetworkResponse(int statusCode, byte[] data, Map headers, 49 | boolean notModified) { 50 | this(statusCode, data, headers, notModified, 0); 51 | } 52 | 53 | public NetworkResponse(byte[] data) { 54 | this(HttpStatus.SC_OK, data, Collections.emptyMap(), false, 0); 55 | } 56 | 57 | public NetworkResponse(byte[] data, Map headers) { 58 | this(HttpStatus.SC_OK, data, headers, false, 0); 59 | } 60 | 61 | /** The HTTP status code. */ 62 | public final int statusCode; 63 | 64 | /** Raw data from this response. */ 65 | public final byte[] data; 66 | 67 | /** Response headers. */ 68 | public final Map headers; 69 | 70 | /** True if the server returned a 304 (Not Modified). */ 71 | public final boolean notModified; 72 | 73 | /** Network roundtrip time in milliseconds. */ 74 | public final long networkTimeMs; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/NetworkImageViewTest.java: -------------------------------------------------------------------------------- 1 | package com.android.volley.toolbox; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.ViewGroup.LayoutParams; 6 | import android.widget.ImageView.ScaleType; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.robolectric.Robolectric; 12 | import org.robolectric.RobolectricTestRunner; 13 | 14 | import static org.junit.Assert.*; 15 | 16 | @RunWith(RobolectricTestRunner.class) 17 | public class NetworkImageViewTest { 18 | private NetworkImageView mNIV; 19 | private MockImageLoader mMockImageLoader; 20 | 21 | @Before public void setUp() throws Exception { 22 | mMockImageLoader = new MockImageLoader(); 23 | mNIV = new NetworkImageView(Robolectric.application); 24 | } 25 | 26 | @Test public void setImageUrl_requestsImage() { 27 | mNIV.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 28 | mNIV.setImageUrl("http://foo", mMockImageLoader); 29 | assertEquals("http://foo", mMockImageLoader.lastRequestUrl); 30 | assertEquals(0, mMockImageLoader.lastMaxWidth); 31 | assertEquals(0, mMockImageLoader.lastMaxHeight); 32 | } 33 | 34 | // public void testSetImageUrl_setsMaxSize() { 35 | // // TODO: Not sure how to make getWidth() return something from an 36 | // // instrumentation test. Write this test once it's figured out. 37 | // } 38 | 39 | private class MockImageLoader extends ImageLoader { 40 | public MockImageLoader() { 41 | super(null, null); 42 | } 43 | 44 | public String lastRequestUrl; 45 | public int lastMaxWidth; 46 | public int lastMaxHeight; 47 | 48 | public ImageContainer get(String requestUrl, ImageListener imageListener, int maxWidth, 49 | int maxHeight, ScaleType scaleType) { 50 | lastRequestUrl = requestUrl; 51 | lastMaxWidth = maxWidth; 52 | lastMaxHeight = maxHeight; 53 | return null; 54 | } 55 | } 56 | 57 | @Test 58 | public void publicMethods() throws Exception { 59 | // Catch-all test to find API-breaking changes. 60 | assertNotNull(NetworkImageView.class.getConstructor(Context.class)); 61 | assertNotNull(NetworkImageView.class.getConstructor(Context.class, AttributeSet.class)); 62 | assertNotNull(NetworkImageView.class.getConstructor(Context.class, AttributeSet.class, 63 | int.class)); 64 | 65 | assertNotNull(NetworkImageView.class.getMethod("setImageUrl", String.class, ImageLoader.class)); 66 | assertNotNull(NetworkImageView.class.getMethod("setDefaultImageResId", int.class)); 67 | assertNotNull(NetworkImageView.class.getMethod("setErrorImageResId", int.class)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/PoolingByteArrayOutputStreamTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import java.io.IOException; 20 | import java.util.Arrays; 21 | 22 | import org.junit.Test; 23 | 24 | import static org.junit.Assert.*; 25 | 26 | public class PoolingByteArrayOutputStreamTest { 27 | @Test public void pooledOneBuffer() throws IOException { 28 | ByteArrayPool pool = new ByteArrayPool(32768); 29 | writeOneBuffer(pool); 30 | writeOneBuffer(pool); 31 | writeOneBuffer(pool); 32 | } 33 | 34 | @Test public void pooledIndividualWrites() throws IOException { 35 | ByteArrayPool pool = new ByteArrayPool(32768); 36 | writeBytesIndividually(pool); 37 | writeBytesIndividually(pool); 38 | writeBytesIndividually(pool); 39 | } 40 | 41 | @Test public void unpooled() throws IOException { 42 | ByteArrayPool pool = new ByteArrayPool(0); 43 | writeOneBuffer(pool); 44 | writeOneBuffer(pool); 45 | writeOneBuffer(pool); 46 | } 47 | 48 | @Test public void unpooledIndividualWrites() throws IOException { 49 | ByteArrayPool pool = new ByteArrayPool(0); 50 | writeBytesIndividually(pool); 51 | writeBytesIndividually(pool); 52 | writeBytesIndividually(pool); 53 | } 54 | 55 | private void writeOneBuffer(ByteArrayPool pool) throws IOException { 56 | byte[] data = new byte[16384]; 57 | for (int i = 0; i < data.length; i++) { 58 | data[i] = (byte) (i & 0xff); 59 | } 60 | PoolingByteArrayOutputStream os = new PoolingByteArrayOutputStream(pool); 61 | os.write(data); 62 | 63 | assertTrue(Arrays.equals(data, os.toByteArray())); 64 | } 65 | 66 | private void writeBytesIndividually(ByteArrayPool pool) { 67 | byte[] data = new byte[16384]; 68 | for (int i = 0; i < data.length; i++) { 69 | data[i] = (byte) (i & 0xff); 70 | } 71 | PoolingByteArrayOutputStream os = new PoolingByteArrayOutputStream(pool); 72 | for (int i = 0; i < data.length; i++) { 73 | os.write(data[i]); 74 | } 75 | 76 | assertTrue(Arrays.equals(data, os.toByteArray())); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/Response.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Encapsulates a parsed response for delivery. 21 | * 22 | * @param Parsed type of this response 23 | */ 24 | public class Response { 25 | 26 | /** Callback interface for delivering parsed responses. */ 27 | public interface Listener { 28 | /** Called when a response is received. */ 29 | public void onResponse(T response); 30 | } 31 | 32 | /** Callback interface for delivering error responses. */ 33 | public interface ErrorListener { 34 | /** 35 | * Callback method that an error has been occurred with the 36 | * provided error code and optional user-readable message. 37 | */ 38 | public void onErrorResponse(VolleyError error); 39 | } 40 | 41 | /** Returns a successful response containing the parsed result. */ 42 | public static Response success(T result, Cache.Entry cacheEntry) { 43 | return new Response(result, cacheEntry); 44 | } 45 | 46 | /** 47 | * Returns a failed response containing the given error code and an optional 48 | * localized message displayed to the user. 49 | */ 50 | public static Response error(VolleyError error) { 51 | return new Response(error); 52 | } 53 | 54 | /** Parsed response, or null in the case of error. */ 55 | public final T result; 56 | 57 | /** Cache metadata for this response, or null in the case of error. */ 58 | public final Cache.Entry cacheEntry; 59 | 60 | /** Detailed error information if errorCode != OK. */ 61 | public final VolleyError error; 62 | 63 | /** True if this response was a soft-expired one and a second one MAY be coming. */ 64 | public boolean intermediate = false; 65 | 66 | /** 67 | * Returns whether this response is considered successful. 68 | */ 69 | public boolean isSuccess() { 70 | return error == null; 71 | } 72 | 73 | 74 | private Response(T result, Cache.Entry cacheEntry) { 75 | this.result = result; 76 | this.cacheEntry = cacheEntry; 77 | this.error = null; 78 | } 79 | 80 | private Response(VolleyError error) { 81 | this.result = null; 82 | this.cacheEntry = null; 83 | this.error = error; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/StringRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Request; 21 | import com.android.volley.Response; 22 | import com.android.volley.Response.ErrorListener; 23 | import com.android.volley.Response.Listener; 24 | 25 | import java.io.UnsupportedEncodingException; 26 | 27 | /** 28 | * A canned request for retrieving the response body at a given URL as a String. 29 | */ 30 | public class StringRequest extends Request { 31 | private Listener mListener; 32 | 33 | /** 34 | * Creates a new request with the given method. 35 | * 36 | * @param method the request {@link Method} to use 37 | * @param url URL to fetch the string at 38 | * @param listener Listener to receive the String response 39 | * @param errorListener Error listener, or null to ignore errors 40 | */ 41 | public StringRequest(int method, String url, Listener listener, 42 | ErrorListener errorListener) { 43 | super(method, url, errorListener); 44 | mListener = listener; 45 | } 46 | 47 | /** 48 | * Creates a new GET request. 49 | * 50 | * @param url URL to fetch the string at 51 | * @param listener Listener to receive the String response 52 | * @param errorListener Error listener, or null to ignore errors 53 | */ 54 | public StringRequest(String url, Listener listener, ErrorListener errorListener) { 55 | this(Method.GET, url, listener, errorListener); 56 | } 57 | 58 | @Override 59 | protected void onFinish() { 60 | super.onFinish(); 61 | mListener = null; 62 | } 63 | 64 | @Override 65 | protected void deliverResponse(String response) { 66 | if (mListener != null) { 67 | mListener.onResponse(response); 68 | } 69 | } 70 | 71 | @Override 72 | protected Response parseNetworkResponse(NetworkResponse response) { 73 | String parsed; 74 | try { 75 | parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 76 | } catch (UnsupportedEncodingException e) { 77 | parsed = new String(response.data); 78 | } 79 | return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/BasicNetworkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Request; 21 | import com.android.volley.Response; 22 | import com.android.volley.mock.MockHttpStack; 23 | 24 | import org.apache.http.ProtocolVersion; 25 | import org.apache.http.entity.StringEntity; 26 | import org.apache.http.message.BasicHttpResponse; 27 | 28 | import org.junit.After; 29 | import org.junit.Before; 30 | import org.junit.Test; 31 | import org.junit.runner.RunWith; 32 | import org.robolectric.RobolectricTestRunner; 33 | 34 | import static org.junit.Assert.*; 35 | 36 | import java.util.HashMap; 37 | import java.util.Map; 38 | 39 | @RunWith(RobolectricTestRunner.class) 40 | public class BasicNetworkTest { 41 | 42 | @Test public void headersAndPostParams() throws Exception { 43 | MockHttpStack mockHttpStack = new MockHttpStack(); 44 | BasicHttpResponse fakeResponse = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 45 | 200, "OK"); 46 | fakeResponse.setEntity(new StringEntity("foobar")); 47 | mockHttpStack.setResponseToReturn(fakeResponse); 48 | BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack); 49 | Request request = new Request(Request.Method.GET, "http://foo", null) { 50 | 51 | @Override 52 | protected Response parseNetworkResponse(NetworkResponse response) { 53 | return null; 54 | } 55 | 56 | @Override 57 | protected void deliverResponse(String response) { 58 | } 59 | 60 | @Override 61 | public Map getHeaders() { 62 | Map result = new HashMap(); 63 | result.put("requestheader", "foo"); 64 | return result; 65 | } 66 | 67 | @Override 68 | public Map getParams() { 69 | Map result = new HashMap(); 70 | result.put("requestpost", "foo"); 71 | return result; 72 | } 73 | }; 74 | httpNetwork.performRequest(request); 75 | assertEquals("foo", mockHttpStack.getLastHeaders().get("requestheader")); 76 | assertEquals("requestpost=foo&", new String(mockHttpStack.getLastPostBody())); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Request; 21 | import com.android.volley.Response; 22 | import com.android.volley.Response.ErrorListener; 23 | import com.android.volley.VolleyError; 24 | import com.android.volley.utils.CacheTestUtils; 25 | 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | 29 | public class MockRequest extends Request { 30 | public MockRequest() { 31 | super(Request.Method.GET, "http://foo.com", null); 32 | } 33 | 34 | public MockRequest(String url, ErrorListener listener) { 35 | super(Request.Method.GET, url, listener); 36 | } 37 | 38 | private Map mPostParams = new HashMap(); 39 | 40 | public void setPostParams(Map postParams) { 41 | mPostParams = postParams; 42 | } 43 | 44 | @Override 45 | public Map getPostParams() { 46 | return mPostParams; 47 | } 48 | 49 | private String mCacheKey = super.getCacheKey(); 50 | 51 | public void setCacheKey(String cacheKey) { 52 | mCacheKey = cacheKey; 53 | } 54 | 55 | @Override 56 | public String getCacheKey() { 57 | return mCacheKey; 58 | } 59 | 60 | public boolean deliverResponse_called = false; 61 | public boolean parseResponse_called = false; 62 | 63 | @Override 64 | protected void deliverResponse(byte[] response) { 65 | deliverResponse_called = true; 66 | } 67 | 68 | public boolean deliverError_called = false; 69 | 70 | @Override 71 | public void deliverError(VolleyError error) { 72 | super.deliverError(error); 73 | deliverError_called = true; 74 | } 75 | 76 | public boolean cancel_called = false; 77 | 78 | @Override 79 | public void cancel() { 80 | cancel_called = true; 81 | super.cancel(); 82 | } 83 | 84 | private Priority mPriority = super.getPriority(); 85 | 86 | public void setPriority(Priority priority) { 87 | mPriority = priority; 88 | } 89 | 90 | @Override 91 | public Priority getPriority() { 92 | return mPriority; 93 | } 94 | 95 | @Override 96 | protected Response parseNetworkResponse(NetworkResponse response) { 97 | parseResponse_called = true; 98 | return Response.success(response.data, CacheTestUtils.makeRandomCacheEntry(response.data)); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.toolbox; 18 | 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.IOException; 21 | 22 | /** 23 | * A variation of {@link java.io.ByteArrayOutputStream} that uses a pool of byte[] buffers instead 24 | * of always allocating them fresh, saving on heap churn. 25 | */ 26 | public class PoolingByteArrayOutputStream extends ByteArrayOutputStream { 27 | /** 28 | * If the {@link #PoolingByteArrayOutputStream(ByteArrayPool)} constructor is called, this is 29 | * the default size to which the underlying byte array is initialized. 30 | */ 31 | private static final int DEFAULT_SIZE = 256; 32 | 33 | private final ByteArrayPool mPool; 34 | 35 | /** 36 | * Constructs a new PoolingByteArrayOutputStream with a default size. If more bytes are written 37 | * to this instance, the underlying byte array will expand. 38 | */ 39 | public PoolingByteArrayOutputStream(ByteArrayPool pool) { 40 | this(pool, DEFAULT_SIZE); 41 | } 42 | 43 | /** 44 | * Constructs a new {@code ByteArrayOutputStream} with a default size of {@code size} bytes. If 45 | * more than {@code size} bytes are written to this instance, the underlying byte array will 46 | * expand. 47 | * 48 | * @param size initial size for the underlying byte array. The value will be pinned to a default 49 | * minimum size. 50 | */ 51 | public PoolingByteArrayOutputStream(ByteArrayPool pool, int size) { 52 | mPool = pool; 53 | buf = mPool.getBuf(Math.max(size, DEFAULT_SIZE)); 54 | } 55 | 56 | @Override 57 | public void close() throws IOException { 58 | mPool.returnBuf(buf); 59 | buf = null; 60 | super.close(); 61 | } 62 | 63 | @Override 64 | public void finalize() { 65 | mPool.returnBuf(buf); 66 | } 67 | 68 | /** 69 | * Ensures there is enough space in the buffer for the given number of additional bytes. 70 | */ 71 | private void expand(int i) { 72 | /* Can the buffer handle @i more bytes, if not expand it */ 73 | if (count + i <= buf.length) { 74 | return; 75 | } 76 | byte[] newbuf = mPool.getBuf((count + i) * 2); 77 | System.arraycopy(buf, 0, newbuf, 0, count); 78 | mPool.returnBuf(buf); 79 | buf = newbuf; 80 | } 81 | 82 | @Override 83 | public synchronized void write(byte[] buffer, int offset, int len) { 84 | expand(len); 85 | super.write(buffer, offset, len); 86 | } 87 | 88 | @Override 89 | public synchronized void write(int oneByte) { 90 | expand(1); 91 | super.write(oneByte); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/Cache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import java.util.Collections; 20 | import java.util.Map; 21 | 22 | /** 23 | * An interface for a cache keyed by a String with a byte array as data. 24 | */ 25 | public interface Cache { 26 | /** 27 | * Retrieves an entry from the cache. 28 | * @param key Cache key 29 | * @return An {@link Entry} or null in the event of a cache miss 30 | */ 31 | public Entry get(String key); 32 | 33 | /** 34 | * Adds or replaces an entry to the cache. 35 | * @param key Cache key 36 | * @param entry Data to store and metadata for cache coherency, TTL, etc. 37 | */ 38 | public void put(String key, Entry entry); 39 | 40 | /** 41 | * Performs any potentially long-running actions needed to initialize the cache; 42 | * will be called from a worker thread. 43 | */ 44 | public void initialize(); 45 | 46 | /** 47 | * Invalidates an entry in the cache. 48 | * @param key Cache key 49 | * @param fullExpire True to fully expire the entry, false to soft expire 50 | */ 51 | public void invalidate(String key, boolean fullExpire); 52 | 53 | /** 54 | * Removes an entry from the cache. 55 | * @param key Cache key 56 | */ 57 | public void remove(String key); 58 | 59 | /** 60 | * Empties the cache. 61 | */ 62 | public void clear(); 63 | 64 | /** 65 | * Data and metadata for an entry returned by the cache. 66 | */ 67 | public static class Entry { 68 | /** The data returned from cache. */ 69 | public byte[] data; 70 | 71 | /** ETag for cache coherency. */ 72 | public String etag; 73 | 74 | /** Date of this response as reported by the server. */ 75 | public long serverDate; 76 | 77 | /** The last modified date for the requested object. */ 78 | public long lastModified; 79 | 80 | /** TTL for this record. */ 81 | public long ttl; 82 | 83 | /** Soft TTL for this record. */ 84 | public long softTtl; 85 | 86 | /** Immutable response headers as received from server; must be non-null. */ 87 | public Map responseHeaders = Collections.emptyMap(); 88 | 89 | /** True if the entry is expired. */ 90 | public boolean isExpired() { 91 | return this.ttl < System.currentTimeMillis(); 92 | } 93 | 94 | /** True if a refresh is needed from the original data source. */ 95 | public boolean refreshNeeded() { 96 | return this.softTtl < System.currentTimeMillis(); 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/DefaultRetryPolicy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | /** 20 | * Default retry policy for requests. 21 | */ 22 | public class DefaultRetryPolicy implements RetryPolicy { 23 | /** The current timeout in milliseconds. */ 24 | private int mCurrentTimeoutMs; 25 | 26 | /** The current retry count. */ 27 | private int mCurrentRetryCount; 28 | 29 | /** The maximum number of attempts. */ 30 | private final int mMaxNumRetries; 31 | 32 | /** The backoff multiplier for the policy. */ 33 | private final float mBackoffMultiplier; 34 | 35 | /** The default socket timeout in milliseconds */ 36 | public static final int DEFAULT_TIMEOUT_MS = 2500; 37 | 38 | /** The default number of retries */ 39 | public static final int DEFAULT_MAX_RETRIES = 0; 40 | 41 | /** The default backoff multiplier */ 42 | public static final float DEFAULT_BACKOFF_MULT = 1f; 43 | 44 | 45 | /** 46 | * Constructs a new retry policy using the default timeouts. 47 | */ 48 | public DefaultRetryPolicy() { 49 | this(DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_BACKOFF_MULT); 50 | } 51 | 52 | /** 53 | * Constructs a new retry policy. 54 | * @param initialTimeoutMs The initial timeout for the policy. 55 | * @param maxNumRetries The maximum number of retries. 56 | * @param backoffMultiplier Backoff multiplier for the policy. 57 | */ 58 | public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) { 59 | mCurrentTimeoutMs = initialTimeoutMs; 60 | mMaxNumRetries = maxNumRetries; 61 | mBackoffMultiplier = backoffMultiplier; 62 | } 63 | 64 | /** 65 | * Returns the current timeout. 66 | */ 67 | @Override 68 | public int getCurrentTimeout() { 69 | return mCurrentTimeoutMs; 70 | } 71 | 72 | /** 73 | * Returns the current retry count. 74 | */ 75 | @Override 76 | public int getCurrentRetryCount() { 77 | return mCurrentRetryCount; 78 | } 79 | 80 | /** 81 | * Returns the backoff multiplier for the policy. 82 | */ 83 | public float getBackoffMultiplier() { 84 | return mBackoffMultiplier; 85 | } 86 | 87 | /** 88 | * Prepares for the next retry by applying a backoff to the timeout. 89 | * @param error The error code of the last attempt. 90 | */ 91 | @Override 92 | public void retry(VolleyError error) throws VolleyError { 93 | mCurrentRetryCount++; 94 | mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier); 95 | if (!hasAttemptRemaining()) { 96 | throw error; 97 | } 98 | } 99 | 100 | /** 101 | * Returns true if this policy has attempts remaining, false otherwise. 102 | */ 103 | protected boolean hasAttemptRemaining() { 104 | return mCurrentRetryCount <= mMaxNumRetries; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/RequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import com.android.volley.Request.Priority; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.robolectric.RobolectricTestRunner; 23 | 24 | import static org.junit.Assert.*; 25 | 26 | @RunWith(RobolectricTestRunner.class) 27 | public class RequestTest { 28 | 29 | @Test public void compareTo() { 30 | int sequence = 0; 31 | TestRequest low = new TestRequest(Priority.LOW); 32 | low.setSequence(sequence++); 33 | TestRequest low2 = new TestRequest(Priority.LOW); 34 | low2.setSequence(sequence++); 35 | TestRequest high = new TestRequest(Priority.HIGH); 36 | high.setSequence(sequence++); 37 | TestRequest immediate = new TestRequest(Priority.IMMEDIATE); 38 | immediate.setSequence(sequence++); 39 | 40 | // "Low" should sort higher because it's really processing order. 41 | assertTrue(low.compareTo(high) > 0); 42 | assertTrue(high.compareTo(low) < 0); 43 | assertTrue(low.compareTo(low2) < 0); 44 | assertTrue(low.compareTo(immediate) > 0); 45 | assertTrue(immediate.compareTo(high) < 0); 46 | } 47 | 48 | private class TestRequest extends Request { 49 | private Priority mPriority = Priority.NORMAL; 50 | public TestRequest(Priority priority) { 51 | super(Request.Method.GET, "", null); 52 | mPriority = priority; 53 | } 54 | 55 | @Override 56 | public Priority getPriority() { 57 | return mPriority; 58 | } 59 | 60 | @Override 61 | protected void deliverResponse(Object response) { 62 | } 63 | 64 | @Override 65 | protected Response parseNetworkResponse(NetworkResponse response) { 66 | return null; 67 | } 68 | } 69 | 70 | @Test public void urlParsing() { 71 | UrlParseRequest nullUrl = new UrlParseRequest(null); 72 | assertEquals(0, nullUrl.getTrafficStatsTag()); 73 | UrlParseRequest emptyUrl = new UrlParseRequest(""); 74 | assertEquals(0, emptyUrl.getTrafficStatsTag()); 75 | UrlParseRequest noHost = new UrlParseRequest("http:///"); 76 | assertEquals(0, noHost.getTrafficStatsTag()); 77 | UrlParseRequest badProtocol = new UrlParseRequest("bad:http://foo"); 78 | assertEquals(0, badProtocol.getTrafficStatsTag()); 79 | UrlParseRequest goodProtocol = new UrlParseRequest("http://foo"); 80 | assertFalse(0 == goodProtocol.getTrafficStatsTag()); 81 | } 82 | 83 | private class UrlParseRequest extends Request { 84 | public UrlParseRequest(String url) { 85 | super(Request.Method.GET, url, null); 86 | } 87 | 88 | @Override 89 | protected void deliverResponse(Object response) { 90 | } 91 | 92 | @Override 93 | protected Response parseNetworkResponse(NetworkResponse response) { 94 | return null; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/RequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import com.android.volley.*; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.robolectric.RobolectricTestRunner; 23 | 24 | import static org.junit.Assert.assertNotNull; 25 | 26 | @RunWith(RobolectricTestRunner.class) 27 | public class RequestTest { 28 | 29 | @Test 30 | public void publicMethods() throws Exception { 31 | // Catch-all test to find API-breaking changes. 32 | assertNotNull(Request.class.getConstructor(int.class, String.class, 33 | Response.ErrorListener.class)); 34 | 35 | assertNotNull(Request.class.getMethod("getMethod")); 36 | assertNotNull(Request.class.getMethod("setTag", Object.class)); 37 | assertNotNull(Request.class.getMethod("getTag")); 38 | assertNotNull(Request.class.getMethod("getErrorListener")); 39 | assertNotNull(Request.class.getMethod("getTrafficStatsTag")); 40 | assertNotNull(Request.class.getMethod("setRetryPolicy", RetryPolicy.class)); 41 | assertNotNull(Request.class.getMethod("addMarker", String.class)); 42 | assertNotNull(Request.class.getDeclaredMethod("finish", String.class)); 43 | assertNotNull(Request.class.getMethod("setRequestQueue", RequestQueue.class)); 44 | assertNotNull(Request.class.getMethod("setSequence", int.class)); 45 | assertNotNull(Request.class.getMethod("getSequence")); 46 | assertNotNull(Request.class.getMethod("getUrl")); 47 | assertNotNull(Request.class.getMethod("getCacheKey")); 48 | assertNotNull(Request.class.getMethod("setCacheEntry", Cache.Entry.class)); 49 | assertNotNull(Request.class.getMethod("getCacheEntry")); 50 | assertNotNull(Request.class.getMethod("cancel")); 51 | assertNotNull(Request.class.getMethod("isCanceled")); 52 | assertNotNull(Request.class.getMethod("getHeaders")); 53 | assertNotNull(Request.class.getDeclaredMethod("getParams")); 54 | assertNotNull(Request.class.getDeclaredMethod("getParamsEncoding")); 55 | assertNotNull(Request.class.getMethod("getBodyContentType")); 56 | assertNotNull(Request.class.getMethod("getBody")); 57 | assertNotNull(Request.class.getMethod("setShouldCache", boolean.class)); 58 | assertNotNull(Request.class.getMethod("shouldCache")); 59 | assertNotNull(Request.class.getMethod("getPriority")); 60 | assertNotNull(Request.class.getMethod("getTimeoutMs")); 61 | assertNotNull(Request.class.getMethod("getRetryPolicy")); 62 | assertNotNull(Request.class.getMethod("markDelivered")); 63 | assertNotNull(Request.class.getMethod("hasHadResponseDelivered")); 64 | assertNotNull(Request.class.getDeclaredMethod("parseNetworkResponse", NetworkResponse.class)); 65 | assertNotNull(Request.class.getDeclaredMethod("parseNetworkError", VolleyError.class)); 66 | assertNotNull(Request.class.getDeclaredMethod("deliverResponse", Object.class)); 67 | assertNotNull(Request.class.getMethod("deliverError", VolleyError.class)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/JsonRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Request; 21 | import com.android.volley.Response; 22 | import com.android.volley.Response.ErrorListener; 23 | import com.android.volley.Response.Listener; 24 | import com.android.volley.VolleyLog; 25 | 26 | import java.io.UnsupportedEncodingException; 27 | 28 | /** 29 | * A request for retrieving a T type response body at a given URL that also 30 | * optionally sends along a JSON body in the request specified. 31 | * 32 | * @param JSON type of response expected 33 | */ 34 | public abstract class JsonRequest extends Request { 35 | /** Default charset for JSON request. */ 36 | protected static final String PROTOCOL_CHARSET = "utf-8"; 37 | 38 | /** Content type for request. */ 39 | private static final String PROTOCOL_CONTENT_TYPE = 40 | String.format("application/json; charset=%s", PROTOCOL_CHARSET); 41 | 42 | private Listener mListener; 43 | private final String mRequestBody; 44 | 45 | /** 46 | * Deprecated constructor for a JsonRequest which defaults to GET unless {@link #getPostBody()} 47 | * or {@link #getPostParams()} is overridden (which defaults to POST). 48 | * 49 | * @deprecated Use {@link #JsonRequest(int, String, String, Listener, ErrorListener)}. 50 | */ 51 | public JsonRequest(String url, String requestBody, Listener listener, 52 | ErrorListener errorListener) { 53 | this(Method.DEPRECATED_GET_OR_POST, url, requestBody, listener, errorListener); 54 | } 55 | 56 | public JsonRequest(int method, String url, String requestBody, Listener listener, 57 | ErrorListener errorListener) { 58 | super(method, url, errorListener); 59 | mListener = listener; 60 | mRequestBody = requestBody; 61 | } 62 | 63 | @Override 64 | protected void onFinish() { 65 | super.onFinish(); 66 | mListener = null; 67 | } 68 | 69 | @Override 70 | protected void deliverResponse(T response) { 71 | if (mListener != null) { 72 | mListener.onResponse(response); 73 | } 74 | } 75 | 76 | @Override 77 | abstract protected Response parseNetworkResponse(NetworkResponse response); 78 | 79 | /** 80 | * @deprecated Use {@link #getBodyContentType()}. 81 | */ 82 | @Override 83 | public String getPostBodyContentType() { 84 | return getBodyContentType(); 85 | } 86 | 87 | /** 88 | * @deprecated Use {@link #getBody()}. 89 | */ 90 | @Override 91 | public byte[] getPostBody() { 92 | return getBody(); 93 | } 94 | 95 | @Override 96 | public String getBodyContentType() { 97 | return PROTOCOL_CONTENT_TYPE; 98 | } 99 | 100 | @Override 101 | public byte[] getBody() { 102 | try { 103 | return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET); 104 | } catch (UnsupportedEncodingException uee) { 105 | VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", 106 | mRequestBody, PROTOCOL_CHARSET); 107 | return null; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/NetworkDispatcherTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import com.android.volley.mock.MockCache; 20 | import com.android.volley.mock.MockNetwork; 21 | import com.android.volley.mock.MockRequest; 22 | import com.android.volley.mock.MockResponseDelivery; 23 | import com.android.volley.mock.WaitableQueue; 24 | import org.junit.After; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.robolectric.RobolectricTestRunner; 29 | 30 | import java.util.Arrays; 31 | 32 | import static org.junit.Assert.*; 33 | 34 | @RunWith(RobolectricTestRunner.class) 35 | public class NetworkDispatcherTest { 36 | private NetworkDispatcher mDispatcher; 37 | private MockResponseDelivery mDelivery; 38 | private WaitableQueue mNetworkQueue; 39 | private MockNetwork mNetwork; 40 | private MockCache mCache; 41 | private MockRequest mRequest; 42 | 43 | private static final byte[] CANNED_DATA = "Ceci n'est pas une vraie reponse".getBytes(); 44 | private static final long TIMEOUT_MILLIS = 5000; 45 | 46 | @Before public void setUp() throws Exception { 47 | mDelivery = new MockResponseDelivery(); 48 | mNetworkQueue = new WaitableQueue(); 49 | mNetwork = new MockNetwork(); 50 | mCache = new MockCache(); 51 | mRequest = new MockRequest(); 52 | mDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); 53 | mDispatcher.start(); 54 | } 55 | 56 | @After public void tearDown() throws Exception { 57 | mDispatcher.quit(); 58 | mDispatcher.join(); 59 | } 60 | 61 | @Test public void successPostsResponse() throws Exception { 62 | mNetwork.setDataToReturn(CANNED_DATA); 63 | mNetwork.setNumExceptionsToThrow(0); 64 | mNetworkQueue.add(mRequest); 65 | mNetworkQueue.waitUntilEmpty(TIMEOUT_MILLIS); 66 | assertFalse(mDelivery.postError_called); 67 | assertTrue(mDelivery.postResponse_called); 68 | Response response = mDelivery.responsePosted; 69 | assertNotNull(response); 70 | assertTrue(response.isSuccess()); 71 | assertTrue(Arrays.equals((byte[])response.result, CANNED_DATA)); 72 | } 73 | 74 | @Test public void exceptionPostsError() throws Exception { 75 | mNetwork.setNumExceptionsToThrow(MockNetwork.ALWAYS_THROW_EXCEPTIONS); 76 | mNetworkQueue.add(mRequest); 77 | mNetworkQueue.waitUntilEmpty(TIMEOUT_MILLIS); 78 | assertFalse(mDelivery.postResponse_called); 79 | assertTrue(mDelivery.postError_called); 80 | } 81 | 82 | @Test public void shouldCacheFalse() throws Exception { 83 | mRequest.setShouldCache(false); 84 | mNetworkQueue.add(mRequest); 85 | mNetworkQueue.waitUntilEmpty(TIMEOUT_MILLIS); 86 | assertFalse(mCache.putCalled); 87 | } 88 | 89 | @Test public void shouldCacheTrue() throws Exception { 90 | mNetwork.setDataToReturn(CANNED_DATA); 91 | mRequest.setShouldCache(true); 92 | mRequest.setCacheKey("bananaphone"); 93 | mNetworkQueue.add(mRequest); 94 | mNetworkQueue.waitUntilEmpty(TIMEOUT_MILLIS); 95 | assertTrue(mCache.putCalled); 96 | assertNotNull(mCache.entryPut); 97 | assertTrue(Arrays.equals(mCache.entryPut.data, CANNED_DATA)); 98 | assertEquals("bananaphone", mCache.keyPut); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/MockHttpClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.mock; 18 | 19 | import org.apache.http.HttpEntity; 20 | import org.apache.http.HttpHost; 21 | import org.apache.http.HttpRequest; 22 | import org.apache.http.HttpResponse; 23 | import org.apache.http.HttpStatus; 24 | import org.apache.http.ProtocolVersion; 25 | import org.apache.http.StatusLine; 26 | import org.apache.http.client.HttpClient; 27 | import org.apache.http.client.ResponseHandler; 28 | import org.apache.http.client.methods.HttpUriRequest; 29 | import org.apache.http.conn.ClientConnectionManager; 30 | import org.apache.http.message.BasicHttpResponse; 31 | import org.apache.http.message.BasicStatusLine; 32 | import org.apache.http.params.HttpParams; 33 | import org.apache.http.protocol.HttpContext; 34 | 35 | 36 | public class MockHttpClient implements HttpClient { 37 | private int mStatusCode = HttpStatus.SC_OK; 38 | private HttpEntity mResponseEntity = null; 39 | 40 | public void setResponseData(HttpEntity entity) { 41 | mStatusCode = HttpStatus.SC_OK; 42 | mResponseEntity = entity; 43 | } 44 | 45 | public void setErrorCode(int statusCode) { 46 | if (statusCode == HttpStatus.SC_OK) { 47 | throw new IllegalArgumentException("statusCode cannot be 200 for an error"); 48 | } 49 | mStatusCode = statusCode; 50 | } 51 | 52 | public HttpUriRequest requestExecuted = null; 53 | 54 | // This is the only one we actually use. 55 | @Override 56 | public HttpResponse execute(HttpUriRequest request, HttpContext context) { 57 | requestExecuted = request; 58 | StatusLine statusLine = new BasicStatusLine( 59 | new ProtocolVersion("HTTP", 1, 1), mStatusCode, ""); 60 | HttpResponse response = new BasicHttpResponse(statusLine); 61 | response.setEntity(mResponseEntity); 62 | 63 | return response; 64 | } 65 | 66 | 67 | // Unimplemented methods ahoy 68 | 69 | @Override 70 | public HttpResponse execute(HttpUriRequest request) { 71 | throw new UnsupportedOperationException(); 72 | } 73 | 74 | @Override 75 | public HttpResponse execute(HttpHost target, HttpRequest request) { 76 | throw new UnsupportedOperationException(); 77 | } 78 | 79 | @Override 80 | public T execute(HttpUriRequest arg0, ResponseHandler arg1) { 81 | throw new UnsupportedOperationException(); 82 | } 83 | 84 | @Override 85 | public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) { 86 | throw new UnsupportedOperationException(); 87 | } 88 | 89 | @Override 90 | public T execute(HttpUriRequest arg0, ResponseHandler arg1, HttpContext arg2) { 91 | throw new UnsupportedOperationException(); 92 | } 93 | 94 | @Override 95 | public T execute(HttpHost arg0, HttpRequest arg1, ResponseHandler arg2) { 96 | throw new UnsupportedOperationException(); 97 | } 98 | 99 | @Override 100 | public T execute(HttpHost arg0, HttpRequest arg1, ResponseHandler arg2, 101 | HttpContext arg3) { 102 | throw new UnsupportedOperationException(); 103 | } 104 | 105 | @Override 106 | public ClientConnectionManager getConnectionManager() { 107 | throw new UnsupportedOperationException(); 108 | } 109 | 110 | @Override 111 | public HttpParams getParams() { 112 | throw new UnsupportedOperationException(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.AuthFailureError; 20 | 21 | import android.accounts.Account; 22 | import android.accounts.AccountManager; 23 | import android.accounts.AccountManagerFuture; 24 | import android.content.Context; 25 | import android.content.Intent; 26 | import android.os.Bundle; 27 | 28 | /** 29 | * An Authenticator that uses {@link AccountManager} to get auth 30 | * tokens of a specified type for a specified account. 31 | */ 32 | public class AndroidAuthenticator implements Authenticator { 33 | private final AccountManager mAccountManager; 34 | private final Account mAccount; 35 | private final String mAuthTokenType; 36 | private final boolean mNotifyAuthFailure; 37 | 38 | /** 39 | * Creates a new authenticator. 40 | * @param context Context for accessing AccountManager 41 | * @param account Account to authenticate as 42 | * @param authTokenType Auth token type passed to AccountManager 43 | */ 44 | public AndroidAuthenticator(Context context, Account account, String authTokenType) { 45 | this(context, account, authTokenType, false); 46 | } 47 | 48 | /** 49 | * Creates a new authenticator. 50 | * @param context Context for accessing AccountManager 51 | * @param account Account to authenticate as 52 | * @param authTokenType Auth token type passed to AccountManager 53 | * @param notifyAuthFailure Whether to raise a notification upon auth failure 54 | */ 55 | public AndroidAuthenticator(Context context, Account account, String authTokenType, 56 | boolean notifyAuthFailure) { 57 | this(AccountManager.get(context), account, authTokenType, notifyAuthFailure); 58 | } 59 | 60 | // Visible for testing. Allows injection of a mock AccountManager. 61 | AndroidAuthenticator(AccountManager accountManager, Account account, 62 | String authTokenType, boolean notifyAuthFailure) { 63 | mAccountManager = accountManager; 64 | mAccount = account; 65 | mAuthTokenType = authTokenType; 66 | mNotifyAuthFailure = notifyAuthFailure; 67 | } 68 | 69 | /** 70 | * Returns the Account being used by this authenticator. 71 | */ 72 | public Account getAccount() { 73 | return mAccount; 74 | } 75 | 76 | // TODO: Figure out what to do about notifyAuthFailure 77 | @SuppressWarnings("deprecation") 78 | @Override 79 | public String getAuthToken() throws AuthFailureError { 80 | AccountManagerFuture future = mAccountManager.getAuthToken(mAccount, 81 | mAuthTokenType, mNotifyAuthFailure, null, null); 82 | Bundle result; 83 | try { 84 | result = future.getResult(); 85 | } catch (Exception e) { 86 | throw new AuthFailureError("Error while retrieving auth token", e); 87 | } 88 | String authToken = null; 89 | if (future.isDone() && !future.isCancelled()) { 90 | if (result.containsKey(AccountManager.KEY_INTENT)) { 91 | Intent intent = result.getParcelable(AccountManager.KEY_INTENT); 92 | throw new AuthFailureError(intent); 93 | } 94 | authToken = result.getString(AccountManager.KEY_AUTHTOKEN); 95 | } 96 | if (authToken == null) { 97 | throw new AuthFailureError("Got null auth token for type: " + mAuthTokenType); 98 | } 99 | 100 | return authToken; 101 | } 102 | 103 | @Override 104 | public void invalidateAuthToken(String authToken) { 105 | mAccountManager.invalidateAuthToken(mAccount.type, authToken); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/ExecutorDelivery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import android.os.Handler; 20 | 21 | import java.util.concurrent.Executor; 22 | 23 | /** 24 | * Delivers responses and errors. 25 | */ 26 | public class ExecutorDelivery implements ResponseDelivery { 27 | /** Used for posting responses, typically to the main thread. */ 28 | private final Executor mResponsePoster; 29 | 30 | /** 31 | * Creates a new response delivery interface. 32 | * @param handler {@link Handler} to post responses on 33 | */ 34 | public ExecutorDelivery(final Handler handler) { 35 | // Make an Executor that just wraps the handler. 36 | mResponsePoster = new Executor() { 37 | @Override 38 | public void execute(Runnable command) { 39 | handler.post(command); 40 | } 41 | }; 42 | } 43 | 44 | /** 45 | * Creates a new response delivery interface, mockable version 46 | * for testing. 47 | * @param executor For running delivery tasks 48 | */ 49 | public ExecutorDelivery(Executor executor) { 50 | mResponsePoster = executor; 51 | } 52 | 53 | @Override 54 | public void postResponse(Request request, Response response) { 55 | postResponse(request, response, null); 56 | } 57 | 58 | @Override 59 | public void postResponse(Request request, Response response, Runnable runnable) { 60 | request.markDelivered(); 61 | request.addMarker("post-response"); 62 | mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); 63 | } 64 | 65 | @Override 66 | public void postError(Request request, VolleyError error) { 67 | request.addMarker("post-error"); 68 | Response response = Response.error(error); 69 | mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null)); 70 | } 71 | 72 | /** 73 | * A Runnable used for delivering network responses to a listener on the 74 | * main thread. 75 | */ 76 | @SuppressWarnings("rawtypes") 77 | private class ResponseDeliveryRunnable implements Runnable { 78 | private final Request mRequest; 79 | private final Response mResponse; 80 | private final Runnable mRunnable; 81 | 82 | public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) { 83 | mRequest = request; 84 | mResponse = response; 85 | mRunnable = runnable; 86 | } 87 | 88 | @SuppressWarnings("unchecked") 89 | @Override 90 | public void run() { 91 | // If this request has canceled, finish it and don't deliver. 92 | if (mRequest.isCanceled()) { 93 | mRequest.finish("canceled-at-delivery"); 94 | return; 95 | } 96 | 97 | // Deliver a normal response or error, depending. 98 | if (mResponse.isSuccess()) { 99 | mRequest.deliverResponse(mResponse.result); 100 | } else { 101 | mRequest.deliverError(mResponse.error); 102 | } 103 | 104 | // If this is an intermediate response, add a marker, otherwise we're done 105 | // and the request can be finished. 106 | if (mResponse.intermediate) { 107 | mRequest.addMarker("intermediate-response"); 108 | } else { 109 | mRequest.finish("done"); 110 | } 111 | 112 | // If we have been provided a post-delivery runnable, run it. 113 | if (mRunnable != null) { 114 | mRunnable.run(); 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/ImageLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import android.graphics.Bitmap; 20 | import android.widget.ImageView; 21 | import com.android.volley.Request; 22 | import com.android.volley.RequestQueue; 23 | import org.junit.Assert; 24 | import org.junit.Before; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.robolectric.RobolectricTestRunner; 28 | 29 | import static org.junit.Assert.assertNotNull; 30 | import static org.mockito.Mockito.*; 31 | 32 | @RunWith(RobolectricTestRunner.class) 33 | public class ImageLoaderTest { 34 | private RequestQueue mRequestQueue; 35 | private ImageLoader.ImageCache mImageCache; 36 | private ImageLoader mImageLoader; 37 | 38 | @Before 39 | public void setUp() { 40 | mRequestQueue = mock(RequestQueue.class); 41 | mImageCache = mock(ImageLoader.ImageCache.class); 42 | mImageLoader = new ImageLoader(mRequestQueue, mImageCache); 43 | } 44 | 45 | @Test 46 | public void isCachedChecksCache() throws Exception { 47 | when(mImageCache.getBitmap(anyString())).thenReturn(null); 48 | Assert.assertFalse(mImageLoader.isCached("http://foo", 0, 0)); 49 | } 50 | 51 | @Test 52 | public void getWithCacheHit() throws Exception { 53 | Bitmap bitmap = Bitmap.createBitmap(1, 1, null); 54 | ImageLoader.ImageListener listener = mock(ImageLoader.ImageListener.class); 55 | when(mImageCache.getBitmap(anyString())).thenReturn(bitmap); 56 | ImageLoader.ImageContainer ic = mImageLoader.get("http://foo", listener); 57 | Assert.assertSame(bitmap, ic.getBitmap()); 58 | verify(listener).onResponse(ic, true); 59 | } 60 | 61 | @Test 62 | public void getWithCacheMiss() throws Exception { 63 | when(mImageCache.getBitmap(anyString())).thenReturn(null); 64 | ImageLoader.ImageListener listener = mock(ImageLoader.ImageListener.class); 65 | // Ask for the image to be loaded. 66 | mImageLoader.get("http://foo", listener); 67 | // Second pass to test deduping logic. 68 | mImageLoader.get("http://foo", listener); 69 | // Response callback should be called both times. 70 | verify(listener, times(2)).onResponse(any(ImageLoader.ImageContainer.class), eq(true)); 71 | // But request should be enqueued only once. 72 | verify(mRequestQueue, times(1)).add(any(Request.class)); 73 | } 74 | 75 | @Test 76 | public void publicMethods() throws Exception { 77 | // Catch API breaking changes. 78 | ImageLoader.getImageListener(null, -1, -1); 79 | mImageLoader.setBatchedResponseDelay(1000); 80 | 81 | assertNotNull(ImageLoader.class.getConstructor(RequestQueue.class, 82 | ImageLoader.ImageCache.class)); 83 | 84 | assertNotNull(ImageLoader.class.getMethod("getImageListener", ImageView.class, 85 | int.class, int.class)); 86 | assertNotNull(ImageLoader.class.getMethod("isCached", String.class, int.class, int.class)); 87 | assertNotNull(ImageLoader.class.getMethod("isCached", String.class, int.class, int.class, 88 | ImageView.ScaleType.class)); 89 | assertNotNull(ImageLoader.class.getMethod("get", String.class, 90 | ImageLoader.ImageListener.class)); 91 | assertNotNull(ImageLoader.class.getMethod("get", String.class, 92 | ImageLoader.ImageListener.class, int.class, int.class)); 93 | assertNotNull(ImageLoader.class.getMethod("get", String.class, 94 | ImageLoader.ImageListener.class, int.class, int.class, ImageView.ScaleType.class)); 95 | assertNotNull(ImageLoader.class.getMethod("setBatchedResponseDelay", int.class)); 96 | 97 | assertNotNull(ImageLoader.ImageListener.class.getMethod("onResponse", 98 | ImageLoader.ImageContainer.class, boolean.class)); 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/AndroidAuthenticatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 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.android.volley.toolbox; 18 | 19 | import android.accounts.Account; 20 | import android.accounts.AccountManager; 21 | import android.accounts.AccountManagerFuture; 22 | import android.accounts.AuthenticatorException; 23 | import android.content.Context; 24 | import android.content.Intent; 25 | import android.os.Bundle; 26 | import com.android.volley.AuthFailureError; 27 | import org.junit.Assert; 28 | import org.junit.Before; 29 | import org.junit.Ignore; 30 | import org.junit.Test; 31 | import org.junit.runner.RunWith; 32 | import org.mockito.Mock; 33 | import org.mockito.MockitoAnnotations; 34 | import org.robolectric.RobolectricTestRunner; 35 | 36 | import static org.mockito.Mockito.*; 37 | 38 | @RunWith(RobolectricTestRunner.class) 39 | public class AndroidAuthenticatorTest { 40 | private AccountManager mAccountManager; 41 | private Account mAccount; 42 | private AccountManagerFuture mFuture; 43 | private AndroidAuthenticator mAuthenticator; 44 | 45 | @Before 46 | public void setUp() { 47 | mAccountManager = mock(AccountManager.class); 48 | mFuture = mock(AccountManagerFuture.class); 49 | mAccount = new Account("coolperson", "cooltype"); 50 | mAuthenticator = new AndroidAuthenticator(mAccountManager, mAccount, "cooltype", false); 51 | } 52 | 53 | @Test(expected = AuthFailureError.class) 54 | public void failedGetAuthToken() throws Exception { 55 | when(mAccountManager.getAuthToken(mAccount, "cooltype", false, null, null)).thenReturn(mFuture); 56 | when(mFuture.getResult()).thenThrow(new AuthenticatorException("sadness!")); 57 | mAuthenticator.getAuthToken(); 58 | } 59 | 60 | @Test(expected = AuthFailureError.class) 61 | public void resultContainsIntent() throws Exception { 62 | Intent intent = new Intent(); 63 | Bundle bundle = new Bundle(); 64 | bundle.putParcelable(AccountManager.KEY_INTENT, intent); 65 | when(mAccountManager.getAuthToken(mAccount, "cooltype", false, null, null)).thenReturn(mFuture); 66 | when(mFuture.getResult()).thenReturn(bundle); 67 | when(mFuture.isDone()).thenReturn(true); 68 | when(mFuture.isCancelled()).thenReturn(false); 69 | mAuthenticator.getAuthToken(); 70 | } 71 | 72 | @Test(expected = AuthFailureError.class) 73 | public void missingAuthToken() throws Exception { 74 | Bundle bundle = new Bundle(); 75 | when(mAccountManager.getAuthToken(mAccount, "cooltype", false, null, null)).thenReturn(mFuture); 76 | when(mFuture.getResult()).thenReturn(bundle); 77 | when(mFuture.isDone()).thenReturn(true); 78 | when(mFuture.isCancelled()).thenReturn(false); 79 | mAuthenticator.getAuthToken(); 80 | } 81 | 82 | @Test 83 | public void invalidateAuthToken() throws Exception { 84 | mAuthenticator.invalidateAuthToken("monkey"); 85 | verify(mAccountManager).invalidateAuthToken("cooltype", "monkey"); 86 | } 87 | 88 | @Test 89 | public void goodToken() throws Exception { 90 | Bundle bundle = new Bundle(); 91 | bundle.putString(AccountManager.KEY_AUTHTOKEN, "monkey"); 92 | when(mAccountManager.getAuthToken(mAccount, "cooltype", false, null, null)).thenReturn(mFuture); 93 | when(mFuture.getResult()).thenReturn(bundle); 94 | when(mFuture.isDone()).thenReturn(true); 95 | when(mFuture.isCancelled()).thenReturn(false); 96 | Assert.assertEquals("monkey", mAuthenticator.getAuthToken()); 97 | } 98 | 99 | @Test 100 | public void publicMethods() throws Exception { 101 | // Catch-all test to find API-breaking changes. 102 | Context context = mock(Context.class); 103 | new AndroidAuthenticator(context, mAccount, "cooltype"); 104 | new AndroidAuthenticator(context, mAccount, "cooltype", true); 105 | Assert.assertSame(mAccount, mAuthenticator.getAccount()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/RequestFuture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Request; 20 | import com.android.volley.Response; 21 | import com.android.volley.VolleyError; 22 | 23 | import java.util.concurrent.ExecutionException; 24 | import java.util.concurrent.Future; 25 | import java.util.concurrent.TimeUnit; 26 | import java.util.concurrent.TimeoutException; 27 | 28 | /** 29 | * A Future that represents a Volley request. 30 | * 31 | * Used by providing as your response and error listeners. For example: 32 | *
 33 |  * RequestFuture<JSONObject> future = RequestFuture.newFuture();
 34 |  * MyRequest request = new MyRequest(URL, future, future);
 35 |  *
 36 |  * // If you want to be able to cancel the request:
 37 |  * future.setRequest(requestQueue.add(request));
 38 |  *
 39 |  * // Otherwise:
 40 |  * requestQueue.add(request);
 41 |  *
 42 |  * try {
 43 |  *   JSONObject response = future.get();
 44 |  *   // do something with response
 45 |  * } catch (InterruptedException e) {
 46 |  *   // handle the error
 47 |  * } catch (ExecutionException e) {
 48 |  *   // handle the error
 49 |  * }
 50 |  * 
51 | * 52 | * @param The type of parsed response this future expects. 53 | */ 54 | public class RequestFuture implements Future, Response.Listener, 55 | Response.ErrorListener { 56 | private Request mRequest; 57 | private boolean mResultReceived = false; 58 | private T mResult; 59 | private VolleyError mException; 60 | 61 | public static RequestFuture newFuture() { 62 | return new RequestFuture(); 63 | } 64 | 65 | private RequestFuture() {} 66 | 67 | public void setRequest(Request request) { 68 | mRequest = request; 69 | } 70 | 71 | @Override 72 | public synchronized boolean cancel(boolean mayInterruptIfRunning) { 73 | if (mRequest == null) { 74 | return false; 75 | } 76 | 77 | if (!isDone()) { 78 | mRequest.cancel(); 79 | return true; 80 | } else { 81 | return false; 82 | } 83 | } 84 | 85 | @Override 86 | public T get() throws InterruptedException, ExecutionException { 87 | try { 88 | return doGet(null); 89 | } catch (TimeoutException e) { 90 | throw new AssertionError(e); 91 | } 92 | } 93 | 94 | @Override 95 | public T get(long timeout, TimeUnit unit) 96 | throws InterruptedException, ExecutionException, TimeoutException { 97 | return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit)); 98 | } 99 | 100 | private synchronized T doGet(Long timeoutMs) 101 | throws InterruptedException, ExecutionException, TimeoutException { 102 | if (mException != null) { 103 | throw new ExecutionException(mException); 104 | } 105 | 106 | if (mResultReceived) { 107 | return mResult; 108 | } 109 | 110 | if (timeoutMs == null) { 111 | wait(0); 112 | } else if (timeoutMs > 0) { 113 | wait(timeoutMs); 114 | } 115 | 116 | if (mException != null) { 117 | throw new ExecutionException(mException); 118 | } 119 | 120 | if (!mResultReceived) { 121 | throw new TimeoutException(); 122 | } 123 | 124 | return mResult; 125 | } 126 | 127 | @Override 128 | public boolean isCancelled() { 129 | if (mRequest == null) { 130 | return false; 131 | } 132 | return mRequest.isCanceled(); 133 | } 134 | 135 | @Override 136 | public synchronized boolean isDone() { 137 | return mResultReceived || mException != null || isCancelled(); 138 | } 139 | 140 | @Override 141 | public synchronized void onResponse(T response) { 142 | mResultReceived = true; 143 | mResult = response; 144 | notifyAll(); 145 | } 146 | 147 | @Override 148 | public synchronized void onErrorResponse(VolleyError error) { 149 | mException = error; 150 | notifyAll(); 151 | } 152 | } 153 | 154 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/CacheDispatcherTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import com.android.volley.mock.MockCache; 20 | import com.android.volley.mock.MockRequest; 21 | import com.android.volley.mock.MockResponseDelivery; 22 | import com.android.volley.mock.WaitableQueue; 23 | import com.android.volley.utils.CacheTestUtils; 24 | 25 | import org.junit.After; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | import org.junit.runner.RunWith; 29 | import org.robolectric.RobolectricTestRunner; 30 | 31 | import static org.junit.Assert.*; 32 | 33 | @RunWith(RobolectricTestRunner.class) 34 | @SuppressWarnings("rawtypes") 35 | public class CacheDispatcherTest { 36 | private CacheDispatcher mDispatcher; 37 | private WaitableQueue mCacheQueue; 38 | private WaitableQueue mNetworkQueue; 39 | private MockCache mCache; 40 | private MockResponseDelivery mDelivery; 41 | private MockRequest mRequest; 42 | 43 | private static final long TIMEOUT_MILLIS = 5000; 44 | 45 | @Before public void setUp() throws Exception { 46 | mCacheQueue = new WaitableQueue(); 47 | mNetworkQueue = new WaitableQueue(); 48 | mCache = new MockCache(); 49 | mDelivery = new MockResponseDelivery(); 50 | 51 | mRequest = new MockRequest(); 52 | 53 | mDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); 54 | mDispatcher.start(); 55 | } 56 | 57 | @After public void tearDown() throws Exception { 58 | mDispatcher.quit(); 59 | mDispatcher.join(); 60 | } 61 | 62 | // A cancelled request should not be processed at all. 63 | @Test public void cancelledRequest() throws Exception { 64 | mRequest.cancel(); 65 | mCacheQueue.add(mRequest); 66 | mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS); 67 | assertFalse(mCache.getCalled); 68 | assertFalse(mDelivery.wasEitherResponseCalled()); 69 | } 70 | 71 | // A cache miss does not post a response and puts the request on the network queue. 72 | @Test public void cacheMiss() throws Exception { 73 | mCacheQueue.add(mRequest); 74 | mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS); 75 | assertFalse(mDelivery.wasEitherResponseCalled()); 76 | assertTrue(mNetworkQueue.size() > 0); 77 | Request request = mNetworkQueue.take(); 78 | assertNull(request.getCacheEntry()); 79 | } 80 | 81 | // A non-expired cache hit posts a response and does not queue to the network. 82 | @Test public void nonExpiredCacheHit() throws Exception { 83 | Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, false); 84 | mCache.setEntryToReturn(entry); 85 | mCacheQueue.add(mRequest); 86 | mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS); 87 | assertTrue(mDelivery.postResponse_called); 88 | assertFalse(mDelivery.postError_called); 89 | } 90 | 91 | // A soft-expired cache hit posts a response and queues to the network. 92 | @Test public void softExpiredCacheHit() throws Exception { 93 | Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, false, true); 94 | mCache.setEntryToReturn(entry); 95 | mCacheQueue.add(mRequest); 96 | mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS); 97 | assertTrue(mDelivery.postResponse_called); 98 | assertFalse(mDelivery.postError_called); 99 | assertTrue(mNetworkQueue.size() > 0); 100 | Request request = mNetworkQueue.take(); 101 | assertSame(entry, request.getCacheEntry()); 102 | } 103 | 104 | // An expired cache hit does not post a response and queues to the network. 105 | @Test public void expiredCacheHit() throws Exception { 106 | Cache.Entry entry = CacheTestUtils.makeRandomCacheEntry(null, true, true); 107 | mCache.setEntryToReturn(entry); 108 | mCacheQueue.add(mRequest); 109 | mCacheQueue.waitUntilEmpty(TIMEOUT_MILLIS); 110 | assertFalse(mDelivery.wasEitherResponseCalled()); 111 | assertTrue(mNetworkQueue.size() > 0); 112 | Request request = mNetworkQueue.take(); 113 | assertSame(entry, request.getCacheEntry()); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/Volley.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.toolbox; 18 | 19 | import android.content.Context; 20 | import android.content.pm.PackageInfo; 21 | import android.content.pm.PackageManager.NameNotFoundException; 22 | import android.net.http.AndroidHttpClient; 23 | import android.os.Build; 24 | 25 | import com.android.volley.Network; 26 | import com.android.volley.RequestQueue; 27 | 28 | import java.io.File; 29 | 30 | public class Volley { 31 | 32 | /** Default on-disk cache directory. */ 33 | private static final String DEFAULT_CACHE_DIR = "volley"; 34 | 35 | /** 36 | * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. 37 | * You may set a maximum size of the disk cache in bytes. 38 | * 39 | * @param context A {@link Context} to use for creating the cache dir. 40 | * @param stack An {@link HttpStack} to use for the network, or null for default. 41 | * @param maxDiskCacheBytes the maximum size of the disk cache, in bytes. Use -1 for default size. 42 | * @return A started {@link RequestQueue} instance. 43 | */ 44 | public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) { 45 | File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); 46 | 47 | String userAgent = "volley/0"; 48 | try { 49 | String packageName = context.getPackageName(); 50 | PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); 51 | userAgent = packageName + "/" + info.versionCode; 52 | } catch (NameNotFoundException e) { 53 | } 54 | 55 | if (stack == null) { 56 | if (Build.VERSION.SDK_INT >= 9) { 57 | stack = new HurlStack(); 58 | } else { 59 | // Prior to Gingerbread, HttpUrlConnection was unreliable. 60 | // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html 61 | stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); 62 | } 63 | } 64 | 65 | Network network = new BasicNetwork(stack); 66 | 67 | RequestQueue queue; 68 | if (maxDiskCacheBytes <= -1) 69 | { 70 | // No maximum size specified 71 | queue = new RequestQueue(new DiskBasedCache(cacheDir), network); 72 | } 73 | else 74 | { 75 | // Disk cache size specified 76 | queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network); 77 | } 78 | 79 | queue.start(); 80 | 81 | return queue; 82 | } 83 | 84 | /** 85 | * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. 86 | * You may set a maximum size of the disk cache in bytes. 87 | * 88 | * @param context A {@link Context} to use for creating the cache dir. 89 | * @param maxDiskCacheBytes the maximum size of the disk cache, in bytes. Use -1 for default size. 90 | * @return A started {@link RequestQueue} instance. 91 | */ 92 | public static RequestQueue newRequestQueue(Context context, int maxDiskCacheBytes) { 93 | return newRequestQueue(context, null, maxDiskCacheBytes); 94 | } 95 | 96 | /** 97 | * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. 98 | * 99 | * @param context A {@link Context} to use for creating the cache dir. 100 | * @param stack An {@link HttpStack} to use for the network, or null for default. 101 | * @return A started {@link RequestQueue} instance. 102 | */ 103 | public static RequestQueue newRequestQueue(Context context, HttpStack stack) 104 | { 105 | return newRequestQueue(context, stack, -1); 106 | } 107 | 108 | /** 109 | * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. 110 | * 111 | * @param context A {@link Context} to use for creating the cache dir. 112 | * @return A started {@link RequestQueue} instance. 113 | */ 114 | public static RequestQueue newRequestQueue(Context context) { 115 | return newRequestQueue(context, null); 116 | } 117 | 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/JsonObjectRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.ParseError; 21 | import com.android.volley.Response; 22 | import com.android.volley.Response.ErrorListener; 23 | import com.android.volley.Response.Listener; 24 | import org.json.JSONException; 25 | import org.json.JSONObject; 26 | 27 | import java.io.UnsupportedEncodingException; 28 | 29 | /** 30 | * A request for retrieving a {@link JSONObject} response body at a given URL, allowing for an 31 | * optional {@link JSONObject} to be passed in as part of the request body. 32 | */ 33 | public class JsonObjectRequest extends JsonRequest { 34 | 35 | /** 36 | * Creates a new request. 37 | * @param method the HTTP method to use 38 | * @param url URL to fetch the JSON from 39 | * @param requestBody A {@link String} to post with the request. Null is allowed and 40 | * indicates no parameters will be posted along with request. 41 | * @param listener Listener to receive the JSON response 42 | * @param errorListener Error listener, or null to ignore errors. 43 | */ 44 | public JsonObjectRequest(int method, String url, String requestBody, 45 | Listener listener, ErrorListener errorListener) { 46 | super(method, url, requestBody, listener, 47 | errorListener); 48 | } 49 | 50 | /** 51 | * Creates a new request. 52 | * @param url URL to fetch the JSON from 53 | * @param listener Listener to receive the JSON response 54 | * @param errorListener Error listener, or null to ignore errors. 55 | */ 56 | public JsonObjectRequest(String url, Listener listener, ErrorListener errorListener) { 57 | super(Method.GET, url, null, listener, errorListener); 58 | } 59 | 60 | /** 61 | * Creates a new request. 62 | * @param method the HTTP method to use 63 | * @param url URL to fetch the JSON from 64 | * @param listener Listener to receive the JSON response 65 | * @param errorListener Error listener, or null to ignore errors. 66 | */ 67 | public JsonObjectRequest(int method, String url, Listener listener, ErrorListener errorListener) { 68 | super(method, url, null, listener, errorListener); 69 | } 70 | 71 | /** 72 | * Creates a new request. 73 | * @param method the HTTP method to use 74 | * @param url URL to fetch the JSON from 75 | * @param jsonRequest A {@link JSONObject} to post with the request. Null is allowed and 76 | * indicates no parameters will be posted along with request. 77 | * @param listener Listener to receive the JSON response 78 | * @param errorListener Error listener, or null to ignore errors. 79 | */ 80 | public JsonObjectRequest(int method, String url, JSONObject jsonRequest, 81 | Listener listener, ErrorListener errorListener) { 82 | super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, 83 | errorListener); 84 | } 85 | 86 | /** 87 | * Constructor which defaults to GET if jsonRequest is 88 | * null, POST otherwise. 89 | * 90 | * @see #JsonObjectRequest(int, String, JSONObject, Listener, ErrorListener) 91 | */ 92 | public JsonObjectRequest(String url, JSONObject jsonRequest, Listener listener, 93 | ErrorListener errorListener) { 94 | this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, 95 | listener, errorListener); 96 | } 97 | 98 | @Override 99 | protected Response parseNetworkResponse(NetworkResponse response) { 100 | try { 101 | String jsonString = new String(response.data, 102 | HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET)); 103 | return Response.success(new JSONObject(jsonString), 104 | HttpHeaderParser.parseCacheHeaders(response)); 105 | } catch (UnsupportedEncodingException e) { 106 | return Response.error(new ParseError(e)); 107 | } catch (JSONException je) { 108 | return Response.error(new ParseError(je)); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/JsonRequestCharsetTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Response; 21 | import com.android.volley.toolbox.JsonArrayRequest; 22 | import com.android.volley.toolbox.JsonObjectRequest; 23 | 24 | import org.json.JSONArray; 25 | import org.json.JSONObject; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.robolectric.RobolectricTestRunner; 29 | 30 | import java.lang.Exception; 31 | import java.lang.String; 32 | import java.nio.charset.Charset; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | 36 | import static org.junit.Assert.*; 37 | 38 | @RunWith(RobolectricTestRunner.class) 39 | public class JsonRequestCharsetTest { 40 | 41 | /** 42 | * String in Czech - "Retezec v cestine." 43 | */ 44 | private static final String TEXT_VALUE = "\u0158et\u011bzec v \u010de\u0161tin\u011b."; 45 | private static final String TEXT_NAME = "text"; 46 | private static final int TEXT_INDEX = 0; 47 | 48 | /** 49 | * Copyright symbol has different encoding in utf-8 and ISO-8859-1, 50 | * and it doesn't exists in ISO-8859-2 51 | */ 52 | private static final String COPY_VALUE = "\u00a9"; 53 | private static final String COPY_NAME = "copyright"; 54 | private static final int COPY_INDEX = 1; 55 | 56 | @Test public void defaultCharsetJsonObject() throws Exception { 57 | // UTF-8 is default charset for JSON 58 | byte[] data = jsonObjectString().getBytes(Charset.forName("UTF-8")); 59 | NetworkResponse network = new NetworkResponse(data); 60 | JsonObjectRequest objectRequest = new JsonObjectRequest("", null, null, null); 61 | Response objectResponse = objectRequest.parseNetworkResponse(network); 62 | 63 | assertNotNull(objectResponse); 64 | assertTrue(objectResponse.isSuccess()); 65 | assertEquals(TEXT_VALUE, objectResponse.result.getString(TEXT_NAME)); 66 | assertEquals(COPY_VALUE, objectResponse.result.getString(COPY_NAME)); 67 | } 68 | 69 | @Test public void defaultCharsetJsonArray() throws Exception { 70 | // UTF-8 is default charset for JSON 71 | byte[] data = jsonArrayString().getBytes(Charset.forName("UTF-8")); 72 | NetworkResponse network = new NetworkResponse(data); 73 | JsonArrayRequest arrayRequest = new JsonArrayRequest("", null, null); 74 | Response arrayResponse = arrayRequest.parseNetworkResponse(network); 75 | 76 | assertNotNull(arrayResponse); 77 | assertTrue(arrayResponse.isSuccess()); 78 | assertEquals(TEXT_VALUE, arrayResponse.result.getString(TEXT_INDEX)); 79 | assertEquals(COPY_VALUE, arrayResponse.result.getString(COPY_INDEX)); 80 | } 81 | 82 | @Test public void specifiedCharsetJsonObject() throws Exception { 83 | byte[] data = jsonObjectString().getBytes(Charset.forName("ISO-8859-1")); 84 | Map headers = new HashMap(); 85 | headers.put("Content-Type", "application/json; charset=iso-8859-1"); 86 | NetworkResponse network = new NetworkResponse(data, headers); 87 | JsonObjectRequest objectRequest = new JsonObjectRequest("", null, null, null); 88 | Response objectResponse = objectRequest.parseNetworkResponse(network); 89 | 90 | assertNotNull(objectResponse); 91 | assertTrue(objectResponse.isSuccess()); 92 | //don't check the text in Czech, ISO-8859-1 doesn't support some Czech characters 93 | assertEquals(COPY_VALUE, objectResponse.result.getString(COPY_NAME)); 94 | } 95 | 96 | @Test public void specifiedCharsetJsonArray() throws Exception { 97 | byte[] data = jsonArrayString().getBytes(Charset.forName("ISO-8859-2")); 98 | Map headers = new HashMap(); 99 | headers.put("Content-Type", "application/json; charset=iso-8859-2"); 100 | NetworkResponse network = new NetworkResponse(data, headers); 101 | JsonArrayRequest arrayRequest = new JsonArrayRequest("", null, null); 102 | Response arrayResponse = arrayRequest.parseNetworkResponse(network); 103 | 104 | assertNotNull(arrayResponse); 105 | assertTrue(arrayResponse.isSuccess()); 106 | assertEquals(TEXT_VALUE, arrayResponse.result.getString(TEXT_INDEX)); 107 | // don't check the copyright symbol, ISO-8859-2 doesn't have it, but it has Czech characters 108 | } 109 | 110 | private static String jsonObjectString() throws Exception { 111 | JSONObject json = new JSONObject().put(TEXT_NAME, TEXT_VALUE).put(COPY_NAME, COPY_VALUE); 112 | return json.toString(); 113 | } 114 | 115 | private static String jsonArrayString() throws Exception { 116 | JSONArray json = new JSONArray().put(TEXT_INDEX, TEXT_VALUE).put(COPY_INDEX, COPY_VALUE); 117 | return json.toString(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/ByteArrayPool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.toolbox; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.Comparator; 22 | import java.util.LinkedList; 23 | import java.util.List; 24 | 25 | /** 26 | * ByteArrayPool is a source and repository of byte[] objects. Its purpose is to 27 | * supply those buffers to consumers who need to use them for a short period of time and then 28 | * dispose of them. Simply creating and disposing such buffers in the conventional manner can 29 | * considerable heap churn and garbage collection delays on Android, which lacks good management of 30 | * short-lived heap objects. It may be advantageous to trade off some memory in the form of a 31 | * permanently allocated pool of buffers in order to gain heap performance improvements; that is 32 | * what this class does. 33 | *

34 | * A good candidate user for this class is something like an I/O system that uses large temporary 35 | * byte[] buffers to copy data around. In these use cases, often the consumer wants 36 | * the buffer to be a certain minimum size to ensure good performance (e.g. when copying data chunks 37 | * off of a stream), but doesn't mind if the buffer is larger than the minimum. Taking this into 38 | * account and also to maximize the odds of being able to reuse a recycled buffer, this class is 39 | * free to return buffers larger than the requested size. The caller needs to be able to gracefully 40 | * deal with getting buffers any size over the minimum. 41 | *

42 | * If there is not a suitably-sized buffer in its recycling pool when a buffer is requested, this 43 | * class will allocate a new buffer and return it. 44 | *

45 | * This class has no special ownership of buffers it creates; the caller is free to take a buffer 46 | * it receives from this pool, use it permanently, and never return it to the pool; additionally, 47 | * it is not harmful to return to this pool a buffer that was allocated elsewhere, provided there 48 | * are no other lingering references to it. 49 | *

50 | * This class ensures that the total size of the buffers in its recycling pool never exceeds a 51 | * certain byte limit. When a buffer is returned that would cause the pool to exceed the limit, 52 | * least-recently-used buffers are disposed. 53 | */ 54 | public class ByteArrayPool { 55 | /** The buffer pool, arranged both by last use and by buffer size */ 56 | private List mBuffersByLastUse = new LinkedList(); 57 | private List mBuffersBySize = new ArrayList(64); 58 | 59 | /** The total size of the buffers in the pool */ 60 | private int mCurrentSize = 0; 61 | 62 | /** 63 | * The maximum aggregate size of the buffers in the pool. Old buffers are discarded to stay 64 | * under this limit. 65 | */ 66 | private final int mSizeLimit; 67 | 68 | /** Compares buffers by size */ 69 | protected static final Comparator BUF_COMPARATOR = new Comparator() { 70 | @Override 71 | public int compare(byte[] lhs, byte[] rhs) { 72 | return lhs.length - rhs.length; 73 | } 74 | }; 75 | 76 | /** 77 | * @param sizeLimit the maximum size of the pool, in bytes 78 | */ 79 | public ByteArrayPool(int sizeLimit) { 80 | mSizeLimit = sizeLimit; 81 | } 82 | 83 | /** 84 | * Returns a buffer from the pool if one is available in the requested size, or allocates a new 85 | * one if a pooled one is not available. 86 | * 87 | * @param len the minimum size, in bytes, of the requested buffer. The returned buffer may be 88 | * larger. 89 | * @return a byte[] buffer is always returned. 90 | */ 91 | public synchronized byte[] getBuf(int len) { 92 | for (int i = 0; i < mBuffersBySize.size(); i++) { 93 | byte[] buf = mBuffersBySize.get(i); 94 | if (buf.length >= len) { 95 | mCurrentSize -= buf.length; 96 | mBuffersBySize.remove(i); 97 | mBuffersByLastUse.remove(buf); 98 | return buf; 99 | } 100 | } 101 | return new byte[len]; 102 | } 103 | 104 | /** 105 | * Returns a buffer to the pool, throwing away old buffers if the pool would exceed its allotted 106 | * size. 107 | * 108 | * @param buf the buffer to return to the pool. 109 | */ 110 | public synchronized void returnBuf(byte[] buf) { 111 | if (buf == null || buf.length > mSizeLimit) { 112 | return; 113 | } 114 | mBuffersByLastUse.add(buf); 115 | int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR); 116 | if (pos < 0) { 117 | pos = -pos - 1; 118 | } 119 | mBuffersBySize.add(pos, buf); 120 | mCurrentSize += buf.length; 121 | trim(); 122 | } 123 | 124 | /** 125 | * Removes buffers from the pool until it is under its size limit. 126 | */ 127 | private synchronized void trim() { 128 | while (mCurrentSize > mSizeLimit) { 129 | byte[] buf = mBuffersByLastUse.remove(0); 130 | mBuffersBySize.remove(buf); 131 | mCurrentSize -= buf.length; 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/mock/TestRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.mock; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.Request; 21 | import com.android.volley.Response; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | public class TestRequest { 27 | private static final String TEST_URL = "http://foo.com"; 28 | 29 | /** Base Request class for testing allowing both the deprecated and new constructor. */ 30 | private static class Base extends Request { 31 | @SuppressWarnings("deprecation") 32 | public Base(String url, Response.ErrorListener listener) { 33 | super(url, listener); 34 | } 35 | 36 | public Base(int method, String url, Response.ErrorListener listener) { 37 | super(method, url, listener); 38 | } 39 | 40 | @Override 41 | protected Response parseNetworkResponse(NetworkResponse response) { 42 | return null; 43 | } 44 | 45 | @Override 46 | protected void deliverResponse(byte[] response) { 47 | } 48 | } 49 | 50 | /** Test example of a GET request in the deprecated style. */ 51 | public static class DeprecatedGet extends Base { 52 | public DeprecatedGet() { 53 | super(TEST_URL, null); 54 | } 55 | } 56 | 57 | /** Test example of a POST request in the deprecated style. */ 58 | public static class DeprecatedPost extends Base { 59 | private Map mPostParams; 60 | 61 | public DeprecatedPost() { 62 | super(TEST_URL, null); 63 | mPostParams = new HashMap(); 64 | mPostParams.put("requestpost", "foo"); 65 | } 66 | 67 | @Override 68 | protected Map getPostParams() { 69 | return mPostParams; 70 | } 71 | } 72 | 73 | /** Test example of a GET request in the new style. */ 74 | public static class Get extends Base { 75 | public Get() { 76 | super(Method.GET, TEST_URL, null); 77 | } 78 | } 79 | 80 | /** 81 | * Test example of a POST request in the new style. In the new style, it is possible 82 | * to have a POST with no body. 83 | */ 84 | public static class Post extends Base { 85 | public Post() { 86 | super(Method.POST, TEST_URL, null); 87 | } 88 | } 89 | 90 | /** Test example of a POST request in the new style with a body. */ 91 | public static class PostWithBody extends Post { 92 | private Map mParams; 93 | 94 | public PostWithBody() { 95 | mParams = new HashMap(); 96 | mParams.put("testKey", "testValue"); 97 | } 98 | 99 | @Override 100 | public Map getParams() { 101 | return mParams; 102 | } 103 | } 104 | 105 | /** 106 | * Test example of a PUT request in the new style. In the new style, it is possible to have a 107 | * PUT with no body. 108 | */ 109 | public static class Put extends Base { 110 | public Put() { 111 | super(Method.PUT, TEST_URL, null); 112 | } 113 | } 114 | 115 | /** Test example of a PUT request in the new style with a body. */ 116 | public static class PutWithBody extends Put { 117 | private Map mParams = new HashMap(); 118 | 119 | public PutWithBody() { 120 | mParams = new HashMap(); 121 | mParams.put("testKey", "testValue"); 122 | } 123 | 124 | @Override 125 | public Map getParams() { 126 | return mParams; 127 | } 128 | } 129 | 130 | /** Test example of a DELETE request in the new style. */ 131 | public static class Delete extends Base { 132 | public Delete() { 133 | super(Method.DELETE, TEST_URL, null); 134 | } 135 | } 136 | 137 | /** Test example of a HEAD request in the new style. */ 138 | public static class Head extends Base { 139 | public Head() { 140 | super(Method.HEAD, TEST_URL, null); 141 | } 142 | } 143 | 144 | /** Test example of a OPTIONS request in the new style. */ 145 | public static class Options extends Base { 146 | public Options() { 147 | super(Method.OPTIONS, TEST_URL, null); 148 | } 149 | } 150 | 151 | /** Test example of a TRACE request in the new style. */ 152 | public static class Trace extends Base { 153 | public Trace() { 154 | super(Method.TRACE, TEST_URL, null); 155 | } 156 | } 157 | 158 | /** Test example of a PATCH request in the new style. */ 159 | public static class Patch extends Base { 160 | public Patch() { 161 | super(Method.PATCH, TEST_URL, null); 162 | } 163 | } 164 | 165 | /** Test example of a PATCH request in the new style with a body. */ 166 | public static class PatchWithBody extends Patch { 167 | private Map mParams = new HashMap(); 168 | 169 | public PatchWithBody() { 170 | mParams = new HashMap(); 171 | mParams.put("testKey", "testValue"); 172 | } 173 | 174 | @Override 175 | public Map getParams() { 176 | return mParams; 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.android.volley 6 | volley 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | volley 11 | http://android.com 12 | 13 | 14 | UTF-8 15 | 16 | 1.6 17 | 18 | 19 | 20 | 21 | com.google.android 22 | android 23 | 4.1.1.4 24 | 25 | 26 | junit 27 | junit 28 | 4.10 29 | test 30 | 31 | 32 | org.robolectric 33 | robolectric 34 | 2.2 35 | test 36 | 37 | 38 | org.mockito 39 | mockito-core 40 | 1.9.5 41 | test 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | com.jayway.maven.plugins.android.generation2 50 | android-maven-plugin 51 | 3.8.1 52 | 53 | 54 | 19 55 | 56 | 57 | 58 | 59 | 60 | org.apache.maven.plugins 61 | maven-compiler-plugin 62 | 3.0 63 | 64 | ${java.version} 65 | ${java.version} 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | debug 75 | 76 | true 77 | 78 | performDebugBuild 79 | true 80 | 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-surefire-plugin 87 | 2.18.1 88 | 89 | 90 | default-test 91 | 92 | ${surefireArgLine} 93 | 94 | 95 | 96 | 97 | 98 | org.jacoco 99 | jacoco-maven-plugin 100 | 102 | 0.7.2.201409121644 103 | 104 | 105 | pre-unit-test 106 | 107 | prepare-agent 108 | 109 | 110 | ${project.build.directory}/surefire-reports/jacoco-ut.exec 111 | surefireArgLine 112 | 113 | 114 | 115 | jacoco-report 116 | post-integration-test 117 | 118 | report 119 | check 120 | 121 | 122 | ${project.build.directory}/surefire-reports/jacoco-ut.exec 123 | ${project.build.directory}/jacoco-report 124 | 125 | 126 | BUNDLE 127 | 128 | 129 | INSTRUCTION 130 | COVEREDRATIO 131 | 0.40 132 | 133 | 134 | 141 | 142 | 143 | 144 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/JsonArrayRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.NetworkResponse; 20 | import com.android.volley.ParseError; 21 | import com.android.volley.Response; 22 | import com.android.volley.Response.ErrorListener; 23 | import com.android.volley.Response.Listener; 24 | 25 | import org.json.JSONArray; 26 | import org.json.JSONException; 27 | import org.json.JSONObject; 28 | 29 | import java.io.UnsupportedEncodingException; 30 | 31 | /** 32 | * A request for retrieving a {@link JSONArray} response body at a given URL. 33 | */ 34 | public class JsonArrayRequest extends JsonRequest { 35 | 36 | /** 37 | * Creates a new request. 38 | * @param method the HTTP method to use 39 | * @param url URL to fetch the JSON from 40 | * @param requestBody A {@link String} to post with the request. Null is allowed and 41 | * indicates no parameters will be posted along with request. 42 | * @param listener Listener to receive the JSON response 43 | * @param errorListener Error listener, or null to ignore errors. 44 | */ 45 | public JsonArrayRequest(int method, String url, String requestBody, 46 | Listener listener, ErrorListener errorListener) { 47 | super(method, url, requestBody, listener, 48 | errorListener); 49 | } 50 | 51 | /** 52 | * Creates a new request. 53 | * @param url URL to fetch the JSON from 54 | * @param listener Listener to receive the JSON response 55 | * @param errorListener Error listener, or null to ignore errors. 56 | */ 57 | public JsonArrayRequest(String url, Listener listener, ErrorListener errorListener) { 58 | super(Method.GET, url, null, listener, errorListener); 59 | } 60 | 61 | /** 62 | * Creates a new request. 63 | * @param method the HTTP method to use 64 | * @param url URL to fetch the JSON from 65 | * @param listener Listener to receive the JSON response 66 | * @param errorListener Error listener, or null to ignore errors. 67 | */ 68 | public JsonArrayRequest(int method, String url, Listener listener, ErrorListener errorListener) { 69 | super(method, url, null, listener, errorListener); 70 | } 71 | 72 | /** 73 | * Creates a new request. 74 | * @param method the HTTP method to use 75 | * @param url URL to fetch the JSON from 76 | * @param jsonRequest A {@link JSONArray} to post with the request. Null is allowed and 77 | * indicates no parameters will be posted along with request. 78 | * @param listener Listener to receive the JSON response 79 | * @param errorListener Error listener, or null to ignore errors. 80 | */ 81 | public JsonArrayRequest(int method, String url, JSONArray jsonRequest, 82 | Listener listener, ErrorListener errorListener) { 83 | super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, 84 | errorListener); 85 | } 86 | 87 | /** 88 | * Creates a new request. 89 | * @param method the HTTP method to use 90 | * @param url URL to fetch the JSON from 91 | * @param jsonRequest A {@link JSONObject} to post with the request. Null is allowed and 92 | * indicates no parameters will be posted along with request. 93 | * @param listener Listener to receive the JSON response 94 | * @param errorListener Error listener, or null to ignore errors. 95 | */ 96 | public JsonArrayRequest(int method, String url, JSONObject jsonRequest, 97 | Listener listener, ErrorListener errorListener) { 98 | super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, 99 | errorListener); 100 | } 101 | 102 | /** 103 | * Constructor which defaults to GET if jsonRequest is 104 | * null, POST otherwise. 105 | * 106 | * @see #JsonArrayRequest(int, String, JSONArray, Listener, ErrorListener) 107 | */ 108 | public JsonArrayRequest(String url, JSONArray jsonRequest, Listener listener, 109 | ErrorListener errorListener) { 110 | this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, 111 | listener, errorListener); 112 | } 113 | 114 | /** 115 | * Constructor which defaults to GET if jsonRequest is 116 | * null, POST otherwise. 117 | * 118 | * @see #JsonArrayRequest(int, String, JSONObject, Listener, ErrorListener) 119 | */ 120 | public JsonArrayRequest(String url, JSONObject jsonRequest, Listener listener, 121 | ErrorListener errorListener) { 122 | this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, 123 | listener, errorListener); 124 | } 125 | 126 | @Override 127 | protected Response parseNetworkResponse(NetworkResponse response) { 128 | try { 129 | String jsonString = new String(response.data, 130 | HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET)); 131 | return Response.success(new JSONArray(jsonString), 132 | HttpHeaderParser.parseCacheHeaders(response)); 133 | } catch (UnsupportedEncodingException e) { 134 | return Response.error(new ParseError(e)); 135 | } catch (JSONException je) { 136 | return Response.error(new ParseError(je)); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/HttpClientStackTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Request.Method; 20 | import com.android.volley.mock.TestRequest; 21 | import com.android.volley.toolbox.HttpClientStack.HttpPatch; 22 | 23 | import org.apache.http.client.methods.HttpDelete; 24 | import org.apache.http.client.methods.HttpGet; 25 | import org.apache.http.client.methods.HttpHead; 26 | import org.apache.http.client.methods.HttpOptions; 27 | import org.apache.http.client.methods.HttpPost; 28 | import org.apache.http.client.methods.HttpPut; 29 | import org.apache.http.client.methods.HttpTrace; 30 | import org.apache.http.client.methods.HttpUriRequest; 31 | 32 | import org.junit.Test; 33 | import org.junit.runner.RunWith; 34 | import org.robolectric.RobolectricTestRunner; 35 | 36 | import static org.junit.Assert.*; 37 | 38 | @RunWith(RobolectricTestRunner.class) 39 | public class HttpClientStackTest { 40 | 41 | @Test public void createDeprecatedGetRequest() throws Exception { 42 | TestRequest.DeprecatedGet request = new TestRequest.DeprecatedGet(); 43 | assertEquals(request.getMethod(), Method.DEPRECATED_GET_OR_POST); 44 | 45 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 46 | assertTrue(httpRequest instanceof HttpGet); 47 | } 48 | 49 | @Test public void createDeprecatedPostRequest() throws Exception { 50 | TestRequest.DeprecatedPost request = new TestRequest.DeprecatedPost(); 51 | assertEquals(request.getMethod(), Method.DEPRECATED_GET_OR_POST); 52 | 53 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 54 | assertTrue(httpRequest instanceof HttpPost); 55 | } 56 | 57 | @Test public void createGetRequest() throws Exception { 58 | TestRequest.Get request = new TestRequest.Get(); 59 | assertEquals(request.getMethod(), Method.GET); 60 | 61 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 62 | assertTrue(httpRequest instanceof HttpGet); 63 | } 64 | 65 | @Test public void createPostRequest() throws Exception { 66 | TestRequest.Post request = new TestRequest.Post(); 67 | assertEquals(request.getMethod(), Method.POST); 68 | 69 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 70 | assertTrue(httpRequest instanceof HttpPost); 71 | } 72 | 73 | @Test public void createPostRequestWithBody() throws Exception { 74 | TestRequest.PostWithBody request = new TestRequest.PostWithBody(); 75 | assertEquals(request.getMethod(), Method.POST); 76 | 77 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 78 | assertTrue(httpRequest instanceof HttpPost); 79 | } 80 | 81 | @Test public void createPutRequest() throws Exception { 82 | TestRequest.Put request = new TestRequest.Put(); 83 | assertEquals(request.getMethod(), Method.PUT); 84 | 85 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 86 | assertTrue(httpRequest instanceof HttpPut); 87 | } 88 | 89 | @Test public void createPutRequestWithBody() throws Exception { 90 | TestRequest.PutWithBody request = new TestRequest.PutWithBody(); 91 | assertEquals(request.getMethod(), Method.PUT); 92 | 93 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 94 | assertTrue(httpRequest instanceof HttpPut); 95 | } 96 | 97 | @Test public void createDeleteRequest() throws Exception { 98 | TestRequest.Delete request = new TestRequest.Delete(); 99 | assertEquals(request.getMethod(), Method.DELETE); 100 | 101 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 102 | assertTrue(httpRequest instanceof HttpDelete); 103 | } 104 | 105 | @Test public void createHeadRequest() throws Exception { 106 | TestRequest.Head request = new TestRequest.Head(); 107 | assertEquals(request.getMethod(), Method.HEAD); 108 | 109 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 110 | assertTrue(httpRequest instanceof HttpHead); 111 | } 112 | 113 | @Test public void createOptionsRequest() throws Exception { 114 | TestRequest.Options request = new TestRequest.Options(); 115 | assertEquals(request.getMethod(), Method.OPTIONS); 116 | 117 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 118 | assertTrue(httpRequest instanceof HttpOptions); 119 | } 120 | 121 | @Test public void createTraceRequest() throws Exception { 122 | TestRequest.Trace request = new TestRequest.Trace(); 123 | assertEquals(request.getMethod(), Method.TRACE); 124 | 125 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 126 | assertTrue(httpRequest instanceof HttpTrace); 127 | } 128 | 129 | @Test public void createPatchRequest() throws Exception { 130 | TestRequest.Patch request = new TestRequest.Patch(); 131 | assertEquals(request.getMethod(), Method.PATCH); 132 | 133 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 134 | assertTrue(httpRequest instanceof HttpPatch); 135 | } 136 | 137 | @Test public void createPatchRequestWithBody() throws Exception { 138 | TestRequest.PatchWithBody request = new TestRequest.PatchWithBody(); 139 | assertEquals(request.getMethod(), Method.PATCH); 140 | 141 | HttpUriRequest httpRequest = HttpClientStack.createHttpRequest(request, null); 142 | assertTrue(httpRequest instanceof HttpPatch); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/toolbox/HttpHeaderParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Cache; 20 | import com.android.volley.NetworkResponse; 21 | 22 | import org.apache.http.impl.cookie.DateParseException; 23 | import org.apache.http.impl.cookie.DateUtils; 24 | import org.apache.http.protocol.HTTP; 25 | 26 | import java.util.Map; 27 | 28 | /** 29 | * Utility methods for parsing HTTP headers. 30 | */ 31 | public class HttpHeaderParser { 32 | 33 | /** 34 | * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}. 35 | * 36 | * @param response The network response to parse headers from 37 | * @return a cache entry for the given response, or null if the response is not cacheable. 38 | */ 39 | public static Cache.Entry parseCacheHeaders(NetworkResponse response) { 40 | long now = System.currentTimeMillis(); 41 | 42 | Map headers = response.headers; 43 | 44 | long serverDate = 0; 45 | long lastModified = 0; 46 | long serverExpires = 0; 47 | long softExpire = 0; 48 | long finalExpire = 0; 49 | long maxAge = 0; 50 | long staleWhileRevalidate = 0; 51 | boolean hasCacheControl = false; 52 | boolean mustRevalidate = false; 53 | 54 | String serverEtag = null; 55 | String headerValue; 56 | 57 | headerValue = headers.get("Date"); 58 | if (headerValue != null) { 59 | serverDate = parseDateAsEpoch(headerValue); 60 | } 61 | 62 | headerValue = headers.get("Cache-Control"); 63 | if (headerValue != null) { 64 | hasCacheControl = true; 65 | String[] tokens = headerValue.split(","); 66 | for (int i = 0; i < tokens.length; i++) { 67 | String token = tokens[i].trim(); 68 | if (token.equals("no-cache") || token.equals("no-store")) { 69 | return null; 70 | } else if (token.startsWith("max-age=")) { 71 | try { 72 | maxAge = Long.parseLong(token.substring(8)); 73 | } catch (Exception e) { 74 | } 75 | } else if (token.startsWith("stale-while-revalidate=")) { 76 | try { 77 | staleWhileRevalidate = Long.parseLong(token.substring(23)); 78 | } catch (Exception e) { 79 | } 80 | } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) { 81 | mustRevalidate = true; 82 | } 83 | } 84 | } 85 | 86 | headerValue = headers.get("Expires"); 87 | if (headerValue != null) { 88 | serverExpires = parseDateAsEpoch(headerValue); 89 | } 90 | 91 | headerValue = headers.get("Last-Modified"); 92 | if (headerValue != null) { 93 | lastModified = parseDateAsEpoch(headerValue); 94 | } 95 | 96 | serverEtag = headers.get("ETag"); 97 | 98 | // Cache-Control takes precedence over an Expires header, even if both exist and Expires 99 | // is more restrictive. 100 | if (hasCacheControl) { 101 | softExpire = now + maxAge * 1000; 102 | finalExpire = mustRevalidate 103 | ? softExpire 104 | : softExpire + staleWhileRevalidate * 1000; 105 | } else if (serverDate > 0 && serverExpires >= serverDate) { 106 | // Default semantic for Expire header in HTTP specification is softExpire. 107 | softExpire = now + (serverExpires - serverDate); 108 | finalExpire = softExpire; 109 | } 110 | 111 | Cache.Entry entry = new Cache.Entry(); 112 | entry.data = response.data; 113 | entry.etag = serverEtag; 114 | entry.softTtl = softExpire; 115 | entry.ttl = finalExpire; 116 | entry.serverDate = serverDate; 117 | entry.lastModified = lastModified; 118 | entry.responseHeaders = headers; 119 | 120 | return entry; 121 | } 122 | 123 | /** 124 | * Parse date in RFC1123 format, and return its value as epoch 125 | */ 126 | public static long parseDateAsEpoch(String dateStr) { 127 | try { 128 | // Parse date in RFC1123 format if this header contains one 129 | return DateUtils.parseDate(dateStr).getTime(); 130 | } catch (DateParseException e) { 131 | // Date in invalid format, fallback to 0 132 | return 0; 133 | } 134 | } 135 | 136 | /** 137 | * Retrieve a charset from headers 138 | * 139 | * @param headers An {@link java.util.Map} of headers 140 | * @param defaultCharset Charset to return if none can be found 141 | * @return Returns the charset specified in the Content-Type of this header, 142 | * or the defaultCharset if none can be found. 143 | */ 144 | public static String parseCharset(Map headers, String defaultCharset) { 145 | String contentType = headers.get(HTTP.CONTENT_TYPE); 146 | if (contentType != null) { 147 | String[] params = contentType.split(";"); 148 | for (int i = 1; i < params.length; i++) { 149 | String[] pair = params[i].trim().split("="); 150 | if (pair.length == 2) { 151 | if (pair[0].equals("charset")) { 152 | return pair[1]; 153 | } 154 | } 155 | } 156 | } 157 | 158 | return defaultCharset; 159 | } 160 | 161 | /** 162 | * Returns the charset specified in the Content-Type of this header, 163 | * or the HTTP default (ISO-8859-1) if none can be found. 164 | */ 165 | public static String parseCharset(Map headers) { 166 | return parseCharset(headers, HTTP.DEFAULT_CONTENT_CHARSET); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/com/android/volley/NetworkDispatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 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.android.volley; 18 | 19 | import android.annotation.TargetApi; 20 | import android.net.TrafficStats; 21 | import android.os.Build; 22 | import android.os.Process; 23 | import android.os.SystemClock; 24 | 25 | import java.util.concurrent.BlockingQueue; 26 | 27 | /** 28 | * Provides a thread for performing network dispatch from a queue of requests. 29 | * 30 | * Requests added to the specified queue are processed from the network via a 31 | * specified {@link Network} interface. Responses are committed to cache, if 32 | * eligible, using a specified {@link Cache} interface. Valid responses and 33 | * errors are posted back to the caller via a {@link ResponseDelivery}. 34 | */ 35 | public class NetworkDispatcher extends Thread { 36 | /** The queue of requests to service. */ 37 | private final BlockingQueue> mQueue; 38 | /** The network interface for processing requests. */ 39 | private final Network mNetwork; 40 | /** The cache to write to. */ 41 | private final Cache mCache; 42 | /** For posting responses and errors. */ 43 | private final ResponseDelivery mDelivery; 44 | /** Used for telling us to die. */ 45 | private volatile boolean mQuit = false; 46 | 47 | /** 48 | * Creates a new network dispatcher thread. You must call {@link #start()} 49 | * in order to begin processing. 50 | * 51 | * @param queue Queue of incoming requests for triage 52 | * @param network Network interface to use for performing requests 53 | * @param cache Cache interface to use for writing responses to cache 54 | * @param delivery Delivery interface to use for posting responses 55 | */ 56 | public NetworkDispatcher(BlockingQueue> queue, 57 | Network network, Cache cache, 58 | ResponseDelivery delivery) { 59 | mQueue = queue; 60 | mNetwork = network; 61 | mCache = cache; 62 | mDelivery = delivery; 63 | } 64 | 65 | /** 66 | * Forces this dispatcher to quit immediately. If any requests are still in 67 | * the queue, they are not guaranteed to be processed. 68 | */ 69 | public void quit() { 70 | mQuit = true; 71 | interrupt(); 72 | } 73 | 74 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) 75 | private void addTrafficStatsTag(Request request) { 76 | // Tag the request (if API >= 14) 77 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 78 | TrafficStats.setThreadStatsTag(request.getTrafficStatsTag()); 79 | } 80 | } 81 | 82 | @Override 83 | public void run() { 84 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 85 | Request request; 86 | while (true) { 87 | long startTimeMs = SystemClock.elapsedRealtime(); 88 | // release previous request object to avoid leaking request object when mQueue is drained. 89 | request = null; 90 | try { 91 | // Take a request from the queue. 92 | request = mQueue.take(); 93 | } catch (InterruptedException e) { 94 | // We may have been interrupted because it was time to quit. 95 | if (mQuit) { 96 | return; 97 | } 98 | continue; 99 | } 100 | 101 | try { 102 | request.addMarker("network-queue-take"); 103 | 104 | // If the request was cancelled already, do not perform the 105 | // network request. 106 | if (request.isCanceled()) { 107 | request.finish("network-discard-cancelled"); 108 | continue; 109 | } 110 | 111 | addTrafficStatsTag(request); 112 | 113 | // Perform the network request. 114 | NetworkResponse networkResponse = mNetwork.performRequest(request); 115 | request.addMarker("network-http-complete"); 116 | 117 | // If the server returned 304 AND we delivered a response already, 118 | // we're done -- don't deliver a second identical response. 119 | if (networkResponse.notModified && request.hasHadResponseDelivered()) { 120 | request.finish("not-modified"); 121 | continue; 122 | } 123 | 124 | // Parse the response here on the worker thread. 125 | Response response = request.parseNetworkResponse(networkResponse); 126 | request.addMarker("network-parse-complete"); 127 | 128 | // Write to cache if applicable. 129 | // TODO: Only update cache metadata instead of entire record for 304s. 130 | if (request.shouldCache() && response.cacheEntry != null) { 131 | mCache.put(request.getCacheKey(), response.cacheEntry); 132 | request.addMarker("network-cache-written"); 133 | } 134 | 135 | // Post the response back. 136 | request.markDelivered(); 137 | mDelivery.postResponse(request, response); 138 | } catch (VolleyError volleyError) { 139 | volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); 140 | parseAndDeliverNetworkError(request, volleyError); 141 | } catch (Exception e) { 142 | VolleyLog.e(e, "Unhandled exception %s", e.toString()); 143 | VolleyError volleyError = new VolleyError(e); 144 | volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); 145 | mDelivery.postError(request, volleyError); 146 | } 147 | } 148 | } 149 | 150 | private void parseAndDeliverNetworkError(Request request, VolleyError error) { 151 | error = request.parseNetworkError(error); 152 | mDelivery.postError(request, error); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/test/java/com/android/volley/toolbox/DiskBasedCacheTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 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.android.volley.toolbox; 18 | 19 | import com.android.volley.Cache; 20 | import com.android.volley.toolbox.DiskBasedCache.CacheHeader; 21 | import org.junit.Test; 22 | 23 | import java.io.ByteArrayInputStream; 24 | import java.io.ByteArrayOutputStream; 25 | import java.io.File; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | 29 | import static org.junit.Assert.*; 30 | 31 | public class DiskBasedCacheTest { 32 | 33 | // Simple end-to-end serialize/deserialize test. 34 | @Test public void cacheHeaderSerialization() throws Exception { 35 | Cache.Entry e = new Cache.Entry(); 36 | e.data = new byte[8]; 37 | e.serverDate = 1234567L; 38 | e.lastModified = 13572468L; 39 | e.ttl = 9876543L; 40 | e.softTtl = 8765432L; 41 | e.etag = "etag"; 42 | e.responseHeaders = new HashMap(); 43 | e.responseHeaders.put("fruit", "banana"); 44 | 45 | CacheHeader first = new CacheHeader("my-magical-key", e); 46 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 47 | first.writeHeader(baos); 48 | ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 49 | CacheHeader second = CacheHeader.readHeader(bais); 50 | 51 | assertEquals(first.key, second.key); 52 | assertEquals(first.serverDate, second.serverDate); 53 | assertEquals(first.lastModified, second.lastModified); 54 | assertEquals(first.ttl, second.ttl); 55 | assertEquals(first.softTtl, second.softTtl); 56 | assertEquals(first.etag, second.etag); 57 | assertEquals(first.responseHeaders, second.responseHeaders); 58 | } 59 | 60 | @Test public void serializeInt() throws Exception { 61 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 62 | DiskBasedCache.writeInt(baos, 0); 63 | DiskBasedCache.writeInt(baos, 19791214); 64 | DiskBasedCache.writeInt(baos, -20050711); 65 | DiskBasedCache.writeInt(baos, Integer.MIN_VALUE); 66 | DiskBasedCache.writeInt(baos, Integer.MAX_VALUE); 67 | ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 68 | assertEquals(DiskBasedCache.readInt(bais), 0); 69 | assertEquals(DiskBasedCache.readInt(bais), 19791214); 70 | assertEquals(DiskBasedCache.readInt(bais), -20050711); 71 | assertEquals(DiskBasedCache.readInt(bais), Integer.MIN_VALUE); 72 | assertEquals(DiskBasedCache.readInt(bais), Integer.MAX_VALUE); 73 | } 74 | 75 | @Test public void serializeLong() throws Exception { 76 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 77 | DiskBasedCache.writeLong(baos, 0); 78 | DiskBasedCache.writeLong(baos, 31337); 79 | DiskBasedCache.writeLong(baos, -4160); 80 | DiskBasedCache.writeLong(baos, 4295032832L); 81 | DiskBasedCache.writeLong(baos, -4314824046L); 82 | DiskBasedCache.writeLong(baos, Long.MIN_VALUE); 83 | DiskBasedCache.writeLong(baos, Long.MAX_VALUE); 84 | ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 85 | assertEquals(DiskBasedCache.readLong(bais), 0); 86 | assertEquals(DiskBasedCache.readLong(bais), 31337); 87 | assertEquals(DiskBasedCache.readLong(bais), -4160); 88 | assertEquals(DiskBasedCache.readLong(bais), 4295032832L); 89 | assertEquals(DiskBasedCache.readLong(bais), -4314824046L); 90 | assertEquals(DiskBasedCache.readLong(bais), Long.MIN_VALUE); 91 | assertEquals(DiskBasedCache.readLong(bais), Long.MAX_VALUE); 92 | } 93 | 94 | @Test public void serializeString() throws Exception { 95 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 96 | DiskBasedCache.writeString(baos, ""); 97 | DiskBasedCache.writeString(baos, "This is a string."); 98 | DiskBasedCache.writeString(baos, "ファイカス"); 99 | ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 100 | assertEquals(DiskBasedCache.readString(bais), ""); 101 | assertEquals(DiskBasedCache.readString(bais), "This is a string."); 102 | assertEquals(DiskBasedCache.readString(bais), "ファイカス"); 103 | } 104 | 105 | @Test public void serializeMap() throws Exception { 106 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 107 | Map empty = new HashMap(); 108 | DiskBasedCache.writeStringStringMap(empty, baos); 109 | DiskBasedCache.writeStringStringMap(null, baos); 110 | Map twoThings = new HashMap(); 111 | twoThings.put("first", "thing"); 112 | twoThings.put("second", "item"); 113 | DiskBasedCache.writeStringStringMap(twoThings, baos); 114 | Map emptyKey = new HashMap(); 115 | emptyKey.put("", "value"); 116 | DiskBasedCache.writeStringStringMap(emptyKey, baos); 117 | Map emptyValue = new HashMap(); 118 | emptyValue.put("key", ""); 119 | DiskBasedCache.writeStringStringMap(emptyValue, baos); 120 | ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 121 | assertEquals(DiskBasedCache.readStringStringMap(bais), empty); 122 | assertEquals(DiskBasedCache.readStringStringMap(bais), empty); // null reads back empty 123 | assertEquals(DiskBasedCache.readStringStringMap(bais), twoThings); 124 | assertEquals(DiskBasedCache.readStringStringMap(bais), emptyKey); 125 | assertEquals(DiskBasedCache.readStringStringMap(bais), emptyValue); 126 | } 127 | 128 | @Test 129 | public void publicMethods() throws Exception { 130 | // Catch-all test to find API-breaking changes. 131 | assertNotNull(DiskBasedCache.class.getConstructor(File.class, int.class)); 132 | assertNotNull(DiskBasedCache.class.getConstructor(File.class)); 133 | 134 | assertNotNull(DiskBasedCache.class.getMethod("getFileForKey", String.class)); 135 | } 136 | } 137 | --------------------------------------------------------------------------------