├── .github
└── FUNDING.yml
├── .gitignore
├── AndroidAsync-Kotlin
├── .gitignore
├── README.md
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── koushikdutta
│ │ └── async
│ │ └── kotlin
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── koushikdutta
│ │ └── async
│ │ └── kotlin
│ │ └── FutureExtensions.kt
│ └── test
│ └── java
│ └── com
│ └── koushikdutta
│ └── async
│ └── kotlin
│ └── ExampleUnitTest.kt
├── AndroidAsync
├── .classpath
├── Android.mk
├── AndroidManifest.xml
├── build.gradle
├── ic_launcher-web.png
├── lint.xml
├── maven.gradle
├── proguard-project.txt
├── project.properties
├── res
│ └── .gitignore
├── src
│ └── com
│ │ └── koushikdutta
│ │ └── async
│ │ ├── AsyncDatagramSocket.java
│ │ ├── AsyncNetworkSocket.java
│ │ ├── AsyncSSLException.java
│ │ ├── AsyncSSLServerSocket.java
│ │ ├── AsyncSSLSocket.java
│ │ ├── AsyncSSLSocketWrapper.java
│ │ ├── AsyncSemaphore.java
│ │ ├── AsyncServer.java
│ │ ├── AsyncServerSocket.java
│ │ ├── AsyncSocket.java
│ │ ├── BufferedDataSink.java
│ │ ├── ByteBufferList.java
│ │ ├── ChannelWrapper.java
│ │ ├── DataEmitter.java
│ │ ├── DataEmitterBase.java
│ │ ├── DataEmitterReader.java
│ │ ├── DataSink.java
│ │ ├── DataTrackingEmitter.java
│ │ ├── DatagramChannelWrapper.java
│ │ ├── FileDataEmitter.java
│ │ ├── FilteredDataEmitter.java
│ │ ├── FilteredDataSink.java
│ │ ├── HostnameResolutionException.java
│ │ ├── LineEmitter.java
│ │ ├── PushParser.java
│ │ ├── SelectorWrapper.java
│ │ ├── ServerSocketChannelWrapper.java
│ │ ├── SocketChannelWrapper.java
│ │ ├── TapCallback.java
│ │ ├── ThreadQueue.java
│ │ ├── Util.java
│ │ ├── ZipDataSink.java
│ │ ├── callback
│ │ ├── CompletedCallback.java
│ │ ├── ConnectCallback.java
│ │ ├── ContinuationCallback.java
│ │ ├── DataCallback.java
│ │ ├── ListenCallback.java
│ │ ├── ResultCallback.java
│ │ ├── SocketCreateCallback.java
│ │ ├── ValueCallback.java
│ │ ├── ValueFunction.java
│ │ └── WritableCallback.java
│ │ ├── dns
│ │ ├── Dns.java
│ │ └── DnsResponse.java
│ │ ├── future
│ │ ├── Cancellable.java
│ │ ├── Continuation.java
│ │ ├── Converter.java
│ │ ├── DependentCancellable.java
│ │ ├── DependentFuture.java
│ │ ├── DoneCallback.java
│ │ ├── FailCallback.java
│ │ ├── FailConvertCallback.java
│ │ ├── FailRecoverCallback.java
│ │ ├── Future.java
│ │ ├── FutureCallback.java
│ │ ├── FutureRunnable.java
│ │ ├── FutureThread.java
│ │ ├── Futures.java
│ │ ├── HandlerFuture.java
│ │ ├── MultiFuture.java
│ │ ├── MultiTransformFuture.java
│ │ ├── SimpleCancellable.java
│ │ ├── SimpleFuture.java
│ │ ├── SuccessCallback.java
│ │ ├── ThenCallback.java
│ │ ├── ThenFutureCallback.java
│ │ ├── TransformFuture.java
│ │ └── TypeConverter.java
│ │ ├── http
│ │ ├── AsyncHttpClient.java
│ │ ├── AsyncHttpClientMiddleware.java
│ │ ├── AsyncHttpDelete.java
│ │ ├── AsyncHttpGet.java
│ │ ├── AsyncHttpHead.java
│ │ ├── AsyncHttpPost.java
│ │ ├── AsyncHttpPut.java
│ │ ├── AsyncHttpRequest.java
│ │ ├── AsyncHttpResponse.java
│ │ ├── AsyncHttpResponseImpl.java
│ │ ├── AsyncSSLEngineConfigurator.java
│ │ ├── AsyncSSLSocketMiddleware.java
│ │ ├── AsyncSocketMiddleware.java
│ │ ├── BasicNameValuePair.java
│ │ ├── BodyDecoderException.java
│ │ ├── ConnectionClosedException.java
│ │ ├── ConnectionFailedException.java
│ │ ├── Headers.java
│ │ ├── HttpDate.java
│ │ ├── HttpTransportMiddleware.java
│ │ ├── HttpUtil.java
│ │ ├── HybiParser.java
│ │ ├── Multimap.java
│ │ ├── NameValuePair.java
│ │ ├── Protocol.java
│ │ ├── ProtocolVersion.java
│ │ ├── RedirectLimitExceededException.java
│ │ ├── RequestLine.java
│ │ ├── SSLEngineSNIConfigurator.java
│ │ ├── SimpleMiddleware.java
│ │ ├── WebSocket.java
│ │ ├── WebSocketHandshakeException.java
│ │ ├── WebSocketImpl.java
│ │ ├── body
│ │ │ ├── AsyncHttpRequestBody.java
│ │ │ ├── ByteBufferListRequestBody.java
│ │ │ ├── DocumentBody.java
│ │ │ ├── FileBody.java
│ │ │ ├── FilePart.java
│ │ │ ├── JSONArrayBody.java
│ │ │ ├── JSONObjectBody.java
│ │ │ ├── MultipartFormDataBody.java
│ │ │ ├── Part.java
│ │ │ ├── StreamBody.java
│ │ │ ├── StreamPart.java
│ │ │ ├── StringBody.java
│ │ │ ├── StringPart.java
│ │ │ └── UrlEncodedFormBody.java
│ │ ├── cache
│ │ │ ├── HeaderParser.java
│ │ │ ├── Objects.java
│ │ │ ├── RawHeaders.java
│ │ │ ├── RequestHeaders.java
│ │ │ ├── ResponseCacheMiddleware.java
│ │ │ ├── ResponseHeaders.java
│ │ │ ├── ResponseSource.java
│ │ │ └── StrictLineReader.java
│ │ ├── callback
│ │ │ ├── HttpConnectCallback.java
│ │ │ └── RequestCallback.java
│ │ ├── filter
│ │ │ ├── ChunkedDataException.java
│ │ │ ├── ChunkedInputFilter.java
│ │ │ ├── ChunkedOutputFilter.java
│ │ │ ├── ContentLengthFilter.java
│ │ │ ├── DataRemainingException.java
│ │ │ ├── GZIPInputFilter.java
│ │ │ ├── InflaterInputFilter.java
│ │ │ └── PrematureDataEndException.java
│ │ └── server
│ │ │ ├── AsyncHttpRequestBodyProvider.java
│ │ │ ├── AsyncHttpServer.java
│ │ │ ├── AsyncHttpServerRequest.java
│ │ │ ├── AsyncHttpServerRequestImpl.java
│ │ │ ├── AsyncHttpServerResponse.java
│ │ │ ├── AsyncHttpServerResponseImpl.java
│ │ │ ├── AsyncHttpServerRouter.java
│ │ │ ├── AsyncProxyServer.java
│ │ │ ├── BoundaryEmitter.java
│ │ │ ├── HttpServerRequestCallback.java
│ │ │ ├── MalformedRangeException.java
│ │ │ ├── MimeEncodingException.java
│ │ │ ├── RouteMatcher.java
│ │ │ ├── StreamSkipException.java
│ │ │ └── UnknownRequestBody.java
│ │ ├── parser
│ │ ├── AsyncParser.java
│ │ ├── ByteBufferListParser.java
│ │ ├── DocumentParser.java
│ │ ├── JSONArrayParser.java
│ │ ├── JSONObjectParser.java
│ │ └── StringParser.java
│ │ ├── stream
│ │ ├── ByteBufferListInputStream.java
│ │ ├── FileDataSink.java
│ │ ├── InputStreamDataEmitter.java
│ │ ├── OutputStreamDataCallback.java
│ │ └── OutputStreamDataSink.java
│ │ ├── util
│ │ ├── Allocator.java
│ │ ├── ArrayDeque.java
│ │ ├── Charsets.java
│ │ ├── Deque.java
│ │ ├── FileCache.java
│ │ ├── FileUtility.java
│ │ ├── HashList.java
│ │ ├── IdleTimeout.java
│ │ ├── LruCache.java
│ │ ├── StreamUtility.java
│ │ ├── TaggedList.java
│ │ ├── ThrottleTimeout.java
│ │ ├── TimeoutBase.java
│ │ └── UntypedHashtable.java
│ │ └── wrapper
│ │ ├── AsyncSocketWrapper.java
│ │ └── DataEmitterWrapper.java
└── test
│ ├── assets
│ ├── 6691924d7d24237d3b3679310157d640
│ ├── hello.txt
│ └── test.json
│ ├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── raw
│ │ └── keystore.bks
│ └── values
│ │ └── strings.xml
│ └── src
│ └── com
│ └── koushikdutta
│ └── async
│ └── test
│ ├── BodyTests.java
│ ├── ByteUtilTests.java
│ ├── CacheTests.java
│ ├── CallbackTests.java
│ ├── ConscryptTests.java
│ ├── ConvertTests.java
│ ├── DnsTests.java
│ ├── FileCacheTests.java
│ ├── FileTests.java
│ ├── FutureTests.java
│ ├── HttpClientTests.java
│ ├── HttpServerTests.java
│ ├── Issue59.java
│ ├── IssueWithWebSocketFuturesTests.java
│ ├── LineEmitterTests.java
│ ├── Md5.java
│ ├── MultipartTests.java
│ ├── ParserTests.java
│ ├── ProxyTests.java
│ ├── RedirectTests.java
│ ├── SSLTests.java
│ ├── SanityChecks.java
│ ├── TimeoutTests.java
│ ├── TriggerFuture.java
│ └── WebSocketTests.java
├── AndroidAsyncSample
├── AndroidManifest.xml
├── build.gradle
├── ic_launcher-web.png
├── proguard-project.txt
├── project.properties
├── res
│ ├── drawable-hdpi
│ │ ├── ic_action_search.png
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ ├── ic_action_search.png
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ ├── ic_action_search.png
│ │ └── ic_launcher.png
│ ├── layout
│ │ └── activity_main.xml
│ ├── menu
│ │ └── activity_main.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
└── src
│ └── com
│ └── koushikdutta
│ └── async
│ └── sample
│ ├── MainActivity.java
│ └── middleware
│ ├── BasicAuthMiddleware.java
│ └── CacheOverrideMiddleware.java
├── LICENSE
├── README.md
├── build.gradle
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: koush
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | .settings
3 | local.properties
4 | gen
5 | .gradle
6 | build
7 | .idea/
8 | .DS_Store
9 | okhttp/
10 | okio/
11 | libs
12 | *.iml
13 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/README.md:
--------------------------------------------------------------------------------
1 | # Support for Kotlin Coroutines in AndroidAsync and Ion
2 |
3 | Adds coroutines support to AndroidAsync and [Ion](https://github.com/koush/ion).
4 |
5 | Maven:
6 | ```xml
7 |
8 | com.koushikdutta.async
9 | androidasync-kotlin
10 | (insert latest version)
11 |
12 | ```
13 |
14 | Gradle:
15 | ```groovy
16 | dependencies {
17 | compile 'com.koushikdutta.async:androidasync-kotlin:'
18 | }
19 | ```
20 |
21 | Since AndroidAsync and Ion operations all returned futures, you can simply call await() on them within a Kotlin suspend function.
22 |
23 | ```kotlin
24 | suspend fun getTheRobotsTxt() {
25 | val googleRobots = Ion.with(context)
26 | .load("https://google.com/robots.txt")
27 | .asString()
28 | .await()
29 |
30 | val githubRobots = Ion.with(context)
31 | .load("https://github.com/robots.txt")
32 | .asString()
33 | .await()
34 |
35 | return googleRobots + githubRobots
36 | }
37 | ```
38 |
39 | That's it!
40 |
41 | But remember that the await() suspends, so if you want to fetch both robots.txt at the same time:
42 |
43 | ```kotlin
44 | suspend fun getTheRobotsTxt() {
45 | val googleRobots = Ion.with(context)
46 | .load("https://google.com/robots.txt")
47 | .asString()
48 |
49 | val githubRobots = Ion.with(context)
50 | .load("https://github.com/robots.txt")
51 | .asString()
52 |
53 | return googleRobots.await() + githubRobots.await()
54 | }
55 | ```
56 |
57 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | buildscript {
6 | ext.kotlin_version = '1.3.61'
7 | repositories {
8 | mavenCentral()
9 | }
10 | dependencies {
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | }
13 | }
14 |
15 | android {
16 | compileSdkVersion 29
17 | buildToolsVersion "29.0.2"
18 |
19 | kotlinOptions {
20 | apiVersion = "1.3"
21 | languageVersion = "1.3"
22 | }
23 |
24 | compileOptions {
25 | sourceCompatibility 1.8
26 | targetCompatibility 1.8
27 | }
28 |
29 | defaultConfig {
30 | minSdkVersion 14
31 | targetSdkVersion 29
32 |
33 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34 | consumerProguardFiles 'consumer-rules.pro'
35 | }
36 |
37 | buildTypes {
38 | release {
39 | minifyEnabled false
40 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
41 | }
42 | }
43 |
44 | }
45 |
46 | dependencies {
47 | implementation fileTree(dir: 'libs', include: ['*.jar'])
48 | api project(':AndroidAsync:AndroidAsync')
49 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
50 |
51 |
52 | testImplementation 'junit:junit:4.12'
53 | testImplementation 'org.jetbrains.kotlin:kotlin-test-junit:1.3.61'
54 | androidTestImplementation 'androidx.test:runner:1.2.0'
55 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
56 | }
57 |
58 | // upload to maven task
59 | if (false && System.getenv().I_AM_KOUSH == 'true') {
60 | apply from: '/Users/koush/cfg/maven.gradle'
61 | }
62 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync-Kotlin/consumer-rules.pro
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/src/androidTest/java/com/koushikdutta/async/kotlin/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.kotlin
2 |
3 |
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import androidx.test.runner.AndroidJUnit4
6 | import org.junit.Assert.assertEquals
7 | import org.junit.Test
8 | import org.junit.runner.RunWith
9 |
10 | /**
11 | * Instrumented test, which will execute on an Android device.
12 | *
13 | * See [testing documentation](http://d.android.com/tools/testing).
14 | */
15 | @RunWith(AndroidJUnit4::class)
16 | class ExampleInstrumentedTest {
17 | @Test
18 | fun useAppContext() {
19 | // Context of the app under test.
20 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
21 | assertEquals("com.koushikdutta.async.kotlin.test", appContext.packageName)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/src/main/java/com/koushikdutta/async/kotlin/FutureExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.kotlin
2 |
3 | import com.koushikdutta.async.future.Future
4 | import kotlin.coroutines.resume
5 | import kotlin.coroutines.resumeWithException
6 | import kotlin.coroutines.suspendCoroutine
7 |
8 | suspend fun Future.await(): T {
9 | return suspendCoroutine {
10 | this.setCallback { e, result ->
11 | if (e != null)
12 | it.resumeWithException(e)
13 | else
14 | it.resume(result)
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/AndroidAsync-Kotlin/src/test/java/com/koushikdutta/async/kotlin/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.kotlin
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AndroidAsync/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/AndroidAsync/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 := AndroidAsync
22 | LOCAL_SDK_VERSION := 8
23 | LOCAL_SRC_FILES := $(call all-java-files-under, src)
24 |
25 | include $(BUILD_STATIC_JAVA_LIBRARY)
26 |
--------------------------------------------------------------------------------
/AndroidAsync/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/AndroidAsync/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | sourceSets {
5 | main {
6 | manifest.srcFile 'AndroidManifest.xml'
7 |
8 | jniLibs.srcDirs = ['libs/']
9 |
10 | java.srcDirs=['src/'
11 | // , '../conscrypt/'
12 | // , '../compat/'
13 | ]
14 | }
15 | androidTest.java.srcDirs=['test/src/']
16 | androidTest.res.srcDirs=['test/res/']
17 | androidTest.assets.srcDirs=['test/assets/']
18 | }
19 |
20 | lintOptions {
21 | abortOnError false
22 | }
23 |
24 | defaultConfig {
25 | targetSdkVersion 30
26 | minSdkVersion 21
27 |
28 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
29 | }
30 |
31 | compileOptions {
32 | sourceCompatibility 1.8
33 | targetCompatibility 1.8
34 | }
35 |
36 | compileSdkVersion 30
37 | buildToolsVersion '30.0.2'
38 |
39 | dependencies {
40 | // this is only necessary to get compilation working for self signed certificates. dependency isn't added.
41 | compileOnly group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.60'
42 | compileOnly group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.60'
43 |
44 |
45 | testImplementation 'junit:junit:4.12'
46 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
47 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
48 | // for when i wanna test this against gms conscrypt
49 | androidTestImplementation 'com.google.android.gms:play-services-base:17.0.0'
50 | }
51 | }
52 |
53 | apply from: 'maven.gradle'
54 |
--------------------------------------------------------------------------------
/AndroidAsync/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/ic_launcher-web.png
--------------------------------------------------------------------------------
/AndroidAsync/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/AndroidAsync/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 |
22 | -keep class * extends com.koushikdutta.async.TapCallback {
23 | public protected private *;
24 | }
25 |
--------------------------------------------------------------------------------
/AndroidAsync/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-19
15 | android.library=true
16 |
17 |
18 |
--------------------------------------------------------------------------------
/AndroidAsync/res/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/res/.gitignore
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncDatagramSocket.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.IOException;
4 | import java.net.InetSocketAddress;
5 | import java.nio.ByteBuffer;
6 |
7 | public class AsyncDatagramSocket extends AsyncNetworkSocket {
8 | public void disconnect() throws IOException {
9 | socketAddress = null;
10 | ((DatagramChannelWrapper)getChannel()).disconnect();
11 | }
12 |
13 | @Override
14 | public InetSocketAddress getRemoteAddress() {
15 | if (isOpen())
16 | return super.getRemoteAddress();
17 | return ((DatagramChannelWrapper)getChannel()).getRemoteAddress();
18 | }
19 |
20 | public void connect(InetSocketAddress address) throws IOException {
21 | socketAddress = address;
22 | ((DatagramChannelWrapper)getChannel()).mChannel.connect(address);
23 | }
24 |
25 | public void send(final String host, final int port, final ByteBuffer buffer) {
26 | if (getServer().getAffinity() != Thread.currentThread()) {
27 | getServer().run(new Runnable() {
28 | @Override
29 | public void run() {
30 | send(host, port, buffer);
31 | }
32 | });
33 | return;
34 | }
35 |
36 | try {
37 | ((DatagramChannelWrapper)getChannel()).mChannel.send(buffer, new InetSocketAddress(host, port));
38 | }
39 | catch (IOException e) {
40 | // close();
41 | // reportEndPending(e);
42 | // reportClose(e);
43 | }
44 |
45 | }
46 | public void send(final InetSocketAddress address, final ByteBuffer buffer) {
47 | if (getServer().getAffinity() != Thread.currentThread()) {
48 | getServer().run(new Runnable() {
49 | @Override
50 | public void run() {
51 | send(address, buffer);
52 | }
53 | });
54 | return;
55 | }
56 |
57 | try {
58 | int sent = ((DatagramChannelWrapper)getChannel()).mChannel.send(buffer, new InetSocketAddress(address.getHostName(), address.getPort()));
59 | }
60 | catch (IOException e) {
61 | // Log.e("SEND", "send error", e);
62 | // close();
63 | // reportEndPending(e);
64 | // reportClose(e);
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncSSLException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | public class AsyncSSLException extends Exception {
4 | public AsyncSSLException(Throwable cause) {
5 | super("Peer not trusted by any of the system trust managers.", cause);
6 | }
7 | private boolean mIgnore = false;
8 | public void setIgnore(boolean ignore) {
9 | mIgnore = ignore;
10 | }
11 |
12 | public boolean getIgnore() {
13 | return mIgnore;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncSSLServerSocket.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.security.PrivateKey;
4 | import java.security.cert.Certificate;
5 |
6 | public interface AsyncSSLServerSocket extends AsyncServerSocket {
7 | PrivateKey getPrivateKey();
8 | Certificate getCertificate();
9 | }
10 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncSSLSocket.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.security.cert.X509Certificate;
4 |
5 | import javax.net.ssl.SSLEngine;
6 |
7 | public interface AsyncSSLSocket extends AsyncSocket {
8 | public X509Certificate[] getPeerCertificates();
9 | public SSLEngine getSSLEngine();
10 | }
11 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncSemaphore.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.util.concurrent.Semaphore;
4 | import java.util.concurrent.TimeUnit;
5 |
6 | public class AsyncSemaphore {
7 |
8 | Semaphore semaphore = new Semaphore(0);
9 |
10 | public void acquire() throws InterruptedException {
11 | ThreadQueue threadQueue = ThreadQueue.getOrCreateThreadQueue(Thread.currentThread());
12 | AsyncSemaphore last = threadQueue.waiter;
13 | threadQueue.waiter = this;
14 | Semaphore queueSemaphore = threadQueue.queueSemaphore;
15 | try {
16 | if (semaphore.tryAcquire())
17 | return;
18 |
19 | while (true) {
20 | // run the queue
21 | while (true) {
22 | Runnable run = threadQueue.remove();
23 | if (run == null)
24 | break;
25 | // Log.i(LOGTAG, "Pumping for AsyncSemaphore");
26 | run.run();
27 | }
28 |
29 | int permits = Math.max(1, queueSemaphore.availablePermits());
30 | queueSemaphore.acquire(permits);
31 | if (semaphore.tryAcquire())
32 | break;
33 | }
34 | }
35 | finally {
36 | threadQueue.waiter = last;
37 | }
38 | }
39 |
40 | public boolean tryAcquire(long timeout, TimeUnit timeunit) throws InterruptedException {
41 | long timeoutMs = TimeUnit.MILLISECONDS.convert(timeout, timeunit);
42 | ThreadQueue threadQueue = ThreadQueue.getOrCreateThreadQueue(Thread.currentThread());
43 | AsyncSemaphore last = threadQueue.waiter;
44 | threadQueue.waiter = this;
45 | Semaphore queueSemaphore = threadQueue.queueSemaphore;
46 |
47 | try {
48 | if (semaphore.tryAcquire())
49 | return true;
50 |
51 | long start = System.currentTimeMillis();
52 | do {
53 | // run the queue
54 | while (true) {
55 | Runnable run = threadQueue.remove();
56 | if (run == null)
57 | break;
58 | // Log.i(LOGTAG, "Pumping for AsyncSemaphore");
59 | run.run();
60 | }
61 |
62 | int permits = Math.max(1, queueSemaphore.availablePermits());
63 | if (!queueSemaphore.tryAcquire(permits, timeoutMs, TimeUnit.MILLISECONDS))
64 | return false;
65 | if (semaphore.tryAcquire())
66 | return true;
67 | }
68 | while (System.currentTimeMillis() - start < timeoutMs);
69 | return false;
70 | }
71 | finally {
72 | threadQueue.waiter = last;
73 | }
74 | }
75 |
76 | public void release() {
77 | semaphore.release();
78 | ThreadQueue.release(this);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncServerSocket.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | public interface AsyncServerSocket {
4 | public void stop();
5 | public int getLocalPort();
6 | }
7 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/AsyncSocket.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 |
4 | public interface AsyncSocket extends DataEmitter, DataSink {
5 | public AsyncServer getServer();
6 | }
7 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/ChannelWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.nio.ByteBuffer;
6 | import java.nio.channels.ClosedChannelException;
7 | import java.nio.channels.ReadableByteChannel;
8 | import java.nio.channels.ScatteringByteChannel;
9 | import java.nio.channels.SelectionKey;
10 | import java.nio.channels.Selector;
11 | import java.nio.channels.spi.AbstractSelectableChannel;
12 |
13 | abstract class ChannelWrapper implements ReadableByteChannel, ScatteringByteChannel {
14 | private AbstractSelectableChannel mChannel;
15 | ChannelWrapper(AbstractSelectableChannel channel) throws IOException {
16 | channel.configureBlocking(false);
17 | mChannel = channel;
18 | }
19 |
20 | public abstract void shutdownInput();
21 | public abstract void shutdownOutput();
22 |
23 | public abstract boolean isConnected();
24 |
25 | public abstract int write(ByteBuffer src) throws IOException;
26 | public abstract int write(ByteBuffer[] src) throws IOException;
27 |
28 | // register for default events appropriate for this channel
29 | public abstract SelectionKey register(Selector sel) throws ClosedChannelException;
30 |
31 | public SelectionKey register(Selector sel, int ops) throws ClosedChannelException {
32 | return mChannel.register(sel, ops);
33 | }
34 |
35 | public boolean isChunked() {
36 | return false;
37 | }
38 |
39 | @Override
40 | public boolean isOpen() {
41 | return mChannel.isOpen();
42 | }
43 |
44 | @Override
45 | public void close() throws IOException {
46 | mChannel.close();
47 | }
48 |
49 | public abstract int getLocalPort();
50 | public abstract InetAddress getLocalAddress();
51 | public abstract Object getSocket();
52 | }
53 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/DataEmitter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.CompletedCallback;
4 | import com.koushikdutta.async.callback.DataCallback;
5 |
6 | public interface DataEmitter {
7 | void setDataCallback(DataCallback callback);
8 | DataCallback getDataCallback();
9 | boolean isChunked();
10 | void pause();
11 | void resume();
12 | void close();
13 | boolean isPaused();
14 | void setEndCallback(CompletedCallback callback);
15 | CompletedCallback getEndCallback();
16 | AsyncServer getServer();
17 | String charset();
18 | }
19 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/DataEmitterBase.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.CompletedCallback;
4 | import com.koushikdutta.async.callback.DataCallback;
5 |
6 | /**
7 | * Created by koush on 5/27/13.
8 | */
9 | public abstract class DataEmitterBase implements DataEmitter {
10 | private boolean ended;
11 | protected void report(Exception e) {
12 | if (ended)
13 | return;
14 | ended = true;
15 | if (getEndCallback() != null)
16 | getEndCallback().onCompleted(e);
17 | }
18 |
19 | @Override
20 | public final void setEndCallback(CompletedCallback callback) {
21 | endCallback = callback;
22 | }
23 |
24 | CompletedCallback endCallback;
25 | @Override
26 | public final CompletedCallback getEndCallback() {
27 | return endCallback;
28 | }
29 |
30 |
31 | DataCallback mDataCallback;
32 | @Override
33 | public void setDataCallback(DataCallback callback) {
34 | mDataCallback = callback;
35 | }
36 |
37 | @Override
38 | public DataCallback getDataCallback() {
39 | return mDataCallback;
40 | }
41 |
42 | @Override
43 | public String charset() {
44 | return null;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/DataEmitterReader.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.DataCallback;
4 |
5 | public class DataEmitterReader implements com.koushikdutta.async.callback.DataCallback {
6 | DataCallback mPendingRead;
7 | int mPendingReadLength;
8 | ByteBufferList mPendingData = new ByteBufferList();
9 |
10 | public void read(int count, DataCallback callback) {
11 | mPendingReadLength = count;
12 | mPendingRead = callback;
13 | mPendingData.recycle();
14 | }
15 |
16 | private boolean handlePendingData(DataEmitter emitter) {
17 | if (mPendingReadLength > mPendingData.remaining())
18 | return false;
19 |
20 | DataCallback pendingRead = mPendingRead;
21 | mPendingRead = null;
22 | pendingRead.onDataAvailable(emitter, mPendingData);
23 |
24 | return true;
25 | }
26 |
27 | public DataEmitterReader() {
28 | }
29 | @Override
30 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
31 | // if we're registered for data, we must be waiting for a read
32 | do {
33 | int need = Math.min(bb.remaining(), mPendingReadLength - mPendingData.remaining());
34 | bb.get(mPendingData, need);
35 | bb.remaining();
36 | }
37 | while (handlePendingData(emitter) && mPendingRead != null);
38 | bb.remaining();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/DataSink.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.CompletedCallback;
4 | import com.koushikdutta.async.callback.WritableCallback;
5 |
6 | public interface DataSink {
7 | public void write(ByteBufferList bb);
8 | public void setWriteableCallback(WritableCallback handler);
9 | public WritableCallback getWriteableCallback();
10 |
11 | public boolean isOpen();
12 | public void end();
13 | public void setClosedCallback(CompletedCallback handler);
14 | public CompletedCallback getClosedCallback();
15 | public AsyncServer getServer();
16 | }
17 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/DataTrackingEmitter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | /**
4 | * Created by koush on 5/28/13.
5 | */
6 | public interface DataTrackingEmitter extends DataEmitter {
7 | interface DataTracker {
8 | void onData(int totalBytesRead);
9 | }
10 | void setDataTracker(DataTracker tracker);
11 | DataTracker getDataTracker();
12 | int getBytesRead();
13 | void setDataEmitter(DataEmitter emitter);
14 | }
15 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/DatagramChannelWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.net.InetSocketAddress;
6 | import java.nio.ByteBuffer;
7 | import java.nio.channels.ClosedChannelException;
8 | import java.nio.channels.DatagramChannel;
9 | import java.nio.channels.SelectionKey;
10 | import java.nio.channels.Selector;
11 |
12 | class DatagramChannelWrapper extends ChannelWrapper {
13 | DatagramChannel mChannel;
14 |
15 | @Override
16 | public InetAddress getLocalAddress() {
17 | return mChannel.socket().getLocalAddress();
18 | }
19 |
20 | @Override
21 | public int getLocalPort() {
22 | return mChannel.socket().getLocalPort();
23 | }
24 |
25 | InetSocketAddress address;
26 | public InetSocketAddress getRemoteAddress() {
27 | return address;
28 | }
29 |
30 | public void disconnect() throws IOException {
31 | mChannel.disconnect();
32 | }
33 |
34 | DatagramChannelWrapper(DatagramChannel channel) throws IOException {
35 | super(channel);
36 | mChannel = channel;
37 | }
38 | @Override
39 | public int read(ByteBuffer buffer) throws IOException {
40 | if (!isConnected()) {
41 | int position = buffer.position();
42 | address = (InetSocketAddress)mChannel.receive(buffer);
43 | if (address == null)
44 | return -1;
45 | return buffer.position() - position;
46 | }
47 | address = null;
48 | return mChannel.read(buffer);
49 | }
50 | @Override
51 | public boolean isConnected() {
52 | return mChannel.isConnected();
53 | }
54 | @Override
55 | public int write(ByteBuffer src) throws IOException {
56 | return mChannel.write(src);
57 | }
58 | @Override
59 | public int write(ByteBuffer[] src) throws IOException {
60 | return (int)mChannel.write(src);
61 | }
62 | @Override
63 | public SelectionKey register(Selector sel, int ops) throws ClosedChannelException {
64 | return mChannel.register(sel, ops);
65 | }
66 | @Override
67 | public boolean isChunked() {
68 | return true;
69 | }
70 | @Override
71 | public SelectionKey register(Selector sel) throws ClosedChannelException {
72 | return register(sel, SelectionKey.OP_READ);
73 | }
74 |
75 | @Override
76 | public void shutdownOutput() {
77 | }
78 |
79 | @Override
80 | public void shutdownInput() {
81 | }
82 |
83 | @Override
84 | public long read(ByteBuffer[] byteBuffers) throws IOException {
85 | return mChannel.read(byteBuffers);
86 | }
87 |
88 | @Override
89 | public long read(ByteBuffer[] byteBuffers, int i, int i2) throws IOException {
90 | return mChannel.read(byteBuffers, i, i2);
91 | }
92 |
93 | @Override
94 | public Object getSocket() {
95 | return mChannel.socket();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/FileDataEmitter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.DataCallback;
4 | import com.koushikdutta.async.util.StreamUtility;
5 |
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.nio.ByteBuffer;
9 | import java.nio.channels.FileChannel;
10 |
11 | /**
12 | * Created by koush on 5/22/13.
13 | */
14 | public class FileDataEmitter extends DataEmitterBase {
15 | AsyncServer server;
16 | File file;
17 | public FileDataEmitter(AsyncServer server, File file) {
18 | this.server = server;
19 | this.file = file;
20 | paused = !server.isAffinityThread();
21 | if (!paused)
22 | doResume();
23 | }
24 |
25 | DataCallback callback;
26 | @Override
27 | public void setDataCallback(DataCallback callback) {
28 | this.callback = callback;
29 | }
30 |
31 | @Override
32 | public DataCallback getDataCallback() {
33 | return callback;
34 | }
35 |
36 | @Override
37 | public boolean isChunked() {
38 | return false;
39 | }
40 |
41 | boolean paused;
42 | @Override
43 | public void pause() {
44 | paused = true;
45 | }
46 |
47 | @Override
48 | public void resume() {
49 | paused = false;
50 | doResume();
51 | }
52 |
53 | @Override
54 | protected void report(Exception e) {
55 | StreamUtility.closeQuietly(channel);
56 | super.report(e);
57 | }
58 |
59 | ByteBufferList pending = new ByteBufferList();
60 | FileChannel channel;
61 | Runnable pumper = new Runnable() {
62 | @Override
63 | public void run() {
64 | try {
65 | if (channel == null)
66 | channel = new FileInputStream(file).getChannel();
67 | if (!pending.isEmpty()) {
68 | Util.emitAllData(FileDataEmitter.this, pending);
69 | if (!pending.isEmpty())
70 | return;
71 | }
72 | ByteBuffer b;
73 | do {
74 | b = ByteBufferList.obtain(8192);
75 | if (-1 == channel.read(b)) {
76 | report(null);
77 | return;
78 | }
79 | b.flip();
80 | pending.add(b);
81 | Util.emitAllData(FileDataEmitter.this, pending);
82 | }
83 | while (pending.remaining() == 0 && !isPaused());
84 | }
85 | catch (Exception e) {
86 | report(e);
87 | }
88 | }
89 | };
90 |
91 | private void doResume() {
92 | server.post(pumper);
93 | }
94 |
95 | @Override
96 | public boolean isPaused() {
97 | return paused;
98 | }
99 |
100 | @Override
101 | public AsyncServer getServer() {
102 | return server;
103 | }
104 |
105 | @Override
106 | public void close() {
107 | try {
108 | channel.close();
109 | }
110 | catch (Exception e) {
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/FilteredDataEmitter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.CompletedCallback;
4 | import com.koushikdutta.async.callback.DataCallback;
5 | import com.koushikdutta.async.wrapper.DataEmitterWrapper;
6 |
7 | public class FilteredDataEmitter extends DataEmitterBase implements DataEmitter, DataCallback, DataEmitterWrapper, DataTrackingEmitter {
8 | private DataEmitter mEmitter;
9 | @Override
10 | public DataEmitter getDataEmitter() {
11 | return mEmitter;
12 | }
13 |
14 | @Override
15 | public void setDataEmitter(DataEmitter emitter) {
16 | if (mEmitter != null) {
17 | mEmitter.setDataCallback(null);
18 | }
19 | mEmitter = emitter;
20 | mEmitter.setDataCallback(this);
21 | mEmitter.setEndCallback(new CompletedCallback() {
22 | @Override
23 | public void onCompleted(Exception ex) {
24 | report(ex);
25 | }
26 | });
27 | }
28 |
29 | @Override
30 | public int getBytesRead() {
31 | return totalRead;
32 | }
33 |
34 | @Override
35 | public DataTracker getDataTracker() {
36 | return tracker;
37 | }
38 |
39 | @Override
40 | public void setDataTracker(DataTracker tracker) {
41 | this.tracker = tracker;
42 | }
43 |
44 | private DataTracker tracker;
45 | private int totalRead;
46 | @Override
47 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
48 | if (closed) {
49 | // this emitter was closed but for some reason data is still being spewed...
50 | // eat it, nom nom.
51 | bb.recycle();
52 | return;
53 | }
54 | if (bb != null)
55 | totalRead += bb.remaining();
56 | Util.emitAllData(this, bb);
57 | if (bb != null)
58 | totalRead -= bb.remaining();
59 | if (tracker != null && bb != null)
60 | tracker.onData(totalRead);
61 | // if there's data after the emitting, and it is paused... the underlying implementation
62 | // is obligated to cache the byte buffer list.
63 | }
64 |
65 | @Override
66 | public boolean isChunked() {
67 | return mEmitter.isChunked();
68 | }
69 |
70 | @Override
71 | public void pause() {
72 | mEmitter.pause();
73 | }
74 |
75 | @Override
76 | public void resume() {
77 | mEmitter.resume();
78 | }
79 |
80 | @Override
81 | public boolean isPaused() {
82 | return mEmitter.isPaused();
83 | }
84 |
85 | @Override
86 | public AsyncServer getServer() {
87 | return mEmitter.getServer();
88 | }
89 |
90 | boolean closed;
91 | @Override
92 | public void close() {
93 | closed = true;
94 | if (mEmitter != null)
95 | mEmitter.close();
96 | }
97 |
98 | @Override
99 | public String charset() {
100 | if (mEmitter == null)
101 | return null;
102 | return mEmitter.charset();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/FilteredDataSink.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | public class FilteredDataSink extends BufferedDataSink {
4 | public FilteredDataSink(DataSink sink) {
5 | super(sink);
6 | setMaxBuffer(0);
7 | }
8 |
9 | public ByteBufferList filter(ByteBufferList bb) {
10 | return bb;
11 | }
12 |
13 | @Override
14 | protected void onDataAccepted(ByteBufferList bb) {
15 | ByteBufferList filtered = filter(bb);
16 | // filtering may return the same byte buffer, so watch for that.
17 | if (filtered != bb) {
18 | bb.recycle();
19 | filtered.get(bb);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/HostnameResolutionException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | public class HostnameResolutionException extends Exception {
4 | public HostnameResolutionException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/LineEmitter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import com.koushikdutta.async.callback.DataCallback;
4 |
5 | import java.nio.ByteBuffer;
6 | import java.nio.charset.Charset;
7 |
8 | public class LineEmitter implements DataCallback {
9 | public interface StringCallback {
10 | void onStringAvailable(String s);
11 | }
12 |
13 | public LineEmitter() {
14 | this(null);
15 | }
16 |
17 | public LineEmitter(Charset charset) {
18 | this.charset = charset;
19 | }
20 |
21 | Charset charset;
22 |
23 | ByteBufferList data = new ByteBufferList();
24 |
25 | StringCallback mLineCallback;
26 | public void setLineCallback(StringCallback callback) {
27 | mLineCallback = callback;
28 | }
29 |
30 | public StringCallback getLineCallback() {
31 | return mLineCallback;
32 | }
33 |
34 | @Override
35 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
36 | ByteBuffer buffer = ByteBuffer.allocate(bb.remaining());
37 | while (bb.remaining() > 0) {
38 | byte b = bb.get();
39 | if (b == '\n') {
40 | buffer.flip();
41 | data.add(buffer);
42 | mLineCallback.onStringAvailable(data.readString(charset));
43 | data = new ByteBufferList();
44 | return;
45 | }
46 | else {
47 | buffer.put(b);
48 | }
49 | }
50 | buffer.flip();
51 | data.add(buffer);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/SelectorWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.Closeable;
4 | import java.io.IOException;
5 | import java.nio.channels.SelectionKey;
6 | import java.nio.channels.Selector;
7 | import java.util.Set;
8 | import java.util.concurrent.Semaphore;
9 | import java.util.concurrent.TimeUnit;
10 | import java.util.concurrent.atomic.AtomicBoolean;
11 |
12 | /**
13 | * Created by koush on 2/13/14.
14 | */
15 | class SelectorWrapper implements Closeable {
16 | private Selector selector;
17 | public AtomicBoolean isWaking = new AtomicBoolean(false);
18 | Semaphore semaphore = new Semaphore(0);
19 | public Selector getSelector() {
20 | return selector;
21 | }
22 |
23 | public SelectorWrapper(Selector selector) {
24 | this.selector = selector;
25 | }
26 |
27 | public int selectNow() throws IOException {
28 | return selector.selectNow();
29 | }
30 |
31 | public void select() throws IOException {
32 | select(0);
33 | }
34 |
35 | public void select(long timeout) throws IOException {
36 | try {
37 | semaphore.drainPermits();
38 | selector.select(timeout);
39 | }
40 | finally {
41 | semaphore.release(Integer.MAX_VALUE);
42 | }
43 | }
44 |
45 | public Set keys() {
46 | return selector.keys();
47 | }
48 |
49 | public Set selectedKeys() {
50 | return selector.selectedKeys();
51 | }
52 |
53 | @Override
54 | public void close() throws IOException {
55 | selector.close();
56 | }
57 |
58 | public boolean isOpen() {
59 | return selector.isOpen();
60 | }
61 |
62 | public void wakeupOnce() {
63 | // see if it is selecting, ie, can't acquire a permit
64 | boolean selecting = !semaphore.tryAcquire();
65 | selector.wakeup();
66 | // if it was selecting, then the wakeup definitely worked.
67 | if (selecting)
68 | return;
69 |
70 | // now, we NEED to wait for the select to start to forcibly wake it.
71 | if (isWaking.getAndSet(true)) {
72 | selector.wakeup();
73 | return;
74 | }
75 |
76 | try {
77 | waitForSelect();
78 | selector.wakeup();
79 | } finally {
80 | isWaking.set(false);
81 | }
82 | }
83 |
84 | public boolean waitForSelect() {
85 | // try to wake up 10 times
86 | for (int i = 0; i < 100; i++) {
87 | try {
88 | if (semaphore.tryAcquire(10, TimeUnit.MILLISECONDS)) {
89 | // successfully acquiring means the selector is NOT selecting, since select
90 | // will drain all permits.
91 | continue;
92 | }
93 | } catch (InterruptedException e) {
94 | // an InterruptedException means the acquire failed a select is in progress,
95 | // since it holds all permits
96 | return true;
97 | }
98 | }
99 | return false;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/ServerSocketChannelWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.nio.ByteBuffer;
6 | import java.nio.channels.ClosedChannelException;
7 | import java.nio.channels.SelectionKey;
8 | import java.nio.channels.Selector;
9 | import java.nio.channels.ServerSocketChannel;
10 |
11 | class ServerSocketChannelWrapper extends ChannelWrapper {
12 | ServerSocketChannel mChannel;
13 |
14 | @Override
15 | public void shutdownOutput() {
16 | }
17 |
18 | @Override
19 | public void shutdownInput() {
20 | }
21 |
22 | @Override
23 | public InetAddress getLocalAddress() {
24 | return mChannel.socket().getInetAddress();
25 | }
26 |
27 | @Override
28 | public int getLocalPort() {
29 | return mChannel.socket().getLocalPort();
30 | }
31 |
32 | ServerSocketChannelWrapper(ServerSocketChannel channel) throws IOException {
33 | super(channel);
34 | mChannel = channel;
35 | }
36 |
37 | @Override
38 | public int read(ByteBuffer buffer) throws IOException {
39 | final String msg = "Can't read ServerSocketChannel";
40 | throw new IOException(msg);
41 | }
42 |
43 | @Override
44 | public boolean isConnected() {
45 | return false;
46 | }
47 |
48 | @Override
49 | public int write(ByteBuffer src) throws IOException {
50 | final String msg = "Can't write ServerSocketChannel";
51 | throw new IOException(msg);
52 | }
53 |
54 | @Override
55 | public SelectionKey register(Selector sel) throws ClosedChannelException {
56 | return mChannel.register(sel, SelectionKey.OP_ACCEPT);
57 | }
58 |
59 | @Override
60 | public int write(ByteBuffer[] src) throws IOException {
61 | final String msg = "Can't write ServerSocketChannel";
62 | throw new IOException(msg);
63 | }
64 |
65 | @Override
66 | public long read(ByteBuffer[] byteBuffers) throws IOException {
67 | final String msg = "Can't read ServerSocketChannel";
68 | throw new IOException(msg);
69 | }
70 |
71 | @Override
72 | public long read(ByteBuffer[] byteBuffers, int i, int i2) throws IOException {
73 | final String msg = "Can't read ServerSocketChannel";
74 | throw new IOException(msg);
75 | }
76 |
77 | @Override
78 | public Object getSocket() {
79 | return mChannel.socket();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/SocketChannelWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.IOException;
4 | import java.net.InetAddress;
5 | import java.nio.ByteBuffer;
6 | import java.nio.channels.ClosedChannelException;
7 | import java.nio.channels.SelectionKey;
8 | import java.nio.channels.Selector;
9 | import java.nio.channels.SocketChannel;
10 |
11 | class SocketChannelWrapper extends ChannelWrapper {
12 | SocketChannel mChannel;
13 |
14 | @Override
15 | public InetAddress getLocalAddress() {
16 | return mChannel.socket().getLocalAddress();
17 | }
18 |
19 | @Override
20 | public int getLocalPort() {
21 | return mChannel.socket().getLocalPort();
22 | }
23 |
24 | SocketChannelWrapper(SocketChannel channel) throws IOException {
25 | super(channel);
26 | mChannel = channel;
27 | }
28 | @Override
29 | public int read(ByteBuffer buffer) throws IOException {
30 | return mChannel.read(buffer);
31 | }
32 | @Override
33 | public boolean isConnected() {
34 | return mChannel.isConnected();
35 | }
36 | @Override
37 | public int write(ByteBuffer src) throws IOException {
38 | return mChannel.write(src);
39 | }
40 | @Override
41 | public int write(ByteBuffer[] src) throws IOException {
42 | return (int)mChannel.write(src);
43 | }
44 | @Override
45 | public SelectionKey register(Selector sel) throws ClosedChannelException {
46 | return register(sel, SelectionKey.OP_CONNECT);
47 | }
48 |
49 | @Override
50 | public void shutdownOutput() {
51 | try {
52 | mChannel.socket().shutdownOutput();
53 | }
54 | catch (Exception e) {
55 | }
56 | }
57 |
58 | @Override
59 | public void shutdownInput() {
60 | try {
61 | mChannel.socket().shutdownInput();
62 | }
63 | catch (Exception e) {
64 | }
65 | }
66 |
67 | @Override
68 | public long read(ByteBuffer[] byteBuffers) throws IOException {
69 | return mChannel.read(byteBuffers);
70 | }
71 |
72 | @Override
73 | public long read(ByteBuffer[] byteBuffers, int i, int i2) throws IOException {
74 | return mChannel.read(byteBuffers, i, i2);
75 | }
76 |
77 | @Override
78 | public Object getSocket() {
79 | return mChannel.socket();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/TapCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 |
4 | public interface TapCallback {
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/ThreadQueue.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.util.LinkedList;
4 | import java.util.WeakHashMap;
5 | import java.util.concurrent.Semaphore;
6 |
7 | class ThreadQueue extends LinkedList {
8 | final private static WeakHashMap mThreadQueues = new WeakHashMap();
9 |
10 | static ThreadQueue getOrCreateThreadQueue(Thread thread) {
11 | ThreadQueue queue;
12 | synchronized (mThreadQueues) {
13 | queue = mThreadQueues.get(thread);
14 | if (queue == null) {
15 | queue = new ThreadQueue();
16 | mThreadQueues.put(thread, queue);
17 | }
18 | }
19 |
20 | return queue;
21 | }
22 |
23 | static void release(AsyncSemaphore semaphore) {
24 | synchronized (mThreadQueues) {
25 | for (ThreadQueue threadQueue: mThreadQueues.values()) {
26 | if (threadQueue.waiter == semaphore)
27 | threadQueue.queueSemaphore.release();
28 | }
29 | }
30 | }
31 |
32 | AsyncSemaphore waiter;
33 | Semaphore queueSemaphore = new Semaphore(0);
34 |
35 | @Override
36 | public boolean add(Runnable object) {
37 | synchronized (this) {
38 | return super.add(object);
39 | }
40 | }
41 |
42 | @Override
43 | public boolean remove(Object object) {
44 | synchronized (this) {
45 | return super.remove(object);
46 | }
47 | }
48 |
49 | @Override
50 | public Runnable remove() {
51 | synchronized (this) {
52 | if (this.isEmpty())
53 | return null;
54 | return super.remove();
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/ZipDataSink.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.nio.ByteBuffer;
6 | import java.util.zip.ZipEntry;
7 | import java.util.zip.ZipOutputStream;
8 |
9 | import com.koushikdutta.async.callback.CompletedCallback;
10 |
11 | public class ZipDataSink extends FilteredDataSink {
12 | public ZipDataSink(DataSink sink) {
13 | super(sink);
14 | }
15 |
16 | ByteArrayOutputStream bout = new ByteArrayOutputStream();
17 | ZipOutputStream zop = new ZipOutputStream(bout);
18 |
19 | public void putNextEntry(ZipEntry ze) throws IOException {
20 | zop.putNextEntry(ze);
21 | }
22 |
23 | public void closeEntry() throws IOException {
24 | zop.closeEntry();
25 | }
26 |
27 | protected void report(Exception e) {
28 | CompletedCallback closed = getClosedCallback();
29 | if (closed != null)
30 | closed.onCompleted(e);
31 | }
32 |
33 | @Override
34 | public void end() {
35 | try {
36 | zop.close();
37 | }
38 | catch (IOException e) {
39 | report(e);
40 | return;
41 | }
42 | setMaxBuffer(Integer.MAX_VALUE);
43 | write(new ByteBufferList());
44 | super.end();
45 | }
46 |
47 | @Override
48 | public ByteBufferList filter(ByteBufferList bb) {
49 | try {
50 | if (bb != null) {
51 | while (bb.size() > 0) {
52 | ByteBuffer b = bb.remove();
53 | ByteBufferList.writeOutputStream(zop, b);
54 | ByteBufferList.reclaim(b);
55 | }
56 | }
57 | ByteBufferList ret = new ByteBufferList(bout.toByteArray());
58 | bout.reset();
59 | return ret;
60 | }
61 | catch (IOException e) {
62 | report(e);
63 | return null;
64 | }
65 | finally {
66 | if (bb != null)
67 | bb.recycle();
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/CompletedCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | public interface CompletedCallback {
4 | public class NullCompletedCallback implements CompletedCallback {
5 | @Override
6 | public void onCompleted(Exception ex) {
7 |
8 | }
9 | }
10 |
11 | public void onCompleted(Exception ex);
12 | }
13 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/ConnectCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | import com.koushikdutta.async.AsyncSocket;
4 |
5 | public interface ConnectCallback {
6 | public void onConnectCompleted(Exception ex, AsyncSocket socket);
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/ContinuationCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | import com.koushikdutta.async.future.Continuation;
4 |
5 | public interface ContinuationCallback {
6 | public void onContinue(Continuation continuation, CompletedCallback next) throws Exception;
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/DataCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.DataEmitter;
5 |
6 |
7 | public interface DataCallback {
8 | public class NullDataCallback implements DataCallback {
9 | @Override
10 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
11 | bb.recycle();
12 | }
13 | }
14 |
15 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb);
16 | }
17 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/ListenCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | import com.koushikdutta.async.AsyncServerSocket;
4 | import com.koushikdutta.async.AsyncSocket;
5 |
6 |
7 | public interface ListenCallback extends CompletedCallback {
8 | public void onAccepted(AsyncSocket socket);
9 | public void onListening(AsyncServerSocket socket);
10 | }
11 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/ResultCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | public interface ResultCallback {
4 | public void onCompleted(Exception e, S source, T result);
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/SocketCreateCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | import com.koushikdutta.async.AsyncNetworkSocket;
4 |
5 | public interface SocketCreateCallback {
6 | void onSocketCreated(int localPort);
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/ValueCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | /**
4 | * Created by koush on 7/5/16.
5 | */
6 | public interface ValueCallback {
7 | void onResult(T value);
8 | }
9 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/ValueFunction.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | public interface ValueFunction {
4 | T getValue() throws Exception;
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/callback/WritableCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.callback;
2 |
3 | public interface WritableCallback {
4 | public void onWriteable();
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/Cancellable.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface Cancellable {
4 | /**
5 | * Check whether this asynchronous operation completed successfully.
6 | * @return
7 | */
8 | boolean isDone();
9 |
10 | /**
11 | * Check whether this asynchronous operation has been cancelled.
12 | * @return
13 | */
14 | boolean isCancelled();
15 |
16 | /**
17 | * Attempt to cancel this asynchronous operation.
18 | * @return The return value is whether the operation cancelled successfully.
19 | */
20 | boolean cancel();
21 | }
22 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/DependentCancellable.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface DependentCancellable extends Cancellable {
4 | boolean setParent(Cancellable parent);
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/DependentFuture.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface DependentFuture extends Future, DependentCancellable {
4 | }
5 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/DoneCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface DoneCallback {
4 | void done(Exception e, T result) throws Exception;
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/FailCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface FailCallback {
4 | /**
5 | * Callback that is invoked when a future completes with an error.
6 | * The error should be rethrown to pass it along.
7 | * @param e
8 | * @throws Exception
9 | */
10 | void fail(Exception e) throws Exception;
11 | }
12 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/FailConvertCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface FailConvertCallback {
4 | /**
5 | * Callback that is invoked when a future completes with an error.
6 | * The error should be rethrown, or a new value should be returned.
7 | * @param e
8 | * @return
9 | * @throws Exception
10 | */
11 | T fail(Exception e) throws Exception;
12 | }
13 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/FailRecoverCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface FailRecoverCallback {
4 | /**
5 | * Callback that is invoked when a future completes with an error.
6 | * The error should be rethrown, or a new future value should be returned.
7 | * @param e
8 | * @return
9 | * @throws Exception
10 | */
11 | Future fail(Exception e) throws Exception;
12 | }
13 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/Future.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 |
4 | import java.util.concurrent.Executor;
5 |
6 | public interface Future extends Cancellable, java.util.concurrent.Future {
7 | /**
8 | * Set a callback to be invoked when this Future completes.
9 | * @param callback
10 | * @return
11 | */
12 | void setCallback(FutureCallback callback);
13 |
14 | /**
15 | * Set a callback to be invoked when the Future completes
16 | * with an error or a result.
17 | * The existing error or result will be passed down the chain, or a new error
18 | * may be thrown.
19 | * @param done
20 | * @return
21 | */
22 | Future done(DoneCallback done);
23 |
24 | /**
25 | * Set a callback to be invoked when this Future completes successfully.
26 | * @param callback
27 | * @return A future that will resolve once the success callback completes,
28 | * which may contain any errors thrown by the success callback.
29 | */
30 | Future success(SuccessCallback callback);
31 |
32 | /**
33 | * Set a callback to be invoked when this Future completes successfully.
34 | * @param then
35 | * @param
36 | * @return A future containing all exceptions that happened prior or during
37 | * the callback, or the successful result.
38 | */
39 | Future then(ThenFutureCallback then);
40 |
41 | /**
42 | * Set a callback to be invoked when this Future completes successfully.
43 | * @param then
44 | * @param
45 | * @return A future containing all exceptions that happened prior or during
46 | * the callback, or the successful result.
47 | */
48 | Future thenConvert(ThenCallback then);
49 |
50 | /**
51 | * Set a callback to be invoked when this future completes with a failure.
52 | * The failure can be observered and rethrown, otherwise it is considered handled.
53 | * The exception will be nulled for subsequent callbacks in the chain.
54 | * @param fail
55 | * @return
56 | */
57 | Future fail(FailCallback fail);
58 |
59 | /**
60 | * Set a callback to be invoked when this future completes with a failure.
61 | * The failure can be observered and rethrown, or handled by returning
62 | * a new fallback value of the same type.
63 | * @param fail
64 | * @return
65 | */
66 | Future failConvert(FailConvertCallback fail);
67 |
68 | /**
69 | * Set a callback to be invoked when this future completes with a failure.
70 | * The failure should be observered and rethrown, or handled by returning
71 | * a new future of the same type.
72 | * @param fail
73 | * @return
74 | */
75 | Future failRecover(FailRecoverCallback fail);
76 |
77 | /**
78 | * Get the result, if any. Returns null if still in progress.
79 | * @return
80 | */
81 | T tryGet();
82 |
83 | /**
84 | * Get the exception, if any. Returns null if still in progress.
85 | * @return
86 | */
87 | Exception tryGetException();
88 |
89 | /**
90 | * Get the result on the executor thread.
91 | * @param executor
92 | * @return
93 | */
94 | default Future executorThread(Executor executor) {
95 | SimpleFuture ret = new SimpleFuture<>();
96 | executor.execute(() -> ret.setComplete(Future.this));
97 | return ret;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/FutureCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | /**
4 | * Created by koush on 5/20/13.
5 | */
6 | public interface FutureCallback {
7 | /**
8 | * onCompleted is called by the Future with the result or exception of the asynchronous operation.
9 | * @param e Exception encountered by the operation
10 | * @param result Result returned from the operation
11 | */
12 | public void onCompleted(Exception e, T result);
13 | }
14 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/FutureRunnable.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | /**
4 | * Created by koush on 12/22/13.
5 | */
6 | public interface FutureRunnable {
7 | T run() throws Exception;
8 | }
9 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/FutureThread.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | import java.util.concurrent.ExecutorService;
4 |
5 | /**
6 | * Created by koush on 12/22/13.
7 | */
8 | public class FutureThread extends SimpleFuture {
9 | public FutureThread(final FutureRunnable runnable) {
10 | this(runnable, "FutureThread");
11 | }
12 |
13 | public FutureThread(final ExecutorService pool, final FutureRunnable runnable) {
14 | pool.submit(new Runnable() {
15 | @Override
16 | public void run() {
17 | try {
18 | setComplete(runnable.run());
19 | }
20 | catch (Exception e) {
21 | setComplete(e);
22 | }
23 | }
24 | });
25 | }
26 |
27 | public FutureThread(final FutureRunnable runnable, String name) {
28 | new Thread(new Runnable() {
29 | @Override
30 | public void run() {
31 | try {
32 | setComplete(runnable.run());
33 | }
34 | catch (Exception e) {
35 | setComplete(e);
36 | }
37 | }
38 | }, name).start();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/Futures.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Collection;
6 | import java.util.Iterator;
7 | import java.util.List;
8 |
9 | public class Futures {
10 | public static Future> waitAll(final List> futures) {
11 | final ArrayList results = new ArrayList<>();
12 | final SimpleFuture> ret = new SimpleFuture<>();
13 |
14 | if (futures.isEmpty()) {
15 | ret.setComplete(results);
16 | return ret;
17 | }
18 |
19 | FutureCallback cb = new FutureCallback() {
20 | int count = 0;
21 |
22 | @Override
23 | public void onCompleted(Exception e, T result) {
24 | results.add(result);
25 | count++;
26 | if (count < futures.size())
27 | futures.get(count).setCallback(this);
28 | else
29 | ret.setComplete(results);
30 | }
31 | };
32 |
33 | futures.get(0).setCallback(cb);
34 |
35 | return ret;
36 | }
37 |
38 | public static Future> waitAll(final Future... futures) {
39 | return waitAll(Arrays.asList(futures));
40 | }
41 |
42 |
43 | private static void loopUntil(final Iterator values, ThenFutureCallback callback, SimpleFuture ret, Exception lastException) {
44 | while (values.hasNext()) {
45 | try {
46 | callback.then(values.next())
47 | .success(ret::setComplete)
48 | .fail(e -> loopUntil(values, callback, ret, e));
49 | return;
50 | } catch (Exception e) {
51 | lastException = e;
52 | }
53 | }
54 |
55 | if (lastException == null)
56 | ret.setComplete(new Exception("empty list"));
57 | else
58 | ret.setComplete(lastException);
59 | }
60 |
61 | public static Future loopUntil(final Iterable values, ThenFutureCallback callback) {
62 | SimpleFuture ret = new SimpleFuture<>();
63 | loopUntil(values.iterator(), callback, ret, null);
64 | return ret;
65 | }
66 |
67 | public static Future loopUntil(final F[] values, ThenFutureCallback callback) {
68 | return loopUntil(Arrays.asList(values), callback);
69 | }
70 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/HandlerFuture.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | /**
7 | * Created by koush on 12/25/13.
8 | */
9 | public class HandlerFuture extends SimpleFuture {
10 | Handler handler;
11 |
12 | public HandlerFuture() {
13 | Looper looper = Looper.myLooper();
14 | if (looper == null)
15 | looper = Looper.getMainLooper();
16 | handler = new Handler(looper);
17 | }
18 |
19 | @Override
20 | public void setCallback(final FutureCallback callback) {
21 | FutureCallback wrapped = new FutureCallback() {
22 | @Override
23 | public void onCompleted(final Exception e, final T result) {
24 | if (Looper.myLooper() == handler.getLooper()) {
25 | callback.onCompleted(e, result);
26 | return;
27 | }
28 |
29 | handler.post(new Runnable() {
30 | @Override
31 | public void run() {
32 | onCompleted(e, result);
33 | }
34 | });
35 | }
36 | };
37 | super.setCallback(wrapped);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/MultiFuture.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * Created by koush on 2/25/14.
7 | */
8 | public class MultiFuture extends SimpleFuture {
9 | private ArrayList> internalCallbacks;
10 |
11 | public MultiFuture() {
12 | }
13 |
14 | public MultiFuture(T value) {
15 | super(value);
16 | }
17 |
18 | public MultiFuture(Exception e) {
19 | super(e);
20 | }
21 |
22 | public MultiFuture(Future future) {
23 | super(future);
24 | }
25 |
26 | private final FutureCallbackInternal internalCallback = (e, result, callsite) -> {
27 | ArrayList> callbacks;
28 | synchronized (MultiFuture.this) {
29 | callbacks = MultiFuture.this.internalCallbacks;
30 | MultiFuture.this.internalCallbacks = null;
31 | }
32 |
33 | if (callbacks == null)
34 | return;
35 | for (FutureCallbackInternal cb : callbacks) {
36 | cb.onCompleted(e, result, callsite);
37 | }
38 | };
39 |
40 | @Override
41 | protected void setCallbackInternal(FutureCallsite callsite, FutureCallbackInternal internalCallback) {
42 | synchronized (this) {
43 | if (internalCallback != null) {
44 | if (internalCallbacks == null)
45 | internalCallbacks = new ArrayList<>();
46 | internalCallbacks.add(internalCallback);
47 | }
48 | }
49 | // so, there is a race condition where this internal callback could get
50 | // executed twice, if two callbacks are added at the same time.
51 | // however, it doesn't matter, as the actual retrieval and nulling
52 | // of the callback list is done in another sync block.
53 | // one of the invocations will actually invoke all the callbacks,
54 | // while the other will not get a list back.
55 |
56 | // race:
57 | // 1-ADD
58 | // 2-ADD
59 | // 1-INVOKE LIST
60 | // 2-INVOKE NULL
61 |
62 | super.setCallbackInternal(callsite, this.internalCallback);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/MultiTransformFuture.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public abstract class MultiTransformFuture extends MultiFuture implements FutureCallback {
4 | @Override
5 | public void onCompleted(Exception e, F result) {
6 | if (isCancelled())
7 | return;
8 | if (e != null) {
9 | error(e);
10 | return;
11 | }
12 |
13 | try {
14 | transform(result);
15 | }
16 | catch (Exception ex) {
17 | error(ex);
18 | }
19 | }
20 |
21 | protected void error(Exception e) {
22 | setComplete(e);
23 | }
24 |
25 | protected abstract void transform(F result) throws Exception;
26 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/SimpleCancellable.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public class SimpleCancellable implements DependentCancellable {
4 | boolean complete;
5 | @Override
6 | public boolean isDone() {
7 | return complete;
8 | }
9 |
10 | protected void cancelCleanup() {
11 | }
12 |
13 | protected void cleanup() {
14 | }
15 |
16 | protected void completeCleanup() {
17 | }
18 |
19 | public boolean setComplete() {
20 | synchronized (this) {
21 | if (cancelled)
22 | return false;
23 | if (complete) {
24 | // don't allow a Cancellable to complete twice...
25 | return false;
26 | }
27 | complete = true;
28 | parent = null;
29 | }
30 | completeCleanup();
31 | cleanup();
32 | return true;
33 | }
34 |
35 | @Override
36 | public boolean cancel() {
37 | Cancellable parent;
38 | synchronized (this) {
39 | if (complete)
40 | return false;
41 | if (cancelled)
42 | return true;
43 | cancelled = true;
44 | parent = this.parent;
45 | // null out the parent to allow garbage collection
46 | this.parent = null;
47 | }
48 | if (parent != null)
49 | parent.cancel();
50 | cancelCleanup();
51 | cleanup();
52 | return true;
53 | }
54 | boolean cancelled;
55 |
56 | private Cancellable parent;
57 | @Override
58 | public boolean setParent(Cancellable parent) {
59 | synchronized (this) {
60 | if (isDone())
61 | return false;
62 | this.parent = parent;
63 | return true;
64 | }
65 | }
66 |
67 | @Override
68 | public boolean isCancelled() {
69 | synchronized (this) {
70 | return cancelled || (parent != null && parent.isCancelled());
71 | }
72 | }
73 |
74 | public static final Cancellable COMPLETED = new SimpleCancellable() {
75 | {
76 | setComplete();
77 | }
78 | };
79 |
80 | public static final Cancellable CANCELLED = new SimpleCancellable() {
81 | {
82 | cancel();
83 | }
84 | };
85 |
86 | public Cancellable reset() {
87 | cancel();
88 | complete = false;
89 | cancelled = false;
90 | return this;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/SuccessCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface SuccessCallback {
4 | void success(T value) throws Exception;
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/ThenCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface ThenCallback {
4 | /**
5 | * Callback that is invoked when Future.then completes,
6 | * and converts a value F to value T.
7 | * @param from
8 | * @return
9 | * @throws Exception
10 | */
11 | T then(F from) throws Exception;
12 | }
13 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/ThenFutureCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface ThenFutureCallback {
4 | /**
5 | * Callback that is invoked when Future.then completes,
6 | * and converts a value F to a Future.
7 | * @param from
8 | * @return
9 | * @throws Exception
10 | */
11 | Future then(F from) throws Exception;
12 | }
13 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/TransformFuture.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public abstract class TransformFuture extends SimpleFuture implements FutureCallback {
4 | public TransformFuture(F from) {
5 | onCompleted(null, from);
6 | }
7 |
8 | public TransformFuture() {
9 | }
10 |
11 | @Override
12 | public void onCompleted(Exception e, F result) {
13 | if (isCancelled())
14 | return;
15 | if (e != null) {
16 | error(e);
17 | return;
18 | }
19 |
20 | try {
21 | transform(result);
22 | }
23 | catch (Exception ex) {
24 | error(ex);
25 | }
26 | }
27 |
28 | protected void error(Exception e) {
29 | setComplete(e);
30 | }
31 |
32 | protected abstract void transform(F result) throws Exception;
33 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/future/TypeConverter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.future;
2 |
3 | public interface TypeConverter {
4 | Future convert(F from, String fromMime) throws Exception;
5 | }
6 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpDelete.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import android.net.Uri;
4 |
5 | public class AsyncHttpDelete extends AsyncHttpRequest {
6 | public static final String METHOD = "DELETE";
7 |
8 | public AsyncHttpDelete(String uri) {
9 | this(Uri.parse(uri));
10 | }
11 |
12 | public AsyncHttpDelete(Uri uri) {
13 | super(uri, METHOD);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpGet.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import android.net.Uri;
4 |
5 | public class AsyncHttpGet extends AsyncHttpRequest {
6 | public static final String METHOD = "GET";
7 |
8 | public AsyncHttpGet(String uri) {
9 | super(Uri.parse(uri), METHOD);
10 | }
11 |
12 | public AsyncHttpGet(Uri uri) {
13 | super(uri, METHOD);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpHead.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import android.net.Uri;
4 |
5 | /**
6 | * Created by koush on 8/25/13.
7 | */
8 | public class AsyncHttpHead extends AsyncHttpRequest {
9 | public AsyncHttpHead(Uri uri) {
10 | super(uri, METHOD);
11 | }
12 |
13 | @Override
14 | public boolean hasBody() {
15 | return false;
16 | }
17 |
18 | public static final String METHOD = "HEAD";
19 | }
20 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpPost.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import android.net.Uri;
4 |
5 | public class AsyncHttpPost extends AsyncHttpRequest {
6 | public static final String METHOD = "POST";
7 |
8 | public AsyncHttpPost(String uri) {
9 | this(Uri.parse(uri));
10 | }
11 |
12 | public AsyncHttpPost(Uri uri) {
13 | super(uri, METHOD);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpPut.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import android.net.Uri;
4 |
5 | public class AsyncHttpPut extends AsyncHttpRequest {
6 | public static final String METHOD = "PUT";
7 |
8 | public AsyncHttpPut(String uri) {
9 | this(Uri.parse(uri));
10 | }
11 |
12 | public AsyncHttpPut(Uri uri) {
13 | super(uri, METHOD);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncHttpResponse.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import com.koushikdutta.async.AsyncSocket;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.callback.CompletedCallback;
6 |
7 | public interface AsyncHttpResponse extends DataEmitter {
8 | public String protocol();
9 | public String message();
10 | public int code();
11 | public Headers headers();
12 | public AsyncSocket detachSocket();
13 | public AsyncHttpRequest getRequest();
14 | }
15 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/AsyncSSLEngineConfigurator.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import javax.net.ssl.SSLContext;
4 | import javax.net.ssl.SSLEngine;
5 |
6 | public interface AsyncSSLEngineConfigurator {
7 | SSLEngine createEngine(SSLContext sslContext, String peerHost, int peerPort);
8 | void configureEngine(SSLEngine engine, AsyncHttpClientMiddleware.GetSocketData data, String host, int port);
9 | }
10 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/BodyDecoderException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | public class BodyDecoderException extends Exception {
4 | public BodyDecoderException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/ConnectionClosedException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | public class ConnectionClosedException extends Exception {
4 | public ConnectionClosedException(String message) {
5 | super(message);
6 | }
7 |
8 | public ConnectionClosedException(String detailMessage, Throwable throwable) {
9 | super(detailMessage, throwable);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/ConnectionFailedException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | public class ConnectionFailedException extends Exception {
4 | public ConnectionFailedException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/HttpDate.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.koushikdutta.async.http;
18 |
19 | import java.text.DateFormat;
20 | import java.text.ParseException;
21 | import java.text.SimpleDateFormat;
22 | import java.util.Date;
23 | import java.util.Locale;
24 | import java.util.TimeZone;
25 |
26 | /**
27 | * Best-effort parser for HTTP dates.
28 | */
29 | public final class HttpDate {
30 |
31 | /**
32 | * Most websites serve cookies in the blessed format. Eagerly create the parser to ensure such
33 | * cookies are on the fast path.
34 | */
35 | private static final ThreadLocal STANDARD_DATE_FORMAT
36 | = new ThreadLocal() {
37 | @Override protected DateFormat initialValue() {
38 | DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
39 | rfc1123.setTimeZone(TimeZone.getTimeZone("UTC"));
40 | return rfc1123;
41 | }
42 | };
43 |
44 | /**
45 | * If we fail to parse a date in a non-standard format, try each of these formats in sequence.
46 | */
47 | private static final String[] BROWSER_COMPATIBLE_DATE_FORMATS = new String[] {
48 | /* This list comes from {@code org.apache.http.impl.cookie.BrowserCompatSpec}. */
49 | "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 1036
50 | "EEE MMM d HH:mm:ss yyyy", // ANSI C asctime()
51 | "EEE, dd-MMM-yyyy HH:mm:ss z",
52 | "EEE, dd-MMM-yyyy HH-mm-ss z",
53 | "EEE, dd MMM yy HH:mm:ss z",
54 | "EEE dd-MMM-yyyy HH:mm:ss z",
55 | "EEE dd MMM yyyy HH:mm:ss z",
56 | "EEE dd-MMM-yyyy HH-mm-ss z",
57 | "EEE dd-MMM-yy HH:mm:ss z",
58 | "EEE dd MMM yy HH:mm:ss z",
59 | "EEE,dd-MMM-yy HH:mm:ss z",
60 | "EEE,dd-MMM-yyyy HH:mm:ss z",
61 | "EEE, dd-MM-yyyy HH:mm:ss z",
62 |
63 | /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */
64 | "EEE MMM d yyyy HH:mm:ss z",
65 | };
66 |
67 | /**
68 | * Returns the date for {@code value}. Returns null if the value couldn't be
69 | * parsed.
70 | */
71 | public static Date parse(String value) {
72 | if (value == null)
73 | return null;
74 | try {
75 | return STANDARD_DATE_FORMAT.get().parse(value);
76 | } catch (ParseException ignore) {
77 | }
78 | for (String formatString : BROWSER_COMPATIBLE_DATE_FORMATS) {
79 | try {
80 | return new SimpleDateFormat(formatString, Locale.US).parse(value);
81 | } catch (ParseException ignore) {
82 | }
83 | }
84 | return null;
85 | }
86 |
87 | /**
88 | * Returns the string for {@code value}.
89 | */
90 | public static String format(Date value) {
91 | return STANDARD_DATE_FORMAT.get().format(value);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/RedirectLimitExceededException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | public class RedirectLimitExceededException extends Exception {
4 | public RedirectLimitExceededException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/RequestLine.java:
--------------------------------------------------------------------------------
1 | /*
2 | * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/RequestLine.java $
3 | * $Revision: 573864 $
4 | * $Date: 2007-09-08 08:53:25 -0700 (Sat, 08 Sep 2007) $
5 | *
6 | * ====================================================================
7 | * Licensed to the Apache Software Foundation (ASF) under one
8 | * or more contributor license agreements. See the NOTICE file
9 | * distributed with this work for additional information
10 | * regarding copyright ownership. The ASF licenses this file
11 | * to you under the Apache License, Version 2.0 (the
12 | * "License"); you may not use this file except in compliance
13 | * with the License. You may obtain a copy of the License at
14 | *
15 | * http://www.apache.org/licenses/LICENSE-2.0
16 | *
17 | * Unless required by applicable law or agreed to in writing,
18 | * software distributed under the License is distributed on an
19 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 | * KIND, either express or implied. See the License for the
21 | * specific language governing permissions and limitations
22 | * under the License.
23 | * ====================================================================
24 | *
25 | * This software consists of voluntary contributions made by many
26 | * individuals on behalf of the Apache Software Foundation. For more
27 | * information on the Apache Software Foundation, please see
28 | * .
29 | *
30 | */
31 |
32 | package com.koushikdutta.async.http;
33 |
34 | /**
35 | * The first line of an {@link HttpRequest HttpRequest}.
36 | * It contains the method, URI, and HTTP version of the request.
37 | * For details, see RFC 2616.
38 | *
39 | * @author Oleg Kalnichevski
40 | *
41 | * @version $Revision: 573864 $
42 | *
43 | * @since 4.0
44 | */
45 | public interface RequestLine {
46 |
47 | String getMethod();
48 |
49 | ProtocolVersion getProtocolVersion();
50 |
51 | String getUri();
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/SSLEngineSNIConfigurator.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import android.os.Build;
4 |
5 | import java.lang.reflect.Field;
6 | import java.util.Hashtable;
7 |
8 | import javax.net.ssl.SSLContext;
9 | import javax.net.ssl.SSLEngine;
10 |
11 | /**
12 | * Created by koush on 12/8/14.
13 | */
14 | public class SSLEngineSNIConfigurator implements AsyncSSLEngineConfigurator {
15 | private static class EngineHolder implements AsyncSSLEngineConfigurator {
16 | Field peerHost;
17 | Field peerPort;
18 | Field sslParameters;
19 | Field useSni;
20 | boolean skipReflection;
21 |
22 | @Override
23 | public SSLEngine createEngine(SSLContext sslContext, String peerHost, int peerPort) {
24 | return null;
25 | }
26 |
27 | public EngineHolder(Class engineClass) {
28 | try {
29 | peerHost = engineClass.getSuperclass().getDeclaredField("peerHost");
30 | peerHost.setAccessible(true);
31 |
32 | peerPort = engineClass.getSuperclass().getDeclaredField("peerPort");
33 | peerPort.setAccessible(true);
34 |
35 | sslParameters = engineClass.getDeclaredField("sslParameters");
36 | sslParameters.setAccessible(true);
37 |
38 | useSni = sslParameters.getType().getDeclaredField("useSni");
39 | useSni.setAccessible(true);
40 | }
41 | catch (NoSuchFieldException e) {
42 | }
43 | }
44 |
45 | @Override
46 | public void configureEngine(SSLEngine engine, AsyncHttpClientMiddleware.GetSocketData data, String host, int port) {
47 | if (useSni == null || skipReflection)
48 | return;
49 | try {
50 | peerHost.set(engine, host);
51 | peerPort.set(engine, port);
52 | Object sslp = sslParameters.get(engine);
53 | useSni.set(sslp, true);
54 | }
55 | catch (IllegalAccessException e) {
56 | }
57 | }
58 | }
59 |
60 | Hashtable holders = new Hashtable();
61 |
62 | @Override
63 | public SSLEngine createEngine(SSLContext sslContext, String peerHost, int peerPort) {
64 | // pre M, must use reflection to enable SNI, otherwise createSSLEngine(peerHost, peerPort) works.
65 | SSLEngine engine;
66 | boolean skipReflection = "GmsCore_OpenSSL".equals(sslContext.getProvider().getName()) || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
67 | if (skipReflection)
68 | engine = sslContext.createSSLEngine(peerHost, peerPort);
69 | else
70 | engine = sslContext.createSSLEngine();
71 | // ensureHolder(engine).skipReflection = skipReflection;
72 | return engine;
73 | }
74 |
75 | EngineHolder ensureHolder(SSLEngine engine) {
76 | String name = engine.getClass().getCanonicalName();
77 | EngineHolder holder = holders.get(name);
78 | if (holder == null) {
79 | holder = new EngineHolder(engine.getClass());
80 | holders.put(name, holder);
81 | }
82 | return holder;
83 | }
84 |
85 | @Override
86 | public void configureEngine(SSLEngine engine, AsyncHttpClientMiddleware.GetSocketData data, String host, int port) {
87 | EngineHolder holder = ensureHolder(engine);
88 | holder.configureEngine(engine, data, host, port);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/SimpleMiddleware.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import com.koushikdutta.async.future.Cancellable;
4 |
5 | public class SimpleMiddleware implements AsyncHttpClientMiddleware {
6 | @Override
7 | public void onRequest(OnRequestData data) {
8 | }
9 |
10 | @Override
11 | public Cancellable getSocket(GetSocketData data) {
12 | return null;
13 | }
14 |
15 | @Override
16 | public boolean exchangeHeaders(OnExchangeHeaderData data) {
17 | return false;
18 | }
19 |
20 | @Override
21 | public void onRequestSent(OnRequestSentData data) {
22 | }
23 |
24 | @Override
25 | public void onHeadersReceived(OnHeadersReceivedData data) {
26 | }
27 |
28 | @Override
29 | public void onBodyDecoder(OnBodyDecoderData data) {
30 | }
31 |
32 | @Override
33 | public AsyncHttpRequest onResponseReady(OnResponseReadyData data) {
34 | return null;
35 | }
36 |
37 | @Override
38 | public void onResponseComplete(OnResponseCompleteData data) {
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/WebSocket.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | import com.koushikdutta.async.AsyncSocket;
4 |
5 | public interface WebSocket extends AsyncSocket {
6 | interface StringCallback {
7 | void onStringAvailable(String s);
8 | }
9 | interface PingCallback {
10 | void onPingReceived(String s);
11 | }
12 | interface PongCallback {
13 | void onPongReceived(String s);
14 | }
15 |
16 | void send(byte[] bytes);
17 | void send(String string);
18 | void send(byte [] bytes, int offset, int len);
19 | void ping(String message);
20 | void pong(String message);
21 |
22 | void setStringCallback(StringCallback callback);
23 | StringCallback getStringCallback();
24 |
25 | void setPingCallback(PingCallback callback);
26 |
27 | void setPongCallback(PongCallback callback);
28 | PongCallback getPongCallback();
29 |
30 | boolean isBuffering();
31 | String getProtocol();
32 |
33 | AsyncSocket getSocket();
34 | }
35 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/WebSocketHandshakeException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http;
2 |
3 | public class WebSocketHandshakeException extends Exception {
4 | public WebSocketHandshakeException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/AsyncHttpRequestBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.callback.CompletedCallback;
6 | import com.koushikdutta.async.http.AsyncHttpRequest;
7 |
8 | public interface AsyncHttpRequestBody {
9 | public void write(AsyncHttpRequest request, DataSink sink, CompletedCallback completed);
10 | public void parse(DataEmitter emitter, CompletedCallback completed);
11 | public String getContentType();
12 | public boolean readFullyOnRequest();
13 | public int length();
14 | public T get();
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/ByteBufferListRequestBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.DataSink;
6 | import com.koushikdutta.async.Util;
7 | import com.koushikdutta.async.callback.CompletedCallback;
8 | import com.koushikdutta.async.http.AsyncHttpRequest;
9 | import com.koushikdutta.async.parser.ByteBufferListParser;
10 |
11 | public class ByteBufferListRequestBody implements AsyncHttpRequestBody {
12 | public ByteBufferListRequestBody() {
13 | }
14 |
15 | ByteBufferList bb;
16 | public ByteBufferListRequestBody(ByteBufferList bb) {
17 | this.bb = bb;
18 | }
19 | @Override
20 | public void write(AsyncHttpRequest request, DataSink sink, CompletedCallback completed) {
21 | Util.writeAll(sink, bb, completed);
22 | }
23 |
24 | @Override
25 | public void parse(DataEmitter emitter, CompletedCallback completed) {
26 | new ByteBufferListParser().parse(emitter).setCallback((e, result) -> {
27 | bb = result;
28 | completed.onCompleted(e);
29 | });
30 | }
31 |
32 | public static String CONTENT_TYPE = "application/binary";
33 |
34 | @Override
35 | public String getContentType() {
36 | return CONTENT_TYPE;
37 | }
38 |
39 | @Override
40 | public boolean readFullyOnRequest() {
41 | return true;
42 | }
43 |
44 | @Override
45 | public int length() {
46 | return bb.remaining();
47 | }
48 |
49 | @Override
50 | public ByteBufferList get() {
51 | return bb;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/DocumentBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.future.FutureCallback;
8 | import com.koushikdutta.async.http.AsyncHttpRequest;
9 | import com.koushikdutta.async.parser.DocumentParser;
10 | import com.koushikdutta.async.util.Charsets;
11 |
12 | import org.w3c.dom.Document;
13 |
14 | import java.io.ByteArrayOutputStream;
15 | import java.io.OutputStreamWriter;
16 |
17 | import javax.xml.transform.Transformer;
18 | import javax.xml.transform.TransformerFactory;
19 | import javax.xml.transform.dom.DOMSource;
20 | import javax.xml.transform.stream.StreamResult;
21 |
22 | /**
23 | * Created by koush on 8/30/13.
24 | */
25 | public class DocumentBody implements AsyncHttpRequestBody {
26 | public DocumentBody() {
27 | this(null);
28 | }
29 |
30 | public DocumentBody(Document document) {
31 | this.document = document;
32 | }
33 |
34 | ByteArrayOutputStream bout;
35 | private void prepare() {
36 | if (bout != null)
37 | return;
38 |
39 | try {
40 | DOMSource source = new DOMSource(document);
41 | TransformerFactory tf = TransformerFactory.newInstance();
42 | Transformer transformer = tf.newTransformer();
43 | bout = new ByteArrayOutputStream();
44 | OutputStreamWriter writer = new OutputStreamWriter(bout, Charsets.UTF_8);
45 | StreamResult result = new StreamResult(writer);
46 | transformer.transform(source, result);
47 | writer.flush();
48 | }
49 | catch (Exception e) {
50 | }
51 | }
52 |
53 | @Override
54 | public void write(AsyncHttpRequest request, DataSink sink, CompletedCallback completed) {
55 | prepare();
56 | byte[] bytes = bout.toByteArray();
57 | Util.writeAll(sink, bytes, completed);
58 | }
59 |
60 | @Override
61 | public void parse(DataEmitter emitter, final CompletedCallback completed) {
62 | new DocumentParser().parse(emitter).setCallback(new FutureCallback() {
63 | @Override
64 | public void onCompleted(Exception e, Document result) {
65 | document = result;
66 | completed.onCompleted(e);
67 | }
68 | });
69 | }
70 |
71 | public static final String CONTENT_TYPE = "application/xml";
72 |
73 | @Override
74 | public String getContentType() {
75 | return CONTENT_TYPE;
76 | }
77 |
78 | @Override
79 | public boolean readFullyOnRequest() {
80 | return true;
81 | }
82 |
83 | @Override
84 | public int length() {
85 | prepare();
86 | return bout.size();
87 | }
88 |
89 | Document document;
90 | @Override
91 | public Document get() {
92 | return document;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/FileBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.http.AsyncHttpRequest;
8 |
9 | import java.io.File;
10 |
11 | /**
12 | * Created by koush on 10/14/13.
13 | */
14 | public class FileBody implements AsyncHttpRequestBody {
15 | public static final String CONTENT_TYPE = "application/binary";
16 |
17 | File file;
18 | String contentType = CONTENT_TYPE;
19 |
20 | public FileBody(File file) {
21 | this.file = file;
22 | }
23 |
24 | public FileBody(File file, String contentType) {
25 | this.file = file;
26 | this.contentType = contentType;
27 | }
28 |
29 | @Override
30 | public void write(AsyncHttpRequest request, DataSink sink, CompletedCallback completed) {
31 | Util.pump(file, sink, completed);
32 | }
33 |
34 | @Override
35 | public void parse(DataEmitter emitter, CompletedCallback completed) {
36 | throw new AssertionError("not implemented");
37 | }
38 |
39 | @Override
40 | public String getContentType() {
41 | return contentType;
42 | }
43 |
44 | public void setContentType(String contentType) {
45 | this.contentType = contentType;
46 | }
47 |
48 | @Override
49 | public boolean readFullyOnRequest() {
50 | throw new AssertionError("not implemented");
51 | }
52 |
53 | @Override
54 | public int length() {
55 | return (int)file.length();
56 | }
57 |
58 | @Override
59 | public File get() {
60 | return file;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/FilePart.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.http.BasicNameValuePair;
4 | import com.koushikdutta.async.http.NameValuePair;
5 |
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.util.ArrayList;
11 |
12 | public class FilePart extends StreamPart {
13 | File file;
14 | public FilePart(String name, final File file) {
15 | super(name, (int)file.length(), new ArrayList() {
16 | {
17 | add(new BasicNameValuePair("filename", file.getName()));
18 | }
19 | });
20 |
21 | // getRawHeaders().set("Content-Type", "application/xml");
22 |
23 | this.file = file;
24 | }
25 |
26 | @Override
27 | protected InputStream getInputStream() throws IOException {
28 | return new FileInputStream(file);
29 | }
30 |
31 | @Override
32 | public String toString() {
33 | return getName();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/JSONArrayBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.future.FutureCallback;
8 | import com.koushikdutta.async.http.AsyncHttpRequest;
9 | import com.koushikdutta.async.parser.JSONArrayParser;
10 |
11 | import org.json.JSONArray;
12 |
13 | public class JSONArrayBody implements AsyncHttpRequestBody {
14 | public JSONArrayBody() {
15 | }
16 |
17 | byte[] mBodyBytes;
18 | JSONArray json;
19 | public JSONArrayBody(JSONArray json) {
20 | this();
21 | this.json = json;
22 | }
23 |
24 | @Override
25 | public void parse(DataEmitter emitter, final CompletedCallback completed) {
26 | new JSONArrayParser().parse(emitter).setCallback(new FutureCallback() {
27 | @Override
28 | public void onCompleted(Exception e, JSONArray result) {
29 | json = result;
30 | completed.onCompleted(e);
31 | }
32 | });
33 | }
34 |
35 | @Override
36 | public void write(AsyncHttpRequest request, DataSink sink, final CompletedCallback completed) {
37 | Util.writeAll(sink, mBodyBytes, completed);
38 | }
39 |
40 | @Override
41 | public String getContentType() {
42 | return "application/json";
43 | }
44 |
45 | @Override
46 | public boolean readFullyOnRequest() {
47 | return true;
48 | }
49 |
50 | @Override
51 | public int length() {
52 | mBodyBytes = json.toString().getBytes();
53 | return mBodyBytes.length;
54 | }
55 |
56 | public static final String CONTENT_TYPE = "application/json";
57 |
58 | @Override
59 | public JSONArray get() {
60 | return json;
61 | }
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/JSONObjectBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.future.FutureCallback;
8 | import com.koushikdutta.async.http.AsyncHttpRequest;
9 | import com.koushikdutta.async.parser.JSONObjectParser;
10 |
11 | import org.json.JSONObject;
12 |
13 | public class JSONObjectBody implements AsyncHttpRequestBody {
14 | public JSONObjectBody() {
15 | }
16 |
17 | byte[] mBodyBytes;
18 | JSONObject json;
19 | public JSONObjectBody(JSONObject json) {
20 | this();
21 | this.json = json;
22 | }
23 |
24 | @Override
25 | public void parse(DataEmitter emitter, final CompletedCallback completed) {
26 | new JSONObjectParser().parse(emitter).setCallback(new FutureCallback() {
27 | @Override
28 | public void onCompleted(Exception e, JSONObject result) {
29 | json = result;
30 | completed.onCompleted(e);
31 | }
32 | });
33 | }
34 |
35 | @Override
36 | public void write(AsyncHttpRequest request, DataSink sink, final CompletedCallback completed) {
37 | Util.writeAll(sink, mBodyBytes, completed);
38 | }
39 |
40 | @Override
41 | public String getContentType() {
42 | return CONTENT_TYPE;
43 | }
44 |
45 | @Override
46 | public boolean readFullyOnRequest() {
47 | return true;
48 | }
49 |
50 | @Override
51 | public int length() {
52 | mBodyBytes = json.toString().getBytes();
53 | return mBodyBytes.length;
54 | }
55 |
56 | public static final String CONTENT_TYPE = "application/json";
57 |
58 | @Override
59 | public JSONObject get() {
60 | return json;
61 | }
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/Part.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataSink;
4 | import com.koushikdutta.async.callback.CompletedCallback;
5 | import com.koushikdutta.async.http.Headers;
6 | import com.koushikdutta.async.http.Multimap;
7 | import com.koushikdutta.async.http.NameValuePair;
8 |
9 | import java.io.File;
10 | import java.util.List;
11 | import java.util.Locale;
12 |
13 | public class Part {
14 | public static final String CONTENT_DISPOSITION = "Content-Disposition";
15 |
16 | Headers mHeaders;
17 | Multimap mContentDisposition;
18 | public Part(Headers headers) {
19 | mHeaders = headers;
20 | mContentDisposition = Multimap.parseSemicolonDelimited(mHeaders.get(CONTENT_DISPOSITION));
21 | }
22 |
23 | public String getName() {
24 | return mContentDisposition.getString("name");
25 | }
26 |
27 | private long length = -1;
28 | public Part(String name, long length, List contentDisposition) {
29 | this.length = length;
30 | mHeaders = new Headers();
31 | StringBuilder builder = new StringBuilder(String.format(Locale.ENGLISH, "form-data; name=\"%s\"", name));
32 | if (contentDisposition != null) {
33 | for (NameValuePair pair: contentDisposition) {
34 | builder.append(String.format(Locale.ENGLISH, "; %s=\"%s\"", pair.getName(), pair.getValue()));
35 | }
36 | }
37 | mHeaders.set(CONTENT_DISPOSITION, builder.toString());
38 | mContentDisposition = Multimap.parseSemicolonDelimited(mHeaders.get(CONTENT_DISPOSITION));
39 | }
40 |
41 | public Headers getRawHeaders() {
42 | return mHeaders;
43 | }
44 |
45 | public String getContentType() {
46 | return mHeaders.get("Content-Type");
47 | }
48 |
49 | public void setContentType(String contentType) {
50 | mHeaders.set("Content-Type", contentType);
51 | }
52 |
53 | public String getFilename() {
54 | String file = mContentDisposition.getString("filename");
55 | if (file == null)
56 | return null;
57 | return new File(file).getName();
58 | }
59 |
60 | public boolean isFile() {
61 | return mContentDisposition.containsKey("filename");
62 | }
63 |
64 | public long length() {
65 | return length;
66 | }
67 |
68 | public void write(DataSink sink, CompletedCallback callback) {
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/StreamBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.http.AsyncHttpRequest;
8 |
9 | import java.io.InputStream;
10 |
11 | public class StreamBody implements AsyncHttpRequestBody {
12 | InputStream stream;
13 | int length;
14 | String contentType = CONTENT_TYPE;
15 |
16 | /**
17 | * Construct an http body from a stream
18 | * @param stream
19 | * @param length Length of stream to read, or value < 0 to read to end
20 | */
21 | public StreamBody(InputStream stream, int length) {
22 | this.stream = stream;
23 | this.length = length;
24 | }
25 |
26 | @Override
27 | public void write(AsyncHttpRequest request, DataSink sink, CompletedCallback completed) {
28 | Util.pump(stream, length < 0 ? Integer.MAX_VALUE : length, sink, completed);
29 | }
30 |
31 | @Override
32 | public void parse(DataEmitter emitter, CompletedCallback completed) {
33 | throw new AssertionError("not implemented");
34 | }
35 |
36 | public static final String CONTENT_TYPE = "application/binary";
37 | @Override
38 | public String getContentType() {
39 | return contentType;
40 | }
41 | public StreamBody setContentType(String contentType) {
42 | this.contentType = contentType;
43 | return this;
44 | }
45 |
46 | @Override
47 | public boolean readFullyOnRequest() {
48 | throw new AssertionError("not implemented");
49 | }
50 |
51 | @Override
52 | public int length() {
53 | return length;
54 | }
55 |
56 | @Override
57 | public InputStream get() {
58 | return stream;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/StreamPart.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.List;
6 |
7 | import com.koushikdutta.async.DataSink;
8 | import com.koushikdutta.async.callback.CompletedCallback;
9 | import com.koushikdutta.async.http.NameValuePair;
10 |
11 | public abstract class StreamPart extends Part {
12 | public StreamPart(String name, long length, List contentDisposition) {
13 | super(name, length, contentDisposition);
14 | }
15 |
16 | @Override
17 | public void write(DataSink sink, CompletedCallback callback) {
18 | try {
19 | InputStream is = getInputStream();
20 | com.koushikdutta.async.Util.pump(is, sink, callback);
21 | }
22 | catch (Exception e) {
23 | callback.onCompleted(e);
24 | }
25 | }
26 |
27 | protected abstract InputStream getInputStream() throws IOException;
28 | }
29 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/StringBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.future.FutureCallback;
8 | import com.koushikdutta.async.http.AsyncHttpRequest;
9 | import com.koushikdutta.async.parser.StringParser;
10 |
11 | public class StringBody implements AsyncHttpRequestBody {
12 | public StringBody() {
13 | }
14 |
15 | byte[] mBodyBytes;
16 | String string;
17 | public StringBody(String string) {
18 | this();
19 | this.string = string;
20 | }
21 |
22 | @Override
23 | public void parse(DataEmitter emitter, final CompletedCallback completed) {
24 | new StringParser().parse(emitter).setCallback(new FutureCallback() {
25 | @Override
26 | public void onCompleted(Exception e, String result) {
27 | string = result;
28 | completed.onCompleted(e);
29 | }
30 | });
31 | }
32 |
33 | public static final String CONTENT_TYPE = "text/plain";
34 |
35 | @Override
36 | public void write(AsyncHttpRequest request, DataSink sink, final CompletedCallback completed) {
37 | if (mBodyBytes == null)
38 | mBodyBytes = string.getBytes();
39 | Util.writeAll(sink, mBodyBytes, completed);
40 | }
41 |
42 | @Override
43 | public String getContentType() {
44 | return "text/plain";
45 | }
46 |
47 | @Override
48 | public boolean readFullyOnRequest() {
49 | return true;
50 | }
51 |
52 | @Override
53 | public int length() {
54 | if (mBodyBytes == null)
55 | mBodyBytes = string.getBytes();
56 | return mBodyBytes.length;
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return string;
62 | }
63 |
64 | @Override
65 | public String get() {
66 | return toString();
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/body/StringPart.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.body;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 |
7 | public class StringPart extends StreamPart {
8 | String value;
9 | public StringPart(String name, String value) {
10 | super(name, value.getBytes().length, null);
11 | this.value = value;
12 | }
13 |
14 | @Override
15 | protected InputStream getInputStream() throws IOException {
16 | return new ByteArrayInputStream(value.getBytes());
17 | }
18 |
19 | public String getValue() {
20 | return value;
21 | }
22 |
23 | @Override
24 | public String toString() {
25 | return value;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/cache/Objects.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.koushikdutta.async.http.cache;
18 |
19 | final class Objects {
20 | private Objects() {}
21 |
22 | /**
23 | * Returns true if two possibly-null objects are equal.
24 | */
25 | public static boolean equal(Object a, Object b) {
26 | return a == b || (a != null && a.equals(b));
27 | }
28 |
29 | public static int hashCode(Object o) {
30 | return (o == null) ? 0 : o.hashCode();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/cache/ResponseSource.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.koushikdutta.async.http.cache;
18 |
19 | enum ResponseSource {
20 |
21 | /**
22 | * Return the response from the cache immediately.
23 | */
24 | CACHE,
25 |
26 | /**
27 | * Make a conditional request to the host, returning the cache response if
28 | * the cache is valid and the network response otherwise.
29 | */
30 | CONDITIONAL_CACHE,
31 |
32 | /**
33 | * Return the response from the network.
34 | */
35 | NETWORK;
36 |
37 | public boolean requiresConnection() {
38 | return this == CONDITIONAL_CACHE || this == NETWORK;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/callback/HttpConnectCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.callback;
2 |
3 |
4 | import com.koushikdutta.async.http.AsyncHttpResponse;
5 |
6 | public interface HttpConnectCallback {
7 | public void onConnectCompleted(Exception ex, AsyncHttpResponse response);
8 | }
9 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/callback/RequestCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.callback;
2 |
3 | import com.koushikdutta.async.callback.ResultCallback;
4 | import com.koushikdutta.async.http.AsyncHttpResponse;
5 |
6 | public interface RequestCallback extends ResultCallback {
7 | public void onConnect(AsyncHttpResponse response);
8 | public void onProgress(AsyncHttpResponse response, long downloaded, long total);
9 | }
10 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedDataException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.filter;
2 |
3 | public class ChunkedDataException extends Exception {
4 | public ChunkedDataException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/filter/ChunkedOutputFilter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.filter;
2 |
3 | import java.nio.ByteBuffer;
4 |
5 | import com.koushikdutta.async.ByteBufferList;
6 | import com.koushikdutta.async.DataSink;
7 | import com.koushikdutta.async.FilteredDataSink;
8 |
9 | public class ChunkedOutputFilter extends FilteredDataSink {
10 | public ChunkedOutputFilter(DataSink sink) {
11 | super(sink);
12 | }
13 |
14 | @Override
15 | public ByteBufferList filter(ByteBufferList bb) {
16 | String chunkLen = Integer.toString(bb.remaining(), 16) + "\r\n";
17 | bb.addFirst(ByteBuffer.wrap(chunkLen.getBytes()));
18 | bb.add(ByteBuffer.wrap("\r\n".getBytes()));
19 | return bb;
20 | }
21 |
22 | @Override
23 | public void end() {
24 | setMaxBuffer(Integer.MAX_VALUE);
25 | ByteBufferList fin = new ByteBufferList();
26 | write(fin);
27 | setMaxBuffer(0);
28 | // do NOT call through to super.end, as chunking is a framing protocol.
29 | // we don't want to close the underlying transport.
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/filter/ContentLengthFilter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.filter;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.FilteredDataEmitter;
6 |
7 | public class ContentLengthFilter extends FilteredDataEmitter {
8 | public ContentLengthFilter(long contentLength) {
9 | this.contentLength = contentLength;
10 | }
11 |
12 | @Override
13 | protected void report(Exception e) {
14 | if (e == null && totalRead != contentLength)
15 | e = new PrematureDataEndException("End of data reached before content length was read: " + totalRead + "/" + contentLength + " Paused: " + isPaused());
16 | super.report(e);
17 | }
18 |
19 | long contentLength;
20 | long totalRead;
21 | ByteBufferList transformed = new ByteBufferList();
22 | @Override
23 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
24 | int remaining = bb.remaining();
25 | long toRead = Math.min(contentLength - totalRead, remaining);
26 |
27 | bb.get(transformed, (int)toRead);
28 |
29 | int beforeRead = transformed.remaining();
30 |
31 | super.onDataAvailable(emitter, transformed);
32 |
33 | totalRead += (beforeRead - transformed.remaining());
34 | transformed.get(bb);
35 |
36 | if (totalRead == contentLength)
37 | report(null);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/filter/DataRemainingException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.filter;
2 |
3 | public class DataRemainingException extends Exception {
4 | public DataRemainingException(String message, Exception cause) {
5 | super(message, cause);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/filter/InflaterInputFilter.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.filter;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.FilteredDataEmitter;
6 | import com.koushikdutta.async.Util;
7 |
8 | import java.io.IOException;
9 | import java.nio.ByteBuffer;
10 | import java.util.zip.Inflater;
11 |
12 | public class InflaterInputFilter extends FilteredDataEmitter {
13 | private Inflater mInflater;
14 |
15 | @Override
16 | protected void report(Exception e) {
17 | mInflater.end();
18 | if (e != null && mInflater.getRemaining() > 0) {
19 | e = new DataRemainingException("data still remaining in inflater", e);
20 | }
21 | super.report(e);
22 | }
23 |
24 | ByteBufferList transformed = new ByteBufferList();
25 | @Override
26 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
27 | try {
28 | ByteBuffer output = ByteBufferList.obtain(bb.remaining() * 2);
29 | int totalRead = 0;
30 | while (bb.size() > 0) {
31 | ByteBuffer b = bb.remove();
32 | if (b.hasRemaining()) {
33 | totalRead =+ b.remaining();
34 | mInflater.setInput(b.array(), b.arrayOffset() + b.position(), b.remaining());
35 | do {
36 | int inflated = mInflater.inflate(output.array(), output.arrayOffset() + output.position(), output.remaining());
37 | output.position(output.position() + inflated);
38 | if (!output.hasRemaining()) {
39 | output.flip();
40 | transformed.add(output);
41 | int newSize = output.capacity() * 2;
42 | output = ByteBufferList.obtain(newSize);
43 | }
44 | }
45 | while (!mInflater.needsInput() && !mInflater.finished());
46 | }
47 | ByteBufferList.reclaim(b);
48 | }
49 | output.flip();
50 | transformed.add(output);
51 |
52 | Util.emitAllData(this, transformed);
53 | }
54 | catch (Exception ex) {
55 | report(ex);
56 | }
57 | }
58 |
59 | public InflaterInputFilter() {
60 | this(new Inflater());
61 | }
62 |
63 | public InflaterInputFilter(Inflater inflater) {
64 | mInflater = inflater;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/filter/PrematureDataEndException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.filter;
2 |
3 | public class PrematureDataEndException extends Exception {
4 | public PrematureDataEndException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpRequestBodyProvider.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | import com.koushikdutta.async.http.Headers;
4 | import com.koushikdutta.async.http.body.AsyncHttpRequestBody;
5 |
6 | public interface AsyncHttpRequestBodyProvider {
7 | AsyncHttpRequestBody getBody(Headers headers);
8 | }
9 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerRequest.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | import com.koushikdutta.async.AsyncSocket;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.http.Headers;
6 | import com.koushikdutta.async.http.Multimap;
7 | import com.koushikdutta.async.http.body.AsyncHttpRequestBody;
8 |
9 | import java.util.Map;
10 | import java.util.regex.Matcher;
11 |
12 | public interface AsyncHttpServerRequest extends DataEmitter {
13 | Headers getHeaders();
14 | Matcher getMatcher();
15 | void setMatcher(Matcher matcher);
16 | T getBody();
17 | AsyncSocket getSocket();
18 | String getPath();
19 | Multimap getQuery();
20 | String getMethod();
21 | String getUrl();
22 |
23 | String get(String name);
24 | Map getState();
25 | }
26 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncHttpServerResponse.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | import com.koushikdutta.async.AsyncSocket;
4 | import com.koushikdutta.async.ByteBufferList;
5 | import com.koushikdutta.async.DataSink;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.http.AsyncHttpResponse;
8 | import com.koushikdutta.async.http.Headers;
9 | import com.koushikdutta.async.http.body.AsyncHttpRequestBody;
10 | import com.koushikdutta.async.parser.AsyncParser;
11 |
12 | import org.json.JSONArray;
13 | import org.json.JSONObject;
14 |
15 | import java.io.File;
16 | import java.io.InputStream;
17 | import java.nio.ByteBuffer;
18 |
19 | public interface AsyncHttpServerResponse extends DataSink, CompletedCallback {
20 | void end();
21 | void send(String contentType, byte[] bytes);
22 | void send(String contentType, ByteBufferList bb);
23 | void send(String contentType, ByteBuffer bb);
24 | void send(String contentType, String string);
25 | void send(String string);
26 | void send(JSONObject json);
27 | void send(JSONArray jsonArray);
28 | void sendFile(File file);
29 | void sendStream(InputStream inputStream, long totalLength);
30 | void sendBody(AsyncParser body, T value);
31 | AsyncHttpServerResponse code(int code);
32 | int code();
33 | Headers getHeaders();
34 | void writeHead();
35 | void setContentType(String contentType);
36 | void redirect(String location);
37 | AsyncHttpServerRequest getRequest();
38 | String getHttpVersion();
39 | void setHttpVersion(String httpVersion);
40 |
41 | // NOT FINAL
42 | void proxy(AsyncHttpResponse response);
43 |
44 | /**
45 | * Alias for end. Used with CompletedEmitters
46 | */
47 | void onCompleted(Exception ex);
48 | AsyncSocket getSocket();
49 | void setSocket(AsyncSocket socket);
50 | }
51 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/AsyncProxyServer.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | import android.net.Uri;
4 |
5 | import com.koushikdutta.async.AsyncServer;
6 | import com.koushikdutta.async.Util;
7 | import com.koushikdutta.async.callback.CompletedCallback;
8 | import com.koushikdutta.async.http.AsyncHttpClient;
9 | import com.koushikdutta.async.http.AsyncHttpRequest;
10 | import com.koushikdutta.async.http.AsyncHttpResponse;
11 | import com.koushikdutta.async.http.callback.HttpConnectCallback;
12 |
13 | /**
14 | * Created by koush on 7/22/14.
15 | */
16 | public class AsyncProxyServer extends AsyncHttpServer {
17 | AsyncHttpClient proxyClient;
18 | public AsyncProxyServer(AsyncServer server) {
19 | proxyClient = new AsyncHttpClient(server);
20 | }
21 |
22 | @Override
23 | protected void onRequest(HttpServerRequestCallback callback, AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
24 | super.onRequest(callback, request, response);
25 |
26 | if (callback != null)
27 | return;
28 |
29 | try {
30 | Uri uri;
31 |
32 | try {
33 | uri = Uri.parse(request.getPath());
34 | if (uri.getScheme() == null)
35 | throw new Exception("no host or full uri provided");
36 | }
37 | catch (Exception e) {
38 | String host = request.getHeaders().get("Host");
39 | int port = 80;
40 | if (host != null) {
41 | String[] splits = host.split(":", 2);
42 | if (splits.length == 2) {
43 | host = splits[0];
44 | port = Integer.parseInt(splits[1]);
45 | }
46 | }
47 | uri = Uri.parse("http://" + host + ":" + port + request.getPath());
48 | }
49 |
50 | proxyClient.execute(new AsyncHttpRequest(uri, request.getMethod(), request.getHeaders()), new HttpConnectCallback() {
51 | @Override
52 | public void onConnectCompleted(Exception ex, AsyncHttpResponse remoteResponse) {
53 | if (ex != null) {
54 | response.code(500);
55 | response.send(ex.getMessage());
56 | return;
57 | }
58 | response.proxy(remoteResponse);
59 | }
60 | });
61 | }
62 | catch (Exception e) {
63 | response.code(500);
64 | response.send(e.getMessage());
65 | }
66 | }
67 |
68 | @Override
69 | protected boolean onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
70 | return true;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/HttpServerRequestCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 |
4 | public interface HttpServerRequestCallback {
5 | public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response);
6 | }
7 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/MalformedRangeException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | public class MalformedRangeException extends Exception {
4 | }
5 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/MimeEncodingException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | public class MimeEncodingException extends Exception {
4 | public MimeEncodingException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/RouteMatcher.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | public interface RouteMatcher {
4 | AsyncHttpServerRouter.RouteMatch route(String method, String path);
5 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/StreamSkipException.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | public class StreamSkipException extends Exception {
4 | public StreamSkipException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/http/server/UnknownRequestBody.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.http.server;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.Util;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.callback.DataCallback;
8 | import com.koushikdutta.async.http.AsyncHttpRequest;
9 | import com.koushikdutta.async.http.body.AsyncHttpRequestBody;
10 |
11 | public class UnknownRequestBody implements AsyncHttpRequestBody {
12 | public UnknownRequestBody(String contentType) {
13 | mContentType = contentType;
14 | }
15 |
16 | int length = -1;
17 | public UnknownRequestBody(DataEmitter emitter, String contentType, int length) {
18 | mContentType = contentType;
19 | this.emitter = emitter;
20 | this.length = length;
21 | }
22 |
23 | @Override
24 | public void write(final AsyncHttpRequest request, DataSink sink, final CompletedCallback completed) {
25 | Util.pump(emitter, sink, completed);
26 | if (emitter.isPaused())
27 | emitter.resume();
28 | }
29 |
30 | private String mContentType;
31 | @Override
32 | public String getContentType() {
33 | return mContentType;
34 | }
35 |
36 | @Override
37 | public boolean readFullyOnRequest() {
38 | return false;
39 | }
40 |
41 | @Override
42 | public int length() {
43 | return length;
44 | }
45 |
46 | @Override
47 | public Void get() {
48 | return null;
49 | }
50 |
51 | @Deprecated
52 | public void setCallbacks(DataCallback callback, CompletedCallback endCallback) {
53 | emitter.setEndCallback(endCallback);
54 | emitter.setDataCallback(callback);
55 | }
56 |
57 | public DataEmitter getEmitter() {
58 | return emitter;
59 | }
60 |
61 | DataEmitter emitter;
62 | @Override
63 | public void parse(DataEmitter emitter, CompletedCallback completed) {
64 | this.emitter = emitter;
65 | emitter.setEndCallback(completed);
66 | emitter.setDataCallback(new DataCallback.NullDataCallback());
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/parser/AsyncParser.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.parser;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.callback.CompletedCallback;
6 | import com.koushikdutta.async.future.Future;
7 |
8 | import java.lang.reflect.Type;
9 |
10 | /**
11 | * Created by koush on 5/27/13.
12 | */
13 | public interface AsyncParser {
14 | Future parse(DataEmitter emitter);
15 | void write(DataSink sink, T value, CompletedCallback completed);
16 | Type getType();
17 | String getMime();
18 | }
19 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/parser/ByteBufferListParser.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.parser;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.DataSink;
6 | import com.koushikdutta.async.Util;
7 | import com.koushikdutta.async.callback.CompletedCallback;
8 | import com.koushikdutta.async.callback.DataCallback;
9 | import com.koushikdutta.async.future.Future;
10 | import com.koushikdutta.async.future.SimpleFuture;
11 |
12 | import java.lang.reflect.Type;
13 |
14 | /**
15 | * Created by koush on 5/27/13.
16 | */
17 | public class ByteBufferListParser implements AsyncParser {
18 | @Override
19 | public Future parse(final DataEmitter emitter) {
20 | final ByteBufferList bb = new ByteBufferList();
21 | final SimpleFuture ret = new SimpleFuture() {
22 | @Override
23 | protected void cancelCleanup() {
24 | emitter.close();
25 | }
26 | };
27 | emitter.setDataCallback(new DataCallback() {
28 | @Override
29 | public void onDataAvailable(DataEmitter emitter, ByteBufferList data) {
30 | data.get(bb);
31 | }
32 | });
33 |
34 | emitter.setEndCallback(new CompletedCallback() {
35 | @Override
36 | public void onCompleted(Exception ex) {
37 | if (ex != null) {
38 | ret.setComplete(ex);
39 | return;
40 | }
41 |
42 | try {
43 | ret.setComplete(bb);
44 | }
45 | catch (Exception e) {
46 | ret.setComplete(e);
47 | }
48 | }
49 | });
50 |
51 | return ret;
52 | }
53 |
54 | @Override
55 | public void write(DataSink sink, ByteBufferList value, CompletedCallback completed) {
56 | Util.writeAll(sink, value, completed);
57 | }
58 |
59 | @Override
60 | public Type getType() {
61 | return ByteBufferList.class;
62 | }
63 |
64 | @Override
65 | public String getMime() {
66 | return null;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/parser/DocumentParser.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.parser;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.callback.CompletedCallback;
6 | import com.koushikdutta.async.future.Future;
7 | import com.koushikdutta.async.http.body.DocumentBody;
8 | import com.koushikdutta.async.stream.ByteBufferListInputStream;
9 |
10 | import org.w3c.dom.Document;
11 |
12 | import java.lang.reflect.Type;
13 |
14 | import javax.xml.parsers.DocumentBuilderFactory;
15 |
16 | /**
17 | * Created by koush on 8/3/13.
18 | */
19 | public class DocumentParser implements AsyncParser {
20 | @Override
21 | public Future parse(DataEmitter emitter) {
22 | return new ByteBufferListParser().parse(emitter)
23 | .thenConvert(from -> DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteBufferListInputStream(from)));
24 | }
25 |
26 | @Override
27 | public void write(DataSink sink, Document value, CompletedCallback completed) {
28 | new DocumentBody(value).write(null, sink, completed);
29 | }
30 |
31 | @Override
32 | public Type getType() {
33 | return Document.class;
34 | }
35 |
36 | @Override
37 | public String getMime() {
38 | return "text/xml";
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/parser/JSONArrayParser.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.parser;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.callback.CompletedCallback;
6 | import com.koushikdutta.async.future.Future;
7 |
8 | import org.json.JSONArray;
9 |
10 | import java.lang.reflect.Type;
11 |
12 | /**
13 | * Created by koush on 5/27/13.
14 | */
15 | public class JSONArrayParser implements AsyncParser {
16 | @Override
17 | public Future parse(DataEmitter emitter) {
18 | return new StringParser().parse(emitter)
19 | .thenConvert(JSONArray::new);
20 | }
21 |
22 | @Override
23 | public void write(DataSink sink, JSONArray value, CompletedCallback completed) {
24 | new StringParser().write(sink, value.toString(), completed);
25 | }
26 |
27 | @Override
28 | public Type getType() {
29 | return JSONArray.class;
30 | }
31 |
32 | @Override
33 | public String getMime() {
34 | return "application/json";
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/parser/JSONObjectParser.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.parser;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 | import com.koushikdutta.async.DataSink;
5 | import com.koushikdutta.async.callback.CompletedCallback;
6 | import com.koushikdutta.async.future.Future;
7 |
8 | import org.json.JSONObject;
9 |
10 | import java.lang.reflect.Type;
11 |
12 | /**
13 | * Created by koush on 5/27/13.
14 | */
15 | public class JSONObjectParser implements AsyncParser {
16 | @Override
17 | public Future parse(DataEmitter emitter) {
18 | return new StringParser().parse(emitter).thenConvert(JSONObject::new);
19 | }
20 |
21 | @Override
22 | public void write(DataSink sink, JSONObject value, CompletedCallback completed) {
23 | new StringParser().write(sink, value.toString(), completed);
24 | }
25 |
26 | @Override
27 | public Type getType() {
28 | return JSONObject.class;
29 | }
30 |
31 | @Override
32 | public String getMime() {
33 | return "application/json";
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/parser/StringParser.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.parser;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.DataEmitter;
5 | import com.koushikdutta.async.DataSink;
6 | import com.koushikdutta.async.callback.CompletedCallback;
7 | import com.koushikdutta.async.future.Future;
8 |
9 | import java.lang.reflect.Type;
10 | import java.nio.charset.Charset;
11 |
12 | /**
13 | * Created by koush on 5/27/13.
14 | */
15 | public class StringParser implements AsyncParser {
16 | Charset forcedCharset;
17 |
18 | public StringParser() {
19 | }
20 |
21 | public StringParser(Charset charset) {
22 | this.forcedCharset = charset;
23 | }
24 |
25 | @Override
26 | public Future parse(DataEmitter emitter) {
27 | final String charset = emitter.charset();
28 | return new ByteBufferListParser().parse(emitter)
29 | .thenConvert(from -> {
30 | Charset charsetToUse = forcedCharset;
31 | if (charsetToUse == null && charset != null)
32 | charsetToUse = Charset.forName(charset);
33 | return from.readString(charsetToUse);
34 | });
35 | }
36 |
37 | @Override
38 | public void write(DataSink sink, String value, CompletedCallback completed) {
39 | new ByteBufferListParser().write(sink, new ByteBufferList(value.getBytes()), completed);
40 | }
41 |
42 | @Override
43 | public Type getType() {
44 | return String.class;
45 | }
46 |
47 | @Override
48 | public String getMime() {
49 | return null;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/stream/ByteBufferListInputStream.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.stream;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 |
8 | /**
9 | * Created by koush on 6/1/13.
10 | */
11 | public class ByteBufferListInputStream extends InputStream {
12 | ByteBufferList bb;
13 | public ByteBufferListInputStream(ByteBufferList bb) {
14 | this.bb = bb;
15 | }
16 |
17 | @Override
18 | public int read() throws IOException {
19 | if (bb.remaining() <= 0)
20 | return -1;
21 | return (int)bb.get() & 0x000000ff;
22 | }
23 |
24 | @Override
25 | public int read(byte[] buffer) throws IOException {
26 | return this.read(buffer, 0, buffer.length);
27 | }
28 |
29 | @Override
30 | public int read(byte[] buffer, int offset, int length) throws IOException {
31 | if (bb.remaining() <= 0)
32 | return -1;
33 | int toRead = Math.min(length, bb.remaining());
34 | bb.get(buffer, offset, toRead);
35 | return toRead;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/stream/FileDataSink.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.stream;
2 |
3 | import com.koushikdutta.async.AsyncServer;
4 |
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.OutputStream;
9 |
10 | /**
11 | * Created by koush on 2/2/14.
12 | */
13 | public class FileDataSink extends OutputStreamDataSink {
14 | File file;
15 | public FileDataSink(AsyncServer server, File file) {
16 | super(server);
17 | this.file = file;
18 | }
19 |
20 | @Override
21 | public OutputStream getOutputStream() throws IOException {
22 | OutputStream ret = super.getOutputStream();
23 | if (ret == null) {
24 | file.getParentFile().mkdirs();
25 | ret = new FileOutputStream(file);
26 | setOutputStream(ret);
27 | }
28 | return ret;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataCallback.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.stream;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 |
7 | import com.koushikdutta.async.ByteBufferList;
8 | import com.koushikdutta.async.DataEmitter;
9 | import com.koushikdutta.async.callback.CompletedCallback;
10 | import com.koushikdutta.async.callback.DataCallback;
11 |
12 | public class OutputStreamDataCallback implements DataCallback, CompletedCallback {
13 | private OutputStream mOutput;
14 | public OutputStreamDataCallback(OutputStream os) {
15 | mOutput = os;
16 | }
17 |
18 | public OutputStream getOutputStream() {
19 | return mOutput;
20 | }
21 |
22 | @Override
23 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
24 | try {
25 | while (bb.size() > 0) {
26 | ByteBuffer b = bb.remove();
27 | mOutput.write(b.array(), b.arrayOffset() + b.position(), b.remaining());
28 | ByteBufferList.reclaim(b);
29 | }
30 | }
31 | catch (Exception ex) {
32 | onCompleted(ex);
33 | }
34 | finally {
35 | bb.recycle();
36 | }
37 | }
38 |
39 | public void close() {
40 | try {
41 | mOutput.close();
42 | }
43 | catch (IOException e) {
44 | onCompleted(e);
45 | }
46 | }
47 |
48 | @Override
49 | public void onCompleted(Exception error) {
50 | error.printStackTrace();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/stream/OutputStreamDataSink.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.stream;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.nio.ByteBuffer;
6 |
7 | import com.koushikdutta.async.AsyncServer;
8 | import com.koushikdutta.async.ByteBufferList;
9 | import com.koushikdutta.async.DataSink;
10 | import com.koushikdutta.async.callback.CompletedCallback;
11 | import com.koushikdutta.async.callback.WritableCallback;
12 |
13 | public class OutputStreamDataSink implements DataSink {
14 | public OutputStreamDataSink(AsyncServer server) {
15 | this(server, null);
16 | }
17 |
18 | @Override
19 | public void end() {
20 | try {
21 | if (mStream != null)
22 | mStream.close();
23 | reportClose(null);
24 | }
25 | catch (IOException e) {
26 | reportClose(e);
27 | }
28 | }
29 |
30 | AsyncServer server;
31 | public OutputStreamDataSink(AsyncServer server, OutputStream stream) {
32 | this.server = server;
33 | setOutputStream(stream);
34 | }
35 |
36 | OutputStream mStream;
37 | public void setOutputStream(OutputStream stream) {
38 | mStream = stream;
39 | }
40 |
41 | public OutputStream getOutputStream() throws IOException {
42 | return mStream;
43 | }
44 |
45 | @Override
46 | public void write(final ByteBufferList bb) {
47 | try {
48 | while (bb.size() > 0) {
49 | ByteBuffer b = bb.remove();
50 | getOutputStream().write(b.array(), b.arrayOffset() + b.position(), b.remaining());
51 | ByteBufferList.reclaim(b);
52 | }
53 | }
54 | catch (IOException e) {
55 | reportClose(e);
56 | }
57 | finally {
58 | bb.recycle();
59 | }
60 | }
61 |
62 | WritableCallback mWritable;
63 | @Override
64 | public void setWriteableCallback(WritableCallback handler) {
65 | mWritable = handler;
66 | }
67 |
68 | @Override
69 | public WritableCallback getWriteableCallback() {
70 | return mWritable;
71 | }
72 |
73 | @Override
74 | public boolean isOpen() {
75 | return closeReported;
76 | }
77 |
78 | boolean closeReported;
79 | Exception closeException;
80 | public void reportClose(Exception ex) {
81 | if (closeReported)
82 | return;
83 | closeReported = true;
84 | closeException = ex;
85 |
86 | if (mClosedCallback != null)
87 | mClosedCallback.onCompleted(closeException);
88 | }
89 |
90 | CompletedCallback mClosedCallback;
91 | @Override
92 | public void setClosedCallback(CompletedCallback handler) {
93 | mClosedCallback = handler;
94 | }
95 |
96 | @Override
97 | public CompletedCallback getClosedCallback() {
98 | return mClosedCallback;
99 | }
100 |
101 | @Override
102 | public AsyncServer getServer() {
103 | return server;
104 | }
105 |
106 | WritableCallback outputStreamCallback;
107 | public void setOutputStreamWritableCallback(WritableCallback outputStreamCallback) {
108 | this.outputStreamCallback = outputStreamCallback;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/Allocator.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 |
5 | import java.nio.ByteBuffer;
6 |
7 | /**
8 | * Created by koush on 6/28/14.
9 | */
10 | public class Allocator {
11 | final int maxAlloc;
12 | int currentAlloc = 0;
13 | int minAlloc = 2 << 11;
14 |
15 | public Allocator(int maxAlloc) {
16 | this.maxAlloc = maxAlloc;
17 | }
18 |
19 | public Allocator() {
20 | maxAlloc = ByteBufferList.MAX_ITEM_SIZE;
21 | }
22 |
23 | public ByteBuffer allocate() {
24 | return allocate(currentAlloc);
25 | }
26 |
27 | public ByteBuffer allocate(int currentAlloc) {
28 | return ByteBufferList.obtain(Math.min(Math.max(currentAlloc, minAlloc), maxAlloc));
29 | }
30 |
31 | public void track(long read) {
32 | currentAlloc = (int)read * 2;
33 | }
34 |
35 | public int getMaxAlloc() {
36 | return maxAlloc;
37 | }
38 |
39 | public void setCurrentAlloc(int currentAlloc) {
40 | this.currentAlloc = currentAlloc;
41 | }
42 |
43 | public int getMinAlloc() {
44 | return minAlloc;
45 | }
46 |
47 | public Allocator setMinAlloc(int minAlloc ) {
48 | this.minAlloc = Math.max(0, minAlloc);
49 | return this;
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/Charsets.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import java.nio.charset.Charset;
4 |
5 | /** From java.nio.charset.Charsets */
6 | public class Charsets {
7 | public static final Charset US_ASCII = Charset.forName("US-ASCII");
8 | public static final Charset UTF_8 = Charset.forName("UTF-8");
9 | public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
10 | }
11 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/FileUtility.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * Created by koush on 4/7/14.
7 | */
8 | public class FileUtility {
9 | static public boolean deleteDirectory(File path) {
10 | if (path.exists()) {
11 | File[] files = path.listFiles();
12 | if (files != null) {
13 | for (int i = 0; i < files.length; i++) {
14 | if (files[i].isDirectory()) {
15 | deleteDirectory(files[i]);
16 | }
17 | else {
18 | files[i].delete();
19 | }
20 | }
21 | }
22 | }
23 | return (path.delete());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/HashList.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Hashtable;
5 | import java.util.Set;
6 |
7 | /**
8 | * Created by koush on 5/27/13.
9 | */
10 | public class HashList {
11 | Hashtable> internal = new Hashtable>();
12 |
13 | public HashList() {
14 | }
15 |
16 | public Set keySet() {
17 | return internal.keySet();
18 | }
19 |
20 | public synchronized V tag(String key) {
21 | TaggedList list = internal.get(key);
22 | if (list == null)
23 | return null;
24 | return list.tag();
25 | }
26 |
27 | public synchronized void tag(String key, V tag) {
28 | TaggedList list = internal.get(key);
29 | if (list == null) {
30 | list = new TaggedList();
31 | internal.put(key, list);
32 | }
33 | list.tag(tag);
34 | }
35 |
36 | public synchronized ArrayList remove(String key) {
37 | return internal.remove(key);
38 | }
39 |
40 | public synchronized int size() {
41 | return internal.size();
42 | }
43 |
44 | public synchronized ArrayList get(String key) {
45 | return internal.get(key);
46 | }
47 |
48 | synchronized public boolean contains(String key) {
49 | ArrayList check = get(key);
50 | return check != null && check.size() > 0;
51 | }
52 |
53 | synchronized public void add(String key, T value) {
54 | ArrayList ret = get(key);
55 | if (ret == null) {
56 | TaggedList put = new TaggedList();
57 | ret = put;
58 | internal.put(key, put);
59 | }
60 | ret.add(value);
61 | }
62 |
63 | synchronized public T pop(String key) {
64 | TaggedList values = internal.get(key);
65 | if (values == null)
66 | return null;
67 | if (values.size() == 0)
68 | return null;
69 | return values.remove(values.size() - 1);
70 | }
71 |
72 | synchronized public boolean removeItem(String key, T value) {
73 | TaggedList values = internal.get(key);
74 | if (values == null)
75 | return false;
76 |
77 | values.remove(value);
78 | return values.size() == 0;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/IdleTimeout.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import android.os.Handler;
4 |
5 | import com.koushikdutta.async.AsyncServer;
6 |
7 | public class IdleTimeout extends TimeoutBase {
8 | Runnable callback;
9 |
10 | public IdleTimeout(AsyncServer server, long delay) {
11 | super(server, delay);
12 |
13 | }
14 |
15 | public IdleTimeout(Handler handler, long delay) {
16 | super(handler, delay);
17 | }
18 |
19 | public void setTimeout(Runnable callback) {
20 | this.callback = callback;
21 | }
22 |
23 | Object cancellable;
24 | public void reset() {
25 | handlerish.removeAllCallbacks(cancellable);
26 | cancellable = handlerish.postDelayed(callback, delay);
27 | }
28 |
29 | public void cancel() {
30 | // must post this, so that when it runs it removes everything in the queue,
31 | // preventing any rescheduling.
32 | // posting gaurantees there is not a reschedule in progress.
33 | handlerish.post(() -> handlerish.removeAllCallbacks(cancellable));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/TaggedList.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class TaggedList extends ArrayList {
6 | private Object tag;
7 |
8 | public synchronized V tag() {
9 | return (V)tag;
10 | }
11 |
12 | public synchronized void tag(V tag) {
13 | this.tag = tag;
14 | }
15 |
16 | public synchronized void tagNull(V tag) {
17 | if (this.tag == null)
18 | this.tag = tag;
19 | }
20 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/ThrottleTimeout.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import android.os.Handler;
4 |
5 | import com.koushikdutta.async.AsyncServer;
6 | import com.koushikdutta.async.callback.ValueCallback;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * Created by koush on 7/19/16.
13 | */
14 | public class ThrottleTimeout extends TimeoutBase {
15 | ValueCallback> callback;
16 | ArrayList values = new ArrayList<>();
17 | ThrottleMode throttleMode = ThrottleMode.Collect;
18 |
19 | public enum ThrottleMode {
20 | /**
21 | * The timeout will keep resetting until it expires, at which point all
22 | * the collected values will be invoked on the callback.
23 | */
24 | Collect,
25 | /**
26 | * The callback will be invoked immediately with the first, but future values will be
27 | * metered until it expires.
28 | */
29 | Meter,
30 | }
31 |
32 |
33 | public ThrottleTimeout(final AsyncServer server, long delay, ValueCallback> callback) {
34 | super(server, delay);
35 | this.callback = callback;
36 | }
37 |
38 | public ThrottleTimeout(final Handler handler, long delay, ValueCallback> callback) {
39 | super(handler, delay);
40 | this.callback = callback;
41 | }
42 |
43 | public void setCallback(ValueCallback> callback) {
44 | this.callback = callback;
45 | }
46 |
47 | private void runCallback() {
48 | cancellable = null;
49 | ArrayList v = new ArrayList<>(values);
50 | values.clear();
51 | callback.onResult(v);
52 | }
53 |
54 | Object cancellable;
55 | public synchronized void postThrottled(final T value) {
56 | handlerish.post(() -> {
57 | values.add(value);
58 |
59 | if (throttleMode == ThrottleMode.Collect) {
60 | // cancel the existing, schedule a new one, and wait.
61 | handlerish.removeAllCallbacks(cancellable);
62 | cancellable = handlerish.postDelayed(this::runCallback, delay);
63 | }
64 | else {
65 | // nothing is pending, so this can be fired off immediately
66 | if (cancellable == null) {
67 | runCallback();
68 |
69 | // meter future invocations
70 | cancellable = handlerish.postDelayed(this::runCallback, delay);
71 | }
72 | }
73 | });
74 | }
75 |
76 | public void setThrottleMode(ThrottleMode throttleMode) {
77 | this.throttleMode = throttleMode;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/TimeoutBase.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import android.os.Handler;
4 |
5 | import com.koushikdutta.async.AsyncServer;
6 | import com.koushikdutta.async.future.Cancellable;
7 |
8 | public class TimeoutBase {
9 | protected Handlerish handlerish;
10 | protected long delay;
11 |
12 | interface Handlerish {
13 | void post(Runnable r);
14 | Object postDelayed(Runnable r, long delay);
15 | void removeAllCallbacks(Object cancellable);
16 | }
17 |
18 | protected void onCallback() {
19 |
20 | }
21 |
22 | public TimeoutBase(final AsyncServer server, long delay) {
23 | this.delay = delay;
24 | this.handlerish = new Handlerish() {
25 | @Override
26 | public void post(Runnable r) {
27 | server.post(r);
28 | }
29 |
30 | @Override
31 | public Object postDelayed(Runnable r, long delay) {
32 | return server.postDelayed(r, delay);
33 | }
34 |
35 | @Override
36 | public void removeAllCallbacks(Object cancellable) {
37 | if (cancellable == null)
38 | return;
39 | ((Cancellable)cancellable).cancel();
40 | }
41 | };
42 | }
43 |
44 | public TimeoutBase(final Handler handler, long delay) {
45 | this.delay = delay;
46 | this.handlerish = new Handlerish() {
47 | @Override
48 | public void post(Runnable r) {
49 | handler.post(r);
50 | }
51 |
52 | @Override
53 | public Object postDelayed(Runnable r, long delay) {
54 | handler.postDelayed(r, delay);
55 | return r;
56 | }
57 |
58 | @Override
59 | public void removeAllCallbacks(Object cancellable) {
60 | if (cancellable == null)
61 | return;
62 | handler.removeCallbacks((Runnable)cancellable);
63 | }
64 | };
65 | }
66 |
67 | public void setDelay(long delay) {
68 | this.delay = delay;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/util/UntypedHashtable.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.util;
2 |
3 | import java.util.Hashtable;
4 |
5 | public class UntypedHashtable {
6 | private Hashtable hash = new Hashtable();
7 |
8 | public void put(String key, Object value) {
9 | hash.put(key, value);
10 | }
11 |
12 | public void remove(String key) {
13 | hash.remove(key);
14 | }
15 |
16 | public T get(String key, T defaultValue) {
17 | T ret = get(key);
18 | if (ret == null)
19 | return defaultValue;
20 | return ret;
21 | }
22 |
23 | public T get(String key) {
24 | return (T)hash.get(key);
25 | }
26 | }
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/wrapper/AsyncSocketWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.wrapper;
2 |
3 | import com.koushikdutta.async.AsyncSocket;
4 |
5 | public interface AsyncSocketWrapper extends AsyncSocket, DataEmitterWrapper {
6 | public AsyncSocket getSocket();
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/src/com/koushikdutta/async/wrapper/DataEmitterWrapper.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.wrapper;
2 |
3 | import com.koushikdutta.async.DataEmitter;
4 |
5 | public interface DataEmitterWrapper extends DataEmitter {
6 | public DataEmitter getDataEmitter();
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidAsync/test/assets/6691924d7d24237d3b3679310157d640:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/test/assets/6691924d7d24237d3b3679310157d640
--------------------------------------------------------------------------------
/AndroidAsync/test/assets/hello.txt:
--------------------------------------------------------------------------------
1 | hello world
--------------------------------------------------------------------------------
/AndroidAsync/test/assets/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": "bar"
3 | }
--------------------------------------------------------------------------------
/AndroidAsync/test/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/test/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsync/test/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/test/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsync/test/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/test/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsync/test/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/test/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsync/test/res/raw/keystore.bks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsync/test/res/raw/keystore.bks
--------------------------------------------------------------------------------
/AndroidAsync/test/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AndroidAsyncTestTest
5 |
6 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/BodyTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import androidx.test.runner.AndroidJUnit4;
4 |
5 | import com.koushikdutta.async.http.Multimap;
6 | import com.koushikdutta.async.http.body.UrlEncodedFormBody;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | /**
12 | * Created by koush on 3/19/14.
13 | */
14 | @RunWith(AndroidJUnit4.class)
15 | public class BodyTests {
16 | @Test
17 | public void testNullValue() throws Exception {
18 | Multimap mm = new Multimap();
19 | mm.add("hello", null);
20 | UrlEncodedFormBody body = new UrlEncodedFormBody(mm);
21 |
22 | int length = body.length();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/ByteUtilTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.FilteredDataEmitter;
5 | import com.koushikdutta.async.PushParser;
6 | import com.koushikdutta.async.TapCallback;
7 | import com.koushikdutta.async.Util;
8 | import com.koushikdutta.async.callback.DataCallback;
9 |
10 | import junit.framework.TestCase;
11 |
12 | /**
13 | * Created by koush on 5/17/13.
14 | */
15 | public class ByteUtilTests extends TestCase {
16 | int valRead;
17 | public void testPushParserUntil() {
18 | valRead = 0;
19 | FilteredDataEmitter mock = new FilteredDataEmitter() {
20 | @Override
21 | public boolean isPaused() {
22 | return false;
23 | }
24 | };
25 | new PushParser(mock)
26 | .until((byte)0, new DataCallback.NullDataCallback())
27 | .readInt(new PushParser.ParseCallback() {
28 | public void parsed(Integer arg) {
29 | valRead = arg;
30 | }
31 | });
32 | byte[] bytes = new byte[] { 5, 5, 5, 5, 0, 10, 5, 5, 5 };
33 | Util.emitAllData(mock, new ByteBufferList(bytes));
34 | assertEquals(valRead, 0x0A050505);
35 | }
36 |
37 | public void testPushParserTapUntil() {
38 | valRead = 0;
39 | FilteredDataEmitter mock = new FilteredDataEmitter() {
40 | @Override
41 | public boolean isPaused() {
42 | return false;
43 | }
44 | };
45 | new PushParser(mock)
46 | .until((byte)0, new DataCallback.NullDataCallback())
47 | .readInt()
48 | .tap(new TapCallback() {
49 | public void parsed(int arg) {
50 | valRead = arg;
51 | }
52 | });
53 | byte[] bytes = new byte[] { 5, 5, 5, 5, 0, 10, 5, 5, 5 };
54 | Util.emitAllData(mock, new ByteBufferList(bytes));
55 | assertEquals(valRead, 0x0A050505);
56 | }
57 |
58 | int readInt;
59 | byte readByte;
60 | String readString;
61 |
62 | public void testTapCallback() {
63 | readInt = 0;
64 | readByte = 0;
65 | readString = "";
66 |
67 | FilteredDataEmitter mock = new FilteredDataEmitter() {
68 | @Override
69 | public boolean isPaused() {
70 | return false;
71 | }
72 | };
73 | new PushParser(mock)
74 | .readInt()
75 | .readByte()
76 | .readString()
77 | .tap(new TapCallback() {
78 | void tap(int i, byte b, String s) {
79 | readInt = i;
80 | readByte = b;
81 | readString = s;
82 | }
83 | });
84 |
85 | byte[] bytes = new byte[] { 10, 5, 5, 5, 3, 0, 0, 0, 4, 116, 101, 115, 116 };
86 | Util.emitAllData(mock, new ByteBufferList(bytes));
87 | assertEquals(readInt, 0x0A050505);
88 | assertEquals(readByte, (byte) 3);
89 | assertEquals(readString, "test");
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/ConvertTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import androidx.test.runner.AndroidJUnit4;
4 |
5 | import com.koushikdutta.async.future.SimpleFuture;
6 |
7 | import org.json.JSONObject;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import java.nio.ByteBuffer;
12 |
13 | import static com.koushikdutta.async.future.Converter.convert;
14 | import static org.junit.Assert.assertEquals;
15 |
16 | @RunWith(AndroidJUnit4.class)
17 | public class ConvertTests {
18 | @Test
19 | public void testConvert() throws Exception {
20 | ByteBuffer buf = convert(new SimpleFuture<>(new JSONObject()))
21 | .to(ByteBuffer.class)
22 | .get();
23 |
24 | assertEquals(buf.remaining(), 2);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/DnsTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.AsyncDatagramSocket;
4 | import com.koushikdutta.async.AsyncServer;
5 | import com.koushikdutta.async.AsyncSocket;
6 | import com.koushikdutta.async.ByteBufferList;
7 | import com.koushikdutta.async.DataEmitter;
8 | import com.koushikdutta.async.callback.ConnectCallback;
9 | import com.koushikdutta.async.callback.DataCallback;
10 | import com.koushikdutta.async.dns.Dns;
11 | import com.koushikdutta.async.dns.DnsResponse;
12 | import com.koushikdutta.async.future.FutureCallback;
13 |
14 | import junit.framework.TestCase;
15 |
16 | import java.net.DatagramPacket;
17 | import java.net.DatagramSocket;
18 | import java.net.Inet4Address;
19 | import java.net.InetAddress;
20 | import java.net.InetSocketAddress;
21 | import java.net.MulticastSocket;
22 | import java.net.UnknownHostException;
23 | import java.nio.channels.DatagramChannel;
24 | import java.util.concurrent.Semaphore;
25 | import java.util.concurrent.TimeUnit;
26 |
27 | /**
28 | * Created by koush on 10/20/13.
29 | */
30 | public class DnsTests extends TestCase {
31 | public void testLookup() throws Exception {
32 | // final Semaphore semaphore = new Semaphore(0);
33 | // Dns.lookup("google.com")
34 | // .setCallback(new FutureCallback() {
35 | // @Override
36 | // public void onCompleted(Exception e, DnsResponse result) {
37 | // semaphore.release();
38 | // }
39 | // });
40 | //
41 | // semaphore.tryAcquire(1000000, TimeUnit.MILLISECONDS);
42 | }
43 |
44 | public void testMulticastLookup() throws Exception {
45 | // MulticastSocket socket = new MulticastSocket(5353);
46 | // socket.joinGroup(InetAddress.getByName("224.0.0.251"));
47 | // DatagramChannel channel = socket.getChannel();
48 | // assertNotNull(channel);
49 |
50 | // while (true) {
51 | // DatagramPacket packet = new DatagramPacket(new byte[2048], 2048);
52 | // socket.receive(packet);
53 | // System.out.println(new String(packet.getData()));
54 | // }
55 |
56 | // AsyncDatagramSocket dgram = AsyncServer.getDefault().openDatagram(new InetSocketAddress(5353), true);
57 | // ((DatagramSocket)dgram.getSocket()).setReuseAddress(true);
58 | // dgram.setDataCallback(new DataCallback() {
59 | // @Override
60 | // public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
61 | // System.out.println(bb.readString());
62 | // }
63 | // });
64 | // ((DatagramSocket)dgram.getSocket()).setBroadcast(true);
65 |
66 |
67 | // final Semaphore semaphore = new Semaphore(0);
68 | // Dns.multicastLookup("_airplay._tcp.local", new FutureCallback() {
69 | // @Override
70 | // public void onCompleted(Exception e, DnsResponse result) {
71 | //// semaphore.release();
72 | // }
73 | // });
74 | //
75 | // semaphore.tryAcquire(1000000, TimeUnit.MILLISECONDS);
76 | }
77 |
78 | public void testNoDomain() throws Exception {
79 | AsyncServer server = new AsyncServer();
80 |
81 | try {
82 | final Semaphore semaphore = new Semaphore(0);
83 | server.connectSocket("www.clockworkmod-notfound.com", 8080, new ConnectCallback() {
84 | @Override
85 | public void onConnectCompleted(Exception ex, AsyncSocket socket) {
86 | assertTrue(ex instanceof UnknownHostException);
87 | semaphore.release();
88 | }
89 | });
90 | assertTrue(semaphore.tryAcquire(5000, TimeUnit.MILLISECONDS));
91 | }
92 | finally {
93 | server.stop();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/FileTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 |
4 | import androidx.test.runner.AndroidJUnit4;
5 |
6 | import com.koushikdutta.async.AsyncServer;
7 | import com.koushikdutta.async.FileDataEmitter;
8 | import com.koushikdutta.async.future.Future;
9 | import com.koushikdutta.async.future.FutureCallback;
10 | import com.koushikdutta.async.parser.StringParser;
11 | import com.koushikdutta.async.util.StreamUtility;
12 |
13 | import org.junit.runner.RunWith;
14 |
15 | import java.io.File;
16 | import java.util.concurrent.Semaphore;
17 | import java.util.concurrent.TimeUnit;
18 |
19 | import static androidx.test.InstrumentationRegistry.getContext;
20 | import static org.junit.Assert.assertEquals;
21 | import static org.junit.Assert.assertTrue;
22 |
23 | /**
24 | * Created by koush on 5/22/13.
25 | */
26 | @RunWith(AndroidJUnit4.class)
27 | public class FileTests {
28 | public static final long TIMEOUT = 1000L;
29 | public void testFileDataEmitter() throws Exception {
30 | final Semaphore semaphore = new Semaphore(0);
31 | File f = getContext().getFileStreamPath("test.txt");
32 | StreamUtility.writeFile(f, "hello world");
33 | FileDataEmitter fdm = new FileDataEmitter(AsyncServer.getDefault(), f);
34 | final Md5 md5 = Md5.createInstance();
35 | Future stringBody = new StringParser().parse(fdm);
36 | stringBody
37 | .setCallback(new FutureCallback() {
38 | @Override
39 | public void onCompleted(Exception e, String result) {
40 | semaphore.release();
41 | }
42 | });
43 | fdm.resume();
44 |
45 | assertTrue("timeout", semaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS));
46 | assertEquals("hello world", stringBody.get());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/Issue59.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import android.util.Log;
4 |
5 | import com.koushikdutta.async.AsyncServer;
6 | import com.koushikdutta.async.ByteBufferList;
7 | import com.koushikdutta.async.Util;
8 | import com.koushikdutta.async.callback.CompletedCallback;
9 | import com.koushikdutta.async.http.AsyncHttpClient;
10 | import com.koushikdutta.async.http.AsyncHttpGet;
11 | import com.koushikdutta.async.http.server.AsyncHttpServer;
12 | import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
13 | import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
14 | import com.koushikdutta.async.http.server.HttpServerRequestCallback;
15 |
16 | import junit.framework.TestCase;
17 |
18 | import java.util.concurrent.TimeUnit;
19 |
20 | /**
21 | * Created by koush on 8/31/13.
22 | */
23 | public class Issue59 extends TestCase {
24 | public void testIssue() throws Exception {
25 | AsyncHttpServer httpServer = new AsyncHttpServer();
26 | try {
27 | httpServer.get("/", new HttpServerRequestCallback() {
28 | @Override
29 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
30 | // setting this to empty is a hacky way of telling the framework not to use
31 | // transfer-encoding. It will get removed.
32 | response.getHeaders().set("Transfer-Encoding", "");
33 | response.code(200);
34 | Util.writeAll(response, "foobarbeepboop".getBytes(), new CompletedCallback() {
35 | @Override
36 | public void onCompleted(Exception ex) {
37 | response.end();
38 | }
39 | });
40 | }
41 | });
42 |
43 | httpServer.listen(5959);
44 |
45 | AsyncHttpGet get = new AsyncHttpGet("http://localhost:5959/");
46 | get.setLogging("issue59", Log.VERBOSE);
47 | get.getHeaders().removeAll("Connection");
48 | get.getHeaders().removeAll("Accept-Encoding");
49 |
50 | assertEquals("foobarbeepboop", AsyncHttpClient.getDefaultInstance().executeString(get, null).get(1000, TimeUnit.MILLISECONDS));
51 | }
52 | finally {
53 | httpServer.stop();
54 | AsyncServer.getDefault().stop();
55 | }
56 | }
57 |
58 | public void testIon428() throws Exception {
59 | ByteBufferList bb = AsyncHttpClient.getDefaultInstance().executeByteBufferList(new AsyncHttpGet("https://cdn2.vox-cdn.com/thumbor/KxtZNw37jKNfxdA0hX5edHvbTBE=/0x0:2039x1359/800x536/cdn0.vox-cdn.com/uploads/chorus_image/image/44254028/lg-g-watch.0.0.jpg"), null)
60 | .get();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/IssueWithWebSocketFuturesTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.future.Future;
4 | import com.koushikdutta.async.http.AsyncHttpClient;
5 | import com.koushikdutta.async.http.WebSocket;
6 | import com.koushikdutta.async.http.server.AsyncHttpServer;
7 | import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
8 |
9 | import junit.framework.TestCase;
10 |
11 | import java.util.concurrent.CountDownLatch;
12 |
13 |
14 | public class IssueWithWebSocketFuturesTests extends TestCase {
15 |
16 | //testing that websocket callback gets called with the correct parameters.
17 | public void testWebSocketFutureWithHandshakeFailureCallback() throws Exception {
18 |
19 | //creating a faulty server!
20 | AsyncHttpServer httpServer = new AsyncHttpServer();
21 | httpServer.websocket(".*", new AsyncHttpServer.WebSocketRequestCallback() {
22 | @Override
23 | public void onConnected(WebSocket webSocket, AsyncHttpServerRequest request) {
24 |
25 | }
26 | });
27 | httpServer.listen(6666);
28 |
29 |
30 |
31 | final Exception[] callbackException = {null};
32 | final WebSocket[] callbackWs = {null};
33 | final CountDownLatch countDownLatch = new CountDownLatch(1);
34 |
35 |
36 | //for some reason, it fails with a WebSocketHandshakeException.
37 | //But in general, if the handshake fails, the callback must be called with an exception.
38 | Future wsFuture = AsyncHttpClient.getDefaultInstance().websocket("ws://127.0.0.1:6666", "ws", new AsyncHttpClient.WebSocketConnectCallback() {
39 | @Override
40 | public void onCompleted(Exception ex, WebSocket webSocket) {
41 | callbackException[0] = ex;
42 | callbackWs[0] = webSocket;
43 | countDownLatch.countDown();
44 | }
45 | });
46 |
47 |
48 | //wait for the future to complete
49 | countDownLatch.await();
50 |
51 | //exactly one mut be null
52 | assertTrue(callbackWs[0] == null ^ callbackException[0] == null);
53 |
54 | //callback parameters must be the same as the future's result
55 | assertEquals(wsFuture.tryGet(), callbackWs[0]);
56 | assertEquals(wsFuture.tryGetException(), callbackException[0]);
57 |
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/LineEmitterTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.LineEmitter;
5 | import com.koushikdutta.async.util.Charsets;
6 |
7 | import junit.framework.TestCase;
8 |
9 | import java.nio.ByteBuffer;
10 | import java.nio.charset.Charset;
11 | import java.util.concurrent.Semaphore;
12 |
13 | /**
14 | * Created by koush on 6/9/16.
15 | */
16 | public class LineEmitterTests extends TestCase {
17 | public void testFunnyCharacter() {
18 | final String stuff = "é\n";
19 | LineEmitter emitter = new LineEmitter(Charsets.UTF_8);
20 | emitter.setLineCallback(new LineEmitter.StringCallback() {
21 | @Override
22 | public void onStringAvailable(String s) {
23 | assertEquals(s + '\n', stuff);
24 | }
25 | });
26 |
27 |
28 | assertEquals(stuff.charAt(0), 233);
29 | ByteBufferList bb = new ByteBufferList(ByteBuffer.wrap(stuff.getBytes(Charsets.UTF_8)));
30 | emitter.onDataAvailable(null, bb);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/Md5.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 |
5 | import java.math.BigInteger;
6 | import java.nio.ByteBuffer;
7 | import java.security.MessageDigest;
8 | import java.security.NoSuchAlgorithmException;
9 |
10 | public class Md5 {
11 | private MessageDigest digest;
12 | public static Md5 createInstance() throws NoSuchAlgorithmException {
13 | Md5 md5 = new Md5();
14 | md5.digest = MessageDigest.getInstance("MD5");
15 | return md5;
16 | }
17 |
18 | private Md5() {
19 |
20 | }
21 | public void update(ByteBufferList bb) {
22 | while (bb.size() > 0) {
23 | ByteBuffer b = bb.remove();
24 | digest.update(b);
25 | }
26 | }
27 |
28 | public String digest() {
29 | String hash = new BigInteger(digest.digest()).toString(16);
30 | return hash;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/ParserTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.ByteBufferList;
4 | import com.koushikdutta.async.FilteredDataEmitter;
5 | import com.koushikdutta.async.future.Future;
6 | import com.koushikdutta.async.parser.DocumentParser;
7 | import com.koushikdutta.async.parser.StringParser;
8 | import com.koushikdutta.async.util.Charsets;
9 |
10 | import junit.framework.TestCase;
11 |
12 | import org.w3c.dom.Document;
13 |
14 | import java.nio.ByteBuffer;
15 | import java.nio.charset.Charset;
16 |
17 | /**
18 | * Created by koush on 7/10/14.
19 | */
20 | public class ParserTests extends TestCase {
21 | public void testString() throws Exception {
22 | StringParser p = new StringParser();
23 | FilteredDataEmitter f = new FilteredDataEmitter() {
24 | @Override
25 | public boolean isPaused() {
26 | return false;
27 | }
28 | };
29 | Future ret = p.parse(f);
30 | ByteBufferList l = new ByteBufferList();
31 | l.add(ByteBuffer.wrap("foo".getBytes(Charsets.US_ASCII.name())));
32 | f.onDataAvailable(f, l);
33 | f.getEndCallback().onCompleted(null);
34 | String s = ret.get();
35 | assertEquals(s, "foo");
36 | }
37 |
38 | public void testUtf8String() throws Exception {
39 | StringParser p = new StringParser();
40 | FilteredDataEmitter f = new FilteredDataEmitter() {
41 | @Override
42 | public String charset() {
43 | return Charsets.UTF_8.name();
44 | }
45 |
46 | @Override
47 | public boolean isPaused() {
48 | return false;
49 | }
50 | };
51 | Future ret = p.parse(f);
52 | ByteBufferList l = new ByteBufferList();
53 | l.add(ByteBuffer.wrap("æææ".getBytes(Charsets.UTF_8.name())));
54 | f.onDataAvailable(f, l);
55 | f.getEndCallback().onCompleted(null);
56 | String s = ret.get();
57 | assertEquals(s, "æææ");
58 | }
59 |
60 | public void testAsyncParserBase() throws Exception {
61 | DocumentParser parser = new DocumentParser();
62 | assertEquals(parser.getType(), Document.class);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/ProxyTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import android.util.Log;
4 |
5 | import com.koushikdutta.async.http.AsyncHttpClient;
6 | import com.koushikdutta.async.http.AsyncHttpGet;
7 |
8 | import junit.framework.TestCase;
9 |
10 | import java.util.concurrent.TimeUnit;
11 |
12 | /**
13 | * Created by koush on 4/20/14.
14 | */
15 | public class ProxyTests extends TestCase {
16 | private void disabledTestSSLProxy() throws Exception {
17 | AsyncHttpGet get = new AsyncHttpGet("http://yahoo.com");
18 | get.enableProxy("192.168.2.21", 8888);
19 | get.setLogging("SSLProxy", Log.VERBOSE);
20 | String ret = AsyncHttpClient.getDefaultInstance().executeString(get, null).get(5000, TimeUnit.DAYS.MILLISECONDS);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/RedirectTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.AsyncServer;
4 | import com.koushikdutta.async.http.AsyncHttpClient;
5 | import com.koushikdutta.async.http.AsyncHttpGet;
6 | import com.koushikdutta.async.http.server.AsyncHttpServer;
7 | import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
8 | import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
9 | import com.koushikdutta.async.http.server.HttpServerRequestCallback;
10 |
11 | import junit.framework.TestCase;
12 |
13 | /**
14 | * Created by koush on 11/4/13.
15 | */
16 | public class RedirectTests extends TestCase {
17 | @Override
18 | protected void setUp() throws Exception {
19 | super.setUp();
20 | AsyncHttpServer server = new AsyncHttpServer();
21 | server.listen(6003);
22 | server.get("/foo", new HttpServerRequestCallback() {
23 | @Override
24 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
25 | response.redirect("/bar");
26 | }
27 | });
28 | server.get("/bar", new HttpServerRequestCallback() {
29 | @Override
30 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
31 | response.send("BORAT!");
32 | }
33 | });
34 |
35 | server.get("/foo/poo", new HttpServerRequestCallback() {
36 | @Override
37 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
38 | response.redirect("../poo");
39 | }
40 | });
41 | server.get("/poo", new HttpServerRequestCallback() {
42 | @Override
43 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
44 | response.send("SWEET!");
45 | }
46 | });
47 | server.get("/foo/bar", new HttpServerRequestCallback() {
48 | @Override
49 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
50 | response.redirect("baz");
51 | }
52 | });
53 | server.get("/foo/baz", new HttpServerRequestCallback() {
54 | @Override
55 | public void onRequest(AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
56 | response.send("SUCCESS!");
57 | }
58 | });
59 | }
60 |
61 | @Override
62 | protected void tearDown() throws Exception {
63 | super.tearDown();
64 | AsyncServer.getDefault().stop();
65 | }
66 |
67 | public void testRelativeRedirect() throws Exception {
68 | String ret = AsyncHttpClient.getDefaultInstance()
69 | .executeString(new AsyncHttpGet("http://localhost:6003/foo/bar"), null)
70 | .get();
71 |
72 | assertEquals(ret, "SUCCESS!");
73 |
74 | ret = AsyncHttpClient.getDefaultInstance()
75 | .executeString(new AsyncHttpGet("http://localhost:6003/foo"), null)
76 | .get();
77 |
78 | assertEquals(ret, "BORAT!");
79 |
80 | ret = AsyncHttpClient.getDefaultInstance()
81 | .executeString(new AsyncHttpGet("http://localhost:6003/foo/poo"), null)
82 | .get();
83 |
84 | assertEquals(ret, "SWEET!");
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/SSLTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import androidx.test.runner.AndroidJUnit4;
4 |
5 | import com.koushikdutta.async.AsyncServer;
6 | import com.koushikdutta.async.http.AsyncHttpClient;
7 | import com.koushikdutta.async.http.AsyncHttpGet;
8 | import com.koushikdutta.async.http.server.AsyncHttpServer;
9 | import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
10 | import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
11 | import com.koushikdutta.async.http.server.HttpServerRequestCallback;
12 |
13 | import org.json.JSONObject;
14 | import org.junit.runner.RunWith;
15 |
16 | import java.security.KeyStore;
17 |
18 | import javax.net.ssl.KeyManagerFactory;
19 | import javax.net.ssl.SSLContext;
20 | import javax.net.ssl.TrustManagerFactory;
21 |
22 | import static androidx.test.InstrumentationRegistry.getContext;
23 |
24 | /**
25 | * Created by koush on 6/4/13.
26 | */
27 | @RunWith(AndroidJUnit4.class)
28 | public class SSLTests {
29 | public void testKeys() throws Exception {
30 | KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
31 | KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
32 |
33 | ks.load(getContext().getResources().openRawResource(R.raw.keystore), "storepass".toCharArray());
34 | kmf.init(ks, "storepass".toCharArray());
35 |
36 |
37 | TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
38 | KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
39 | ts.load(getContext().getResources().openRawResource(R.raw.keystore), "storepass".toCharArray());
40 | tmf.init(ts);
41 |
42 | SSLContext sslContext = SSLContext.getInstance("TLS");
43 | sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
44 |
45 | AsyncHttpServer httpServer = new AsyncHttpServer();
46 | httpServer.listenSecure(8888, sslContext);
47 | httpServer.get("/", new HttpServerRequestCallback() {
48 | @Override
49 | public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
50 | response.send("hello");
51 | }
52 | });
53 |
54 | Thread.sleep(1000);
55 |
56 | AsyncHttpClient.getDefaultInstance().getSSLSocketMiddleware().setSSLContext(sslContext);
57 | AsyncHttpClient.getDefaultInstance().getSSLSocketMiddleware().setTrustManagers(tmf.getTrustManagers());
58 | AsyncHttpClient.getDefaultInstance().executeString(new AsyncHttpGet("https://localhost:8888/"), null).get();
59 | }
60 |
61 | public void disabled__testClientCertificateIssue163() throws Exception {
62 | // https://security.springthroughtest.com/hello.json
63 |
64 | AsyncServer server = new AsyncServer();
65 | try {
66 | AsyncHttpClient client = new AsyncHttpClient(server);
67 | JSONObject json = client.executeJSONObject(new AsyncHttpGet("https://security.springthroughtest.com/hello.json"), null).get();
68 |
69 | }
70 | finally {
71 | server.stop();
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/SanityChecks.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import junit.framework.TestCase;
4 |
5 | import java.nio.ByteBuffer;
6 | import java.nio.ByteOrder;
7 |
8 | /**
9 | * Created by koush on 5/15/13.
10 | */
11 | public class SanityChecks extends TestCase {
12 | public void testByteOrder() {
13 | assertTrue(ByteBuffer.allocate(0).order().equals(ByteOrder.BIG_ENDIAN));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/TriggerFuture.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.future.SimpleFuture;
4 |
5 | class TriggerFuture extends SimpleFuture {
6 | public void trigger() {
7 | setComplete(2020);
8 | }
9 | }
--------------------------------------------------------------------------------
/AndroidAsync/test/src/com/koushikdutta/async/test/WebSocketTests.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.test;
2 |
3 | import com.koushikdutta.async.AsyncServer;
4 | import com.koushikdutta.async.callback.CompletedCallback;
5 | import com.koushikdutta.async.http.AsyncHttpClient;
6 | import com.koushikdutta.async.http.AsyncHttpClient.WebSocketConnectCallback;
7 | import com.koushikdutta.async.http.Headers;
8 | import com.koushikdutta.async.http.WebSocket;
9 | import com.koushikdutta.async.http.WebSocket.StringCallback;
10 | import com.koushikdutta.async.http.server.AsyncHttpServer;
11 | import com.koushikdutta.async.http.server.AsyncHttpServer.WebSocketRequestCallback;
12 | import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
13 |
14 | import junit.framework.TestCase;
15 |
16 | import org.junit.Test;
17 |
18 | import java.util.concurrent.Semaphore;
19 | import java.util.concurrent.TimeUnit;
20 |
21 | public class WebSocketTests extends TestCase {
22 | AsyncHttpServer httpServer;
23 |
24 | @Override
25 | protected void setUp() throws Exception {
26 | super.setUp();
27 |
28 | httpServer = new AsyncHttpServer();
29 | httpServer.setErrorCallback(new CompletedCallback() {
30 | @Override
31 | public void onCompleted(Exception ex) {
32 | fail();
33 | }
34 | });
35 | httpServer.listen(AsyncServer.getDefault(), 5000);
36 |
37 |
38 | httpServer.websocket("/ws", new WebSocketRequestCallback() {
39 | @Override
40 | public void onConnected(final WebSocket webSocket, AsyncHttpServerRequest request) {
41 | webSocket.setStringCallback(new StringCallback() {
42 | @Override
43 | public void onStringAvailable(String s) {
44 | webSocket.send(s);
45 | }
46 | });
47 | }
48 | });
49 | }
50 |
51 | private static final long TIMEOUT = 60000L;
52 | @Test
53 | public void testWebSocket() throws Exception {
54 | final Semaphore semaphore = new Semaphore(0);
55 |
56 | AsyncHttpClient.getDefaultInstance().websocket("http://localhost:5000/ws", (String)null, new WebSocketConnectCallback() {
57 | @Override
58 | public void onCompleted(Exception ex, WebSocket webSocket) {
59 | webSocket.send("hello");
60 | webSocket.setStringCallback(new StringCallback() {
61 | @Override
62 | public void onStringAvailable(String s) {
63 | assertEquals(s, "hello");
64 | semaphore.release();
65 | }
66 | });
67 | }
68 | });
69 |
70 | assertTrue(semaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS));
71 | }
72 |
73 | // public void testDisconnect() throws Exception {
74 | // final Semaphore semaphore = new Semaphore(0);
75 | //
76 | // AsyncHttpClient.getDefaultInstance().websocket("http://192.168.1.2:3005", null, new WebSocketConnectCallback() {
77 | // @Override
78 | // public void onCompleted(Exception ex, WebSocket webSocket) {
79 | // webSocket.setClosedCallback(new CompletedCallback() {
80 | // @Override
81 | // public void onCompleted(Exception ex) {
82 | // semaphore.release();
83 | // }
84 | // });
85 | // }
86 | // });
87 | //
88 | // assertTrue(semaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS));
89 | // }
90 |
91 | @Override
92 | protected void tearDown() throws Exception {
93 | super.tearDown();
94 |
95 | httpServer.stop();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
9 |
10 |
11 |
12 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | dependencies {
4 | compile project(':AndroidAsync')
5 | }
6 |
7 | android {
8 | sourceSets {
9 | main {
10 | manifest.srcFile 'AndroidManifest.xml'
11 | res.srcDirs = ['res/']
12 | java.srcDirs = ['src/']
13 | }
14 | }
15 |
16 | defaultConfig {
17 | targetSdkVersion 24
18 | minSdkVersion 9
19 | }
20 |
21 | compileSdkVersion project.hasProperty('global_compileSdkVersion') ? global_compileSdkVersion : 25
22 | buildToolsVersion project.hasProperty('global_buildToolsVersion') ? global_buildToolsVersion : '25.0.2'
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/ic_launcher-web.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/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 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 | android.library.reference.1=../AndroidAsync
16 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-hdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-hdpi/ic_action_search.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-mdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-mdpi/ic_action_search.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-xhdpi/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-xhdpi/ic_action_search.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koush/AndroidAsync/12f9e20443db5c8e79e7e4d43d9e2b3f4230266b/AndroidAsyncSample/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | AndroidAsyncSample
4 | Hello world!
5 | Settings
6 | AndroidAsync Sample
7 | Download Images
8 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/src/com/koushikdutta/async/sample/middleware/BasicAuthMiddleware.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.sample.middleware;
2 |
3 | import android.text.TextUtils;
4 | import android.util.Base64;
5 |
6 | import com.koushikdutta.async.http.AsyncHttpClient;
7 | import com.koushikdutta.async.http.SimpleMiddleware;
8 |
9 | import java.util.Hashtable;
10 |
11 | /**
12 | * Created by koush on 2/15/15.
13 | */
14 | public class BasicAuthMiddleware extends SimpleMiddleware {
15 | // insert this using
16 | public static BasicAuthMiddleware add(AsyncHttpClient client) {
17 | BasicAuthMiddleware ret = new BasicAuthMiddleware();
18 | client.getMiddleware().add(ret);
19 | return ret;
20 | }
21 |
22 | @Override
23 | public void onRequest(OnRequestData data) {
24 | super.onRequest(data);
25 | // do more checking here, since uri may not necessarily be http or have a host, etc.
26 | String auth = auths.get(data.request.getUri().getHost());
27 | if (!TextUtils.isEmpty(auth))
28 | data.request.setHeader("Authorization", auth);
29 | }
30 |
31 | Hashtable auths = new Hashtable();
32 | public void setAuthorizationForHost(String host, String username, String password) {
33 | String auth = "Basic " + Base64.encodeToString(String.format("%s:%s", username, password).getBytes(), Base64.NO_WRAP);
34 | auths.put(host, auth);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/AndroidAsyncSample/src/com/koushikdutta/async/sample/middleware/CacheOverrideMiddleware.java:
--------------------------------------------------------------------------------
1 | package com.koushikdutta.async.sample.middleware;
2 |
3 | import android.text.TextUtils;
4 | import android.util.Base64;
5 |
6 | import com.koushikdutta.async.http.AsyncHttpClient;
7 | import com.koushikdutta.async.http.AsyncHttpClientMiddleware;
8 | import com.koushikdutta.async.http.SimpleMiddleware;
9 |
10 | import java.util.Hashtable;
11 |
12 | /**
13 | * Created by koush on 2/15/15.
14 | */
15 | public class CacheOverrideMiddleware extends SimpleMiddleware {
16 | // insert this using
17 | public static CacheOverrideMiddleware add(AsyncHttpClient client) {
18 | CacheOverrideMiddleware ret = new CacheOverrideMiddleware();
19 | // add this first so it gets called before everything else
20 | client.getMiddleware().add(ret);
21 | return ret;
22 | }
23 |
24 | @Override
25 | public void onHeadersReceived(OnHeadersReceivedDataOnRequestSentData data) {
26 | super.onHeadersReceived(data);
27 |
28 | // do more checking here, since uri may not necessarily be http or have a host, etc.
29 | String cache = cacheHeaders.get(data.request.getUri().getHost());
30 | if (!TextUtils.isEmpty(cache))
31 | data.response.headers().set("Cache-Control", cache);
32 | }
33 |
34 | Hashtable cacheHeaders = new Hashtable();
35 |
36 | /**
37 | * Override cache-control directives
38 | * @param host
39 | * @param cacheControl a Cache-Control value, like "max-age=300" to cache for 5 minutes
40 | */
41 | public void setCacheControlForHost(String host, String cacheControl) {
42 | cacheHeaders.put(host, cacheControl);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2013 Koushik Dutta (2013)
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath project.hasProperty('global_gradleAndroidPlugin') ? global_gradleAndroidPlugin : 'com.android.tools.build:gradle:3.2.0'
9 | }
10 | }
11 |
12 | subprojects {
13 | repositories {
14 | jcenter()
15 | mavenCentral()
16 | google()
17 | }
18 |
19 | ext.global_compileSdkVersion = project.hasProperty('global_compileSdkVersion') ? global_compileSdkVersion : 28
20 | ext.global_buildToolsVersion = project.hasProperty('global_buildToolsVersion') ? global_buildToolsVersion : '28.0.3'
21 | ext.global_gradleAndroidPlugin = project.hasProperty('global_gradleAndroidPlugin') ? global_gradleAndroidPlugin : 'com.android.tools.build:gradle:3.2.0'
22 | }
23 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include 'AndroidAsync', 'AndroidAsyncSample', 'AndroidAsyncStetho'
2 |
3 |
--------------------------------------------------------------------------------