diff --git a/001.Http_OpenHarmony-master/code/.gitignore b/001.Http_OpenHarmony-master/code/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..603b14077394cd2294ac6922fe619669630ef3ab --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/001.Http_OpenHarmony-master/code/.idea/.gitignore b/001.Http_OpenHarmony-master/code/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/001.Http_OpenHarmony-master/code/.idea/compiler.xml b/001.Http_OpenHarmony-master/code/.idea/compiler.xml new file mode 100644 index 0000000000000000000000000000000000000000..61a9130cd9669c3843e6445dfe1fee2d493869bc --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/.idea/gradle.xml b/001.Http_OpenHarmony-master/code/.idea/gradle.xml new file mode 100644 index 0000000000000000000000000000000000000000..18ae0b8c32294fcceffb386838aec2092e8481ea --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.idea/gradle.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/.idea/jarRepositories.xml b/001.Http_OpenHarmony-master/code/.idea/jarRepositories.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba2e7443424bc5abb3b2c16dd9751cfceb69faed --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.idea/jarRepositories.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/.idea/misc.xml b/001.Http_OpenHarmony-master/code/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..f43837a9d879322d3f3c732d212a3e507d555196 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/.idea/vcs.xml b/001.Http_OpenHarmony-master/code/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..94a25f7f4cb416c083d265558da75d457237d671 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/build.gradle b/001.Http_OpenHarmony-master/code/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..613f3e6a0b18b7a502df3b3655e61411ae191520 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/build.gradle @@ -0,0 +1,36 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } +} + +buildscript { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.4.2' + } +} + +allprojects { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} diff --git a/001.Http_OpenHarmony-master/code/entry/.gitignore b/001.Http_OpenHarmony-master/code/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/.gitignore @@ -0,0 +1 @@ +/build diff --git a/001.Http_OpenHarmony-master/code/entry/build.gradle b/001.Http_OpenHarmony-master/code/entry/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..fd6335971cfb5436f0d1268a89e121ba9bb5dbd5 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar','*.har']) + testCompile'junit:junit:4.12' + compile 'cz.msebera.android:httpclient:4.5.8' + compile 'org.conscrypt:conscrypt-android:2.4.0' + compile 'com.google.code.gson:gson:2.6.2' +} diff --git a/001.Http_OpenHarmony-master/code/entry/libs/httplibrary.har b/001.Http_OpenHarmony-master/code/entry/libs/httplibrary.har new file mode 100644 index 0000000000000000000000000000000000000000..9122984ed866964fd6e7a75cb4e939b568deeeac Binary files /dev/null and b/001.Http_OpenHarmony-master/code/entry/libs/httplibrary.har differ diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/config.json b/001.Http_OpenHarmony-master/code/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..b6f704257715cb09e32e5ea2fdfe087e65417e41 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/config.json @@ -0,0 +1,105 @@ +{ + "app": { + "bundleName": "com.example.http_hos", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 3, + "target": 4 + } + }, + "deviceConfig": {}, + "module": { + "reqPermissions": [ + { + "name": "ohos.permission.INTERNET", + "reason": "", + "usedScene": { + "ability": [ + "com.example.ohosdemo.MainAbility", + "com.example.ohosdemo.slice.MainAbilitySlice" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.GET_NETWORK_INFO", + "reason": "", + "usedScene": { + "ability": [ + "com.example.ohosdemo.MainAbility", + "com.example.ohosdemo.slice.MainAbilitySlice" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.SET_NETWORK_INFO", + "reason": "", + "usedScene": { + "ability": [ + "com.example.ohosdemo.MainAbility", + "com.example.ohosdemo.slice.MainAbilitySlice" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.READ_MEDIA", + "reason": "", + "usedScene": { + "ability": [ + "com.example.ohosdemo.MainAbility", + "com.example.ohosdemo.slice.MainAbilitySlice" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.WRITE_MEDIA", + "reason": "", + "usedScene": { + "ability": [ + "com.example.ohosdemo.MainAbility", + "com.example.ohosdemo.slice.MainAbilitySlice" + ], + "when": "always" + } + } + ], + "package": "com.example.http_hos", + "name": ".MyApplication", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "com.example.http_hos.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:app_name", + "type": "page", + "launchType": "standard" + } + ] + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/MainAbility.java b/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..3f9a8ba1edef6c1e23989af4ebf30115b4aa80de --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/MainAbility.java @@ -0,0 +1,13 @@ +package com.example.http_hos; + +import com.example.http_hos.slice.MainAbilitySlice; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/MyApplication.java b/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/MyApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..18f24ebfe4e0f678998ce236f367d252ba4fefaa --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/MyApplication.java @@ -0,0 +1,10 @@ +package com.example.http_hos; + +import ohos.aafwk.ability.AbilityPackage; + +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/slice/MainAbilitySlice.java b/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..f21847f97a7a0fb9cc8ad4c35a5c064545dc4e6a --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/java/com/example/http_hos/slice/MainAbilitySlice.java @@ -0,0 +1,61 @@ +package com.example.http_hos.slice; + +import com.example.http_hos.ResourceTable; +import com.example.httplibrary.utils.AsyncHttpClient; +import com.example.httplibrary.utils.JsonHttpResponseHandler; +import com.example.httplibrary.utils.RequestHandle; +import com.example.httplibrary.utils.RequestParams; +import com.google.gson.JsonObject; +import cz.msebera.android.httpclient.Header; +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Text; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +public class MainAbilitySlice extends AbilitySlice { + private HiLogLabel label=new HiLogLabel(HiLog.ERROR,00*00101,"test-async-http"); + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_main); + Text tvResult=(Text) findComponentById(ResourceTable.Id_text); + String url="http://apis.juhe.cn/simpleWeather/query"; + String key="32becf485f7f174d4385957b62f28f61"; + AsyncHttpClient client=new AsyncHttpClient(); + RequestParams params=new RequestParams(); + params.put("city","西安"); + params.put("key",key); + RequestHandle requestHandle = client.get(url,params, new JsonHttpResponseHandler(){ + @Override + public void onSuccess(int statusCode, Header[] headers, String responseString) { + super.onSuccess(statusCode, headers, responseString); + HiLog.error(label,"zel-onSuccess:"+responseString,responseString); + getUITaskDispatcher().asyncDispatch(new Runnable() { + @Override + public void run() { + //更新UI + tvResult.setText(responseString); + } + }); + } + + @Override + public void onFailure(int statusCode, Header[] headers, String errorResponse, Throwable throwable) { + super.onFailure(statusCode, headers, errorResponse, throwable); + HiLog.error(label,"zel-onFailure:"+errorResponse,errorResponse); + + } + }); + }; + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } +} diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ac61b7146853ff358959f479ae0fa0971f52c2f9 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Http_hos" + }, + { + "name": "mainability_description", + "value": "Java_Phone_Empty Feature Ability" + } + ] +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0c0a3df480fa387a452b9c40ca191cc918a3fc0 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..bf1f2100f57e09d0b5a9de3c96b223c789797b5b --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/media/icon.png b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/001.Http_OpenHarmony-master/code/entry/src/main/resources/base/media/icon.png differ diff --git a/001.Http_OpenHarmony-master/code/entry/src/test/java/com/example/http_hos/ExampleTest.java b/001.Http_OpenHarmony-master/code/entry/src/test/java/com/example/http_hos/ExampleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5fdf8446d5e94a519a0ebe32ebf5386b3baa9380 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/entry/src/test/java/com/example/http_hos/ExampleTest.java @@ -0,0 +1,9 @@ +package com.example.http_hos; + +import org.junit.Test; + +public class ExampleTest { + @Test + public void onStart() { + } +} diff --git a/001.Http_OpenHarmony-master/code/gradle.properties b/001.Http_OpenHarmony-master/code/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..bd03ae4a58b1f15059cdee6d79f7d640c5fc58d4 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/gradle.properties @@ -0,0 +1,11 @@ +# Project-wide Gradle settings. +# IDE (e.g. DevEco Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# If the Chinese output is garbled, please configure the following parameter. +# org.gradle.jvmargs=-Dfile.encoding=GBK +hwsdk.dir=C\:\\Users\\elzhang\\AppData\\Local\\Huawei\\Sdk diff --git a/001.Http_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.jar b/001.Http_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9 Binary files /dev/null and b/001.Http_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.jar differ diff --git a/001.Http_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.properties b/001.Http_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..6623300bebd011bc5f7991f4f9c389e2f67b14ac --- /dev/null +++ b/001.Http_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/001.Http_OpenHarmony-master/code/gradlew b/001.Http_OpenHarmony-master/code/gradlew new file mode 100644 index 0000000000000000000000000000000000000000..2fe81a7d95e4f9ad2c9b2a046707d36ceb3980b3 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/001.Http_OpenHarmony-master/code/gradlew.bat b/001.Http_OpenHarmony-master/code/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..62bd9b9ccefea2b65ae41e5d9a545e2021b90a1d --- /dev/null +++ b/001.Http_OpenHarmony-master/code/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/001.Http_OpenHarmony-master/code/httplibrary/.gitignore b/001.Http_OpenHarmony-master/code/httplibrary/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/.gitignore @@ -0,0 +1 @@ +/build diff --git a/001.Http_OpenHarmony-master/code/httplibrary/build.gradle b/001.Http_OpenHarmony-master/code/httplibrary/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..c4304ae4b9372c5f74b48ff0d650c1c29c40d886 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'com.huawei.ohos.library' +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + testCompile'junit:junit:4.12' + compile 'cz.msebera.android:httpclient:4.5.8' + compile 'org.conscrypt:conscrypt-android:2.4.0' + compile 'com.google.code.gson:gson:2.6.2' +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/config.json b/001.Http_OpenHarmony-master/code/httplibrary/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..68d7656e4d453ff5009c675540c87a70faa9d738 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/config.json @@ -0,0 +1,27 @@ +{ + "app": { + "bundleName": "com.example.http_hos", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 3, + "target": 4, + "releaseType": "Beta1" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.httplibrary", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "httplibrary", + "moduleType": "har" + } + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpClient.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpClient.java new file mode 100644 index 0000000000000000000000000000000000000000..ab95a20675fb2a9d1676ca826ef6f0b97feca269 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpClient.java @@ -0,0 +1,1668 @@ +package com.example.httplibrary.utils; + +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + +import cz.msebera.android.httpclient.*; +import cz.msebera.android.httpclient.auth.*; +import cz.msebera.android.httpclient.client.CookieStore; +import cz.msebera.android.httpclient.client.CredentialsProvider; +import cz.msebera.android.httpclient.client.HttpClient; +import cz.msebera.android.httpclient.client.RedirectHandler; +import cz.msebera.android.httpclient.client.methods.*; +import cz.msebera.android.httpclient.client.params.ClientPNames; +import cz.msebera.android.httpclient.client.protocol.ClientContext; +import cz.msebera.android.httpclient.conn.ClientConnectionManager; +import cz.msebera.android.httpclient.conn.params.ConnManagerParams; +import cz.msebera.android.httpclient.conn.params.ConnPerRouteBean; +import cz.msebera.android.httpclient.conn.params.ConnRoutePNames; +import cz.msebera.android.httpclient.conn.scheme.PlainSocketFactory; +import cz.msebera.android.httpclient.conn.scheme.Scheme; +import cz.msebera.android.httpclient.conn.scheme.SchemeRegistry; +import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory; +import cz.msebera.android.httpclient.entity.HttpEntityWrapper; +import cz.msebera.android.httpclient.impl.auth.BasicScheme; +import cz.msebera.android.httpclient.impl.client.DefaultHttpClient; +import cz.msebera.android.httpclient.impl.conn.tsccm.ThreadSafeClientConnManager; +import cz.msebera.android.httpclient.params.BasicHttpParams; +import cz.msebera.android.httpclient.params.HttpConnectionParams; +import cz.msebera.android.httpclient.params.HttpParams; +import cz.msebera.android.httpclient.params.HttpProtocolParams; +import cz.msebera.android.httpclient.protocol.BasicHttpContext; +import cz.msebera.android.httpclient.protocol.ExecutionContext; +import cz.msebera.android.httpclient.protocol.HttpContext; +import cz.msebera.android.httpclient.protocol.SyncBasicHttpContext; +import ohos.app.Context; +import ohos.eventhandler.EventRunner; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PushbackInputStream; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URL; +import java.net.URLDecoder; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.zip.GZIPInputStream; + + +/** + * The AsyncHttpClient can be used to make asynchronous GET, POST, PUT and DELETE HTTP requests in + * your Android applications. Requests can be made with additional parameters by passing a {@link + * RequestParams} instance, and responses can be handled by passing an anonymously overridden {@link + * ResponseHandlerInterface} instance.

 

For example:

 

+ *
+ * AsyncHttpClient client = new AsyncHttpClient();
+ * client.get("https://www.google.com", new AsyncHttpResponseHandler() {
+ *     @Override
+ *     public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
+ *          System.out.println(response);
+ *     }
+ *     @Override
+ *     public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable
+ * error)
+ * {
+ *          error.printStackTrace(System.out);
+ *     }
+ * });
+ * 
+ * + + */ +public class AsyncHttpClient { + + public static final String LOG_TAG = "AsyncHttpClient"; + + public static final String HEADER_CONTENT_TYPE = "Content-Type"; + public static final String HEADER_CONTENT_RANGE = "Content-Range"; + public static final String HEADER_CONTENT_ENCODING = "Content-Encoding"; + public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; + public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; + public static final String ENCODING_GZIP = "gzip"; + + public static final int DEFAULT_MAX_CONNECTIONS = 10; + public static final int DEFAULT_SOCKET_TIMEOUT = 10 * 1000; + public static final int DEFAULT_MAX_RETRIES = 5; + public static final int DEFAULT_RETRY_SLEEP_TIME_MILLIS = 1500; + public static final int DEFAULT_SOCKET_BUFFER_SIZE = 8192; + public static LogInterface log = new LogHandler(); + private final DefaultHttpClient httpClient; + private final HttpContext httpContext; + private final Map> requestMap; + private final Map clientHeaderMap; + private int maxConnections = DEFAULT_MAX_CONNECTIONS; + private int connectTimeout = DEFAULT_SOCKET_TIMEOUT; + private int responseTimeout = DEFAULT_SOCKET_TIMEOUT; + private ExecutorService threadPool; + private boolean isUrlEncodingEnabled = true; + + /** + * Creates a new AsyncHttpClient with default constructor arguments values + */ + public AsyncHttpClient() { + this(false, 80, 443); + } + + /** + * Creates a new AsyncHttpClient. + * + * @param httpPort non-standard HTTP-only port + */ + public AsyncHttpClient(int httpPort) { + this(false, httpPort, 443); + } + + /** + * Creates a new AsyncHttpClient. + * + * @param httpPort non-standard HTTP-only port + * @param httpsPort non-standard HTTPS-only port + */ + public AsyncHttpClient(int httpPort, int httpsPort) { + this(false, httpPort, httpsPort); + } + + /** + * Creates new AsyncHttpClient using given params + * + * @param fixNoHttpResponseException Whether to fix issue or not, by omitting SSL verification + * @param httpPort HTTP port to be used, must be greater than 0 + * @param httpsPort HTTPS port to be used, must be greater than 0 + */ + public AsyncHttpClient(boolean fixNoHttpResponseException, int httpPort, int httpsPort) { + this(getDefaultSchemeRegistry(fixNoHttpResponseException, httpPort, httpsPort)); + } + + /** + * Creates a new AsyncHttpClient. + * + * @param schemeRegistry SchemeRegistry to be used + */ + public AsyncHttpClient(SchemeRegistry schemeRegistry) { + + BasicHttpParams httpParams = new BasicHttpParams(); + + ConnManagerParams.setTimeout(httpParams, connectTimeout); + ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections)); + ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS); + + HttpConnectionParams.setSoTimeout(httpParams, responseTimeout); + HttpConnectionParams.setConnectionTimeout(httpParams, connectTimeout); + HttpConnectionParams.setTcpNoDelay(httpParams, true); + HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE); + + HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); + + ClientConnectionManager cm = createConnectionManager(schemeRegistry, httpParams); + Utils.asserts(cm != null, "Custom implementation of #createConnectionManager(SchemeRegistry, BasicHttpParams) returned null"); + + threadPool = getDefaultThreadPool(); + requestMap = Collections.synchronizedMap(new WeakHashMap>()); + clientHeaderMap = new HashMap(); + + httpContext = new SyncBasicHttpContext(new BasicHttpContext()); + httpClient = new DefaultHttpClient(cm, httpParams); + httpClient.addRequestInterceptor(new HttpRequestInterceptor() { + @Override + public void process(HttpRequest request, HttpContext context) { + if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) { + request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); + } + for (String header : clientHeaderMap.keySet()) { + if (request.containsHeader(header)) { + Header overwritten = request.getFirstHeader(header); + log.d(LOG_TAG, + String.format("Headers were overwritten! (%s | %s) overwrites (%s | %s)", + header, clientHeaderMap.get(header), + overwritten.getName(), overwritten.getValue()) + ); + + //remove the overwritten header + request.removeHeader(overwritten); + } + request.addHeader(header, clientHeaderMap.get(header)); + } + } + }); + + httpClient.addResponseInterceptor(new HttpResponseInterceptor() { + @Override + public void process(HttpResponse response, HttpContext context) { + final HttpEntity entity = response.getEntity(); + if (entity == null) { + return; + } + final Header encoding = entity.getContentEncoding(); + if (encoding != null) { + for (HeaderElement element : encoding.getElements()) { + if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) { + response.setEntity(new InflatingEntity(entity)); + break; + } + } + } + } + }); + + httpClient.addRequestInterceptor(new HttpRequestInterceptor() { + @Override + public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { + + AuthSchemeRegistry authSchemeRegistry = new AuthSchemeRegistry(); + authSchemeRegistry.register("Bearer", new BearerAuthSchemeFactory()); + context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, authSchemeRegistry); + + AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); + CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute( + ClientContext.CREDS_PROVIDER); + HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST); + + if (authState.getAuthScheme() == null) { + AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort()); + Credentials creds = credsProvider.getCredentials(authScope); + if (creds instanceof TokenCredentials) { + authState.setAuthScheme(new BearerAuthSchemeFactory.BearerAuthScheme()); + authState.setCredentials(creds); + } else if (creds != null) { + authState.setAuthScheme(new BasicScheme()); + authState.setCredentials(creds); + } + } + } + }, 0); + + httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_MAX_RETRIES, DEFAULT_RETRY_SLEEP_TIME_MILLIS)); + } + + /** + * Returns default instance of SchemeRegistry + * + * @param fixNoHttpResponseException Whether to fix issue or not, by omitting SSL verification + * @param httpPort HTTP port to be used, must be greater than 0 + * @param httpsPort HTTPS port to be used, must be greater than 0 + */ + private static SchemeRegistry getDefaultSchemeRegistry(boolean fixNoHttpResponseException, int httpPort, int httpsPort) { + if (fixNoHttpResponseException) { + log.d(LOG_TAG, "Beware! Using the fix is insecure, as it doesn't verify SSL certificates."); + } + + if (httpPort < 1) { + httpPort = 80; + log.d(LOG_TAG, "Invalid HTTP port number specified, defaulting to 80"); + } + + if (httpsPort < 1) { + httpsPort = 443; + log.d(LOG_TAG, "Invalid HTTPS port number specified, defaulting to 443"); + } + + // Fix to SSL flaw in API < ICS + // See https://code.google.com/p/android/issues/detail?id=13117 + SSLSocketFactory sslSocketFactory; + if (fixNoHttpResponseException) { + sslSocketFactory = MySSLSocketFactory.getFixedSocketFactory(); + } else { + sslSocketFactory = SSLSocketFactory.getSocketFactory(); + } + + SchemeRegistry schemeRegistry = new SchemeRegistry(); + schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), httpPort)); + schemeRegistry.register(new Scheme("https", sslSocketFactory, httpsPort)); + + return schemeRegistry; + } + + public static void allowRetryExceptionClass(Class cls) { + if (cls != null) { + RetryHandler.addClassToWhitelist(cls); + } + } + + public static void blockRetryExceptionClass(Class cls) { + if (cls != null) { + RetryHandler.addClassToBlacklist(cls); + } + } + + /** + * Will encode url, if not disabled, and adds params on the end of it + * + * @param url String with URL, should be valid URL without params + * @param params RequestParams to be appended on the end of URL + * @param shouldEncodeUrl whether url should be encoded (replaces spaces with %20) + * @return encoded url if requested with params appended if any available + */ + public static String getUrlWithQueryString(boolean shouldEncodeUrl, String url, RequestParams params) { + if (url == null) + return null; + + if (shouldEncodeUrl) { + try { + String decodedURL = URLDecoder.decode(url, "UTF-8"); + URL _url = new URL(decodedURL); + URI _uri = new URI(_url.getProtocol(), _url.getUserInfo(), _url.getHost(), _url.getPort(), _url.getPath(), _url.getQuery(), _url.getRef()); + url = _uri.toASCIIString(); + } catch (Exception ex) { + // Should not really happen, added just for sake of validity + log.e(LOG_TAG, "getUrlWithQueryString encoding URL", ex); + } + } + + if (params != null) { + // Construct the query string and trim it, in case it + // includes any excessive white spaces. + String paramString = params.getParamString().trim(); + + // Only add the query string if it isn't empty and it + // isn't equal to '?'. + if (!paramString.equals("") && !paramString.equals("?")) { + url += url.contains("?") ? "&" : "?"; + url += paramString; + } + } + + return url; + } + + /** + * Checks the InputStream if it contains GZIP compressed data + * + * @param inputStream InputStream to be checked + * @return true or false if the stream contains GZIP compressed data + * @throws IOException if read from inputStream fails + */ + public static boolean isInputStreamGZIPCompressed(final PushbackInputStream inputStream) throws IOException { + if (inputStream == null) + return false; + + byte[] signature = new byte[2]; + int count = 0; + try { + while (count < 2) { + int readCount = inputStream.read(signature, count, 2 - count); + if (readCount < 0) return false; + count = count + readCount; + } + } finally { + inputStream.unread(signature, 0, count); + } + int streamHeader = ((int) signature[0] & 0xff) | ((signature[1] << 8) & 0xff00); + return GZIPInputStream.GZIP_MAGIC == streamHeader; + } + + /** + * A utility function to close an input stream without raising an exception. + * + * @param is input stream to close safely + */ + public static void silentCloseInputStream(InputStream is) { + try { + if (is != null) { + is.close(); + } + } catch (IOException e) { + log.w(LOG_TAG, "Cannot close input stream", e); + } + } + + /** + * A utility function to close an output stream without raising an exception. + * + * @param os output stream to close safely + */ + public static void silentCloseOutputStream(OutputStream os) { + try { + if (os != null) { + os.close(); + } + } catch (IOException e) { + log.w(LOG_TAG, "Cannot close output stream", e); + } + } + + /** + * This horrible hack is required on Android, due to implementation of BasicManagedEntity, which + * doesn't chain call consumeContent on underlying wrapped HttpEntity + * + * @param entity HttpEntity, may be null + */ + public static void endEntityViaReflection(HttpEntity entity) { + if (entity instanceof HttpEntityWrapper) { + try { + Field f = null; + Field[] fields = HttpEntityWrapper.class.getDeclaredFields(); + for (Field ff : fields) { + if (ff.getName().equals("wrappedEntity")) { + f = ff; + break; + } + } + if (f != null) { + f.setAccessible(true); + HttpEntity wrapped = (HttpEntity) f.get(entity); + if (wrapped != null) { + wrapped.consumeContent(); + } + } + } catch (Throwable t) { + log.e(LOG_TAG, "wrappedEntity consume", t); + } + } + } + + /** + * Get the underlying HttpClient instance. This is useful for setting additional fine-grained + * settings for requests by accessing the client's ConnectionManager, HttpParams and + * SchemeRegistry. + * + * @return underlying HttpClient instance + */ + public HttpClient getHttpClient() { + return this.httpClient; + } + + /** + * Get the underlying HttpContext instance. This is useful for getting and setting fine-grained + * settings for requests by accessing the context's attributes such as the CookieStore. + * + * @return underlying HttpContext instance + */ + public HttpContext getHttpContext() { + return this.httpContext; + } + + /** + * Returns logging enabled flag from underlying LogInterface instance + * Default setting is logging enabled. + * + * @return boolean whether is logging across the library currently enabled + */ + public boolean isLoggingEnabled() { + return log.isLoggingEnabled(); + } + + /** + * Will set logging enabled flag on underlying LogInterface instance. + * Default setting is logging enabled. + * + * @param loggingEnabled whether the logging should be enabled or not + */ + public void setLoggingEnabled(boolean loggingEnabled) { + log.setLoggingEnabled(loggingEnabled); + } + + /** + * Retrieves current log level from underlying LogInterface instance. + * Default setting is VERBOSE log level. + * + * @return int log level currently in effect + */ + public int getLoggingLevel() { + return log.getLoggingLevel(); + } + + /** + * Sets log level to be used across all library default implementation + * Default setting is VERBOSE log level. + * + * @param logLevel int log level, either from LogInterface interface or from {@link ohos.hiviewdfx.HiLog} + */ + public void setLoggingLevel(int logLevel) { + log.setLoggingLevel(logLevel); + } + + /** + * Will return current LogInterface used in AsyncHttpClient instance + * + * @return LogInterface currently used by AsyncHttpClient instance + */ + public LogInterface getLogInterface() { + return log; + } + + /** + * Sets default LogInterface (similar to std Android Log util class) instance, + * to be used in AsyncHttpClient instance + * + * @param logInterfaceInstance LogInterface instance, if null, nothing is done + */ + public void setLogInterface(LogInterface logInterfaceInstance) { + if (logInterfaceInstance != null) { + log = logInterfaceInstance; + } + } + + /** + * Sets an optional CookieStore to use when making requests + * + * @param cookieStore The CookieStore implementation to use, usually an instance of {@link + * PersistentCookieStore} + */ + public void setCookieStore(CookieStore cookieStore) { + httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); + } + + /** + * Returns the current executor service used. By default, Executors.newCachedThreadPool() is + * used. + * + * @return current executor service used + */ + public ExecutorService getThreadPool() { + return threadPool; + } + + /** + * Overrides the threadpool implementation used when queuing/pooling requests. By default, + * Executors.newCachedThreadPool() is used. + * + * @param threadPool an instance of {@link ExecutorService} to use for queuing/pooling + * requests. + */ + public void setThreadPool(ExecutorService threadPool) { + this.threadPool = threadPool; + } + + /** + * Get the default threading pool to be used for this HTTP client. + * + * @return The default threading pool to be used + */ + protected ExecutorService getDefaultThreadPool() { + return Executors.newCachedThreadPool(); + } + + /** + * Provided so it is easier for developers to provide custom ThreadSafeClientConnManager implementation + * + * @param schemeRegistry SchemeRegistry, usually provided by {@link #getDefaultSchemeRegistry(boolean, int, int)} + * @param httpParams BasicHttpParams + * @return ClientConnectionManager instance + */ + protected ClientConnectionManager createConnectionManager(SchemeRegistry schemeRegistry, BasicHttpParams httpParams) { + return new ThreadSafeClientConnManager(httpParams, schemeRegistry); + } + + /** + * Simple interface method, to enable or disable redirects. If you set manually RedirectHandler + * on underlying HttpClient, effects of this method will be canceled.

 

Default + * setting is to disallow redirects. + * + * @param enableRedirects boolean + * @param enableRelativeRedirects boolean + * @param enableCircularRedirects boolean + */ + public void setEnableRedirects(final boolean enableRedirects, final boolean enableRelativeRedirects, final boolean enableCircularRedirects) { + httpClient.getParams().setBooleanParameter(ClientPNames.REJECT_RELATIVE_REDIRECT, !enableRelativeRedirects); + httpClient.getParams().setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, enableCircularRedirects); + httpClient.setRedirectHandler(new MyRedirectHandler(enableRedirects)); + } + + /** + * Circular redirects are enabled by default + * + * @param enableRedirects boolean + * @param enableRelativeRedirects boolean + * @see #setEnableRedirects(boolean, boolean, boolean) + */ + public void setEnableRedirects(final boolean enableRedirects, final boolean enableRelativeRedirects) { + setEnableRedirects(enableRedirects, enableRelativeRedirects, true); + } + + /** + * @param enableRedirects boolean + * @see #setEnableRedirects(boolean, boolean, boolean) + */ + public void setEnableRedirects(final boolean enableRedirects) { + setEnableRedirects(enableRedirects, enableRedirects, enableRedirects); + } + + /** + * Allows you to set custom RedirectHandler implementation, if the default provided doesn't suit + * your needs + * + * @param customRedirectHandler RedirectHandler instance + */ + public void setRedirectHandler(final RedirectHandler customRedirectHandler) { + httpClient.setRedirectHandler(customRedirectHandler); + } + + /** + * Sets the User-Agent header to be sent with each request. By default, "Android Asynchronous + * Http Client/VERSION (https://github.com/android-async-http/android-async-http/)" is used. + * + * @param userAgent the string to use in the User-Agent header. + */ + public void setUserAgent(String userAgent) { + HttpProtocolParams.setUserAgent(this.httpClient.getParams(), userAgent); + } + + /** + * Returns current limit of parallel connections + * + * @return maximum limit of parallel connections, default is 10 + */ + public int getMaxConnections() { + return maxConnections; + } + + /** + * Sets maximum limit of parallel connections + * + * @param maxConnections maximum parallel connections, must be at least 1 + */ + public void setMaxConnections(int maxConnections) { + if (maxConnections < 1) + maxConnections = DEFAULT_MAX_CONNECTIONS; + this.maxConnections = maxConnections; + final HttpParams httpParams = this.httpClient.getParams(); + ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(this.maxConnections)); + } + + /** + * Set both the connection and socket timeouts. By default, both are set to + * 10 seconds. + * + * @param value the connect/socket timeout in milliseconds, at least 1 second + * @see #setConnectTimeout(int) + * @see #setResponseTimeout(int) + */ + public void setTimeout(int value) { + value = value < 1000 ? DEFAULT_SOCKET_TIMEOUT : value; + setConnectTimeout(value); + setResponseTimeout(value); + } + + /** + * Returns current connection timeout limit (milliseconds). By default, this + * is set to 10 seconds. + * + * @return Connection timeout limit in milliseconds + */ + public int getConnectTimeout() { + return connectTimeout; + } + + /** + * Set connection timeout limit (milliseconds). By default, this is set to + * 10 seconds. + * + * @param value Connection timeout in milliseconds, minimal value is 1000 (1 second). + */ + public void setConnectTimeout(int value) { + connectTimeout = value < 1000 ? DEFAULT_SOCKET_TIMEOUT : value; + final HttpParams httpParams = httpClient.getParams(); + ConnManagerParams.setTimeout(httpParams, connectTimeout); + HttpConnectionParams.setConnectionTimeout(httpParams, connectTimeout); + } + + /** + * Returns current response timeout limit (milliseconds). By default, this + * is set to 10 seconds. + * + * @return Response timeout limit in milliseconds + */ + public int getResponseTimeout() { + return responseTimeout; + } + + /** + * Set response timeout limit (milliseconds). By default, this is set to + * 10 seconds. + * + * @param value Response timeout in milliseconds, minimal value is 1000 (1 second). + */ + public void setResponseTimeout(int value) { + responseTimeout = value < 1000 ? DEFAULT_SOCKET_TIMEOUT : value; + final HttpParams httpParams = httpClient.getParams(); + HttpConnectionParams.setSoTimeout(httpParams, responseTimeout); + } + + /** + * Sets the Proxy by it's hostname and port + * + * @param hostname the hostname (IP or DNS name) + * @param port the port number. -1 indicates the scheme default port. + */ + public void setProxy(String hostname, int port) { + final HttpHost proxy = new HttpHost(hostname, port); + final HttpParams httpParams = this.httpClient.getParams(); + httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + } + + /** + * Sets the Proxy by it's hostname,port,username and password + * + * @param hostname the hostname (IP or DNS name) + * @param port the port number. -1 indicates the scheme default port. + * @param username the username + * @param password the password + */ + public void setProxy(String hostname, int port, String username, String password) { + httpClient.getCredentialsProvider().setCredentials( + new AuthScope(hostname, port), + new UsernamePasswordCredentials(username, password)); + final HttpHost proxy = new HttpHost(hostname, port); + final HttpParams httpParams = this.httpClient.getParams(); + httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + } + + /** + * Sets the SSLSocketFactory to user when making requests. By default, a new, default + * SSLSocketFactory is used. + * + * @param sslSocketFactory the socket factory to use for https requests. + */ + public void setSSLSocketFactory(SSLSocketFactory sslSocketFactory) { + this.httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", sslSocketFactory, 443)); + } + + /** + * Sets the maximum number of retries and timeout for a particular Request. + * + * @param retries maximum number of retries per request + * @param timeout sleep between retries in milliseconds + */ + public void setMaxRetriesAndTimeout(int retries, int timeout) { + this.httpClient.setHttpRequestRetryHandler(new RetryHandler(retries, timeout)); + } + + /** + * Will, before sending, remove all headers currently present in AsyncHttpClient instance, which + * applies on all requests this client makes + */ + public void removeAllHeaders() { + clientHeaderMap.clear(); + } + + /** + * Sets headers that will be added to all requests this client makes (before sending). + * + * @param header the name of the header + * @param value the contents of the header + */ + public void addHeader(String header, String value) { + clientHeaderMap.put(header, value); + } + + /** + * Remove header from all requests this client makes (before sending). + * + * @param header the name of the header + */ + public void removeHeader(String header) { + clientHeaderMap.remove(header); + } + + /** + * Sets bearer authentication for the request. Uses AuthScope.ANY. This is the same as + * setBearerAuth('token',AuthScope.ANY, false) + * + * @param token Bearer Token + */ + public void setBearerAuth(String token) { + setBearerAuth(token, AuthScope.ANY, false); + } + + + /** + * Sets bearer authentication for the request. You should pass in your AuthScope for security. It + * should be like this setBearerAuth("token", new AuthScope("host",port,AuthScope.ANY_REALM), false) + * + * @param token Bearer Token + * @param scope an AuthScope object + * @param preemptive sets authorization in preemptive manner + */ + public void setBearerAuth(String token, AuthScope scope, boolean preemptive) { + TokenCredentials credentials = new TokenCredentials(token); + setCredentials(scope, credentials); + setAuthenticationPreemptive(preemptive); + } + + /** + * Sets basic authentication for the request. Uses AuthScope.ANY. This is the same as + * setBasicAuth('username','password',AuthScope.ANY) + * + * @param username Basic Auth username + * @param password Basic Auth password + */ + public void setBasicAuth(String username, String password) { + setBasicAuth(username, password, false); + } + + /** + * Sets basic authentication for the request. Uses AuthScope.ANY. This is the same as + * setBasicAuth('username','password',AuthScope.ANY) + * + * @param username Basic Auth username + * @param password Basic Auth password + * @param preemptive sets authorization in preemptive manner + */ + public void setBasicAuth(String username, String password, boolean preemptive) { + setBasicAuth(username, password, null, preemptive); + } + + /** + * Sets basic authentication for the request. You should pass in your AuthScope for security. It + * should be like this setBasicAuth("username","password", new AuthScope("host",port,AuthScope.ANY_REALM)) + * + * @param username Basic Auth username + * @param password Basic Auth password + * @param scope - an AuthScope object + */ + public void setBasicAuth(String username, String password, AuthScope scope) { + setBasicAuth(username, password, scope, false); + } + + /** + * Sets basic authentication for the request. You should pass in your AuthScope for security. It + * should be like this setBasicAuth("username","password", new AuthScope("host",port,AuthScope.ANY_REALM)) + * + * @param username Basic Auth username + * @param password Basic Auth password + * @param scope an AuthScope object + * @param preemptive sets authorization in preemptive manner + */ + public void setBasicAuth(String username, String password, AuthScope scope, boolean preemptive) { + UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password); + setCredentials(scope, credentials); + setAuthenticationPreemptive(preemptive); + } + + public void setCredentials(AuthScope authScope, Credentials credentials) { + if (credentials == null) { + log.d(LOG_TAG, "Provided credentials are null, not setting"); + return; + } + this.httpClient.getCredentialsProvider().setCredentials(authScope == null ? AuthScope.ANY : authScope, credentials); + } + + /** + * Sets HttpRequestInterceptor which handles authorization in preemptive way, as workaround you + * can use call `AsyncHttpClient.addHeader("Authorization","Basic base64OfUsernameAndPassword==")` + * + * @param isPreemptive whether the authorization is processed in preemptive way + */ + public void setAuthenticationPreemptive(boolean isPreemptive) { + if (isPreemptive) { + httpClient.addRequestInterceptor(new PreemptiveAuthorizationHttpRequestInterceptor(), 0); + } else { + httpClient.removeRequestInterceptorByClass(PreemptiveAuthorizationHttpRequestInterceptor.class); + } + } + + // [+] HTTP HEAD + + /** + * Removes previously set auth credentials + */ + public void clearCredentialsProvider() { + this.httpClient.getCredentialsProvider().clear(); + } + + /** + * Cancels any pending (or potentially active) requests associated with the passed Context. + *

 

Note: This will only affect requests which were created with a non-null + * android Context. This method is intended to be used in the onDestroy method of your android + * activities to destroy all requests which are no longer required. + * + * @param context the android Context instance associated to the request. + * @param mayInterruptIfRunning specifies if active requests should be cancelled along with + * pending requests. + */ + public void cancelRequests(final Context context, final boolean mayInterruptIfRunning) { + if (context == null) { + log.e(LOG_TAG, "Passed null Context to cancelRequests"); + return; + } + + final List requestList = requestMap.get(context); + requestMap.remove(context); + + if (EventRunner.current() == EventRunner.getMainEventRunner()) { + Runnable runnable = new Runnable() { + @Override + public void run() { + cancelRequests(requestList, mayInterruptIfRunning); + } + }; + threadPool.submit(runnable); + } else { + cancelRequests(requestList, mayInterruptIfRunning); + } + } + + private void cancelRequests(final List requestList, final boolean mayInterruptIfRunning) { + if (requestList != null) { + for (RequestHandle requestHandle : requestList) { + requestHandle.cancel(mayInterruptIfRunning); + } + } + } + + /** + * Cancels all pending (or potentially active) requests.

 

Note: This will + * only affect requests which were created with a non-null android Context. This method is + * intended to be used in the onDestroy method of your android activities to destroy all + * requests which are no longer required. + * + * @param mayInterruptIfRunning specifies if active requests should be cancelled along with + * pending requests. + */ + public void cancelAllRequests(boolean mayInterruptIfRunning) { + for (List requestList : requestMap.values()) { + if (requestList != null) { + for (RequestHandle requestHandle : requestList) { + requestHandle.cancel(mayInterruptIfRunning); + } + } + } + requestMap.clear(); + } + + /** + * Allows you to cancel all requests currently in queue or running, by set TAG, + * if passed TAG is null, will not attempt to cancel any requests, if TAG is null + * on RequestHandle, it cannot be canceled by this call + * + * @param TAG TAG to be matched in RequestHandle + * @param mayInterruptIfRunning specifies if active requests should be cancelled along with + * pending requests. + */ + public void cancelRequestsByTAG(Object TAG, boolean mayInterruptIfRunning) { + if (TAG == null) { + log.d(LOG_TAG, "cancelRequestsByTAG, passed TAG is null, cannot proceed"); + return; + } + for (List requestList : requestMap.values()) { + if (requestList != null) { + for (RequestHandle requestHandle : requestList) { + if (TAG.equals(requestHandle.getTag())) + requestHandle.cancel(mayInterruptIfRunning); + } + } + } + } + + // [-] HTTP HEAD + // [+] HTTP OPTIONS + + /** + * Perform a HTTP OPTIONS request, without any parameters. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle options(String url, ResponseHandlerInterface responseHandler) { + return options(null, url, null, responseHandler); + } + + public RequestHandle options(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, new HttpOptions(getUrlWithQueryString(isUrlEncodingEnabled(), url, params)), null, responseHandler, context); + } + + // [-] HTTP OPTIONS + // [+] HTTP GET + + /** + * Perform a HTTP HEAD request, without any parameters. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle head(String url, ResponseHandlerInterface responseHandler) { + return head(null, url, null, responseHandler); + } + + /** + * Perform a HTTP HEAD request with parameters. + * + * @param url the URL to send the request to. + * @param params additional HEAD parameters to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle head(String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return head(null, url, params, responseHandler); + } + + /** + * Perform a HTTP HEAD request without any parameters and track the Android Context which + * initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle head(Context context, String url, ResponseHandlerInterface responseHandler) { + return head(context, url, null, responseHandler); + } + + /** + * Perform a HTTP HEAD request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param params additional HEAD parameters to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle head(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, new HttpHead(getUrlWithQueryString(isUrlEncodingEnabled, url, params)), null, responseHandler, context); + } + + /** + * Perform a HTTP HEAD request and track the Android Context which initiated the request with + * customized headers + * + * @param context Context to execute request against + * @param url the URL to send the request to. + * @param headers set headers only for this request + * @param params additional HEAD parameters to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle head(Context context, String url, Header[] headers, RequestParams params, ResponseHandlerInterface responseHandler) { + HttpUriRequest request = new HttpHead(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); + if (headers != null) request.setHeaders(headers); + return sendRequest(httpClient, httpContext, request, null, responseHandler, + context); + } + + /** + * Perform a HTTP GET request, without any parameters. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle get(String url, ResponseHandlerInterface responseHandler) { + return get(null, url, null, responseHandler); + } + + // [-] HTTP GET + // [+] HTTP POST + + /** + * Perform a HTTP GET request with parameters. + * + * @param url the URL to send the request to. + * @param params additional GET parameters to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle get(String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return get(null, url, params, responseHandler); + } + + /** + * Perform a HTTP GET request without any parameters and track the Android Context which + * initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle get(Context context, String url, ResponseHandlerInterface responseHandler) { + return get(context, url, null, responseHandler); + } + + /** + * Perform a HTTP GET request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param params additional GET parameters to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle get(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params)), null, responseHandler, context); + } + + /** + * Perform a HTTP GET request and track the Android Context which initiated the request with + * customized headers + * + * @param context Context to execute request against + * @param url the URL to send the request to. + * @param headers set headers only for this request + * @param params additional GET parameters to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle get(Context context, String url, Header[] headers, RequestParams params, ResponseHandlerInterface responseHandler) { + HttpUriRequest request = new HttpGet(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); + if (headers != null) request.setHeaders(headers); + return sendRequest(httpClient, httpContext, request, null, responseHandler, + context); + } + + /** + * Perform a HTTP GET request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param entity a raw {@link HttpEntity} to send with the request, for + * example, use this to send string/json/xml payloads to a server by + * passing a {@link cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response ha ndler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle get(Context context, String url, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpGet(URI.create(url).normalize()), entity), contentType, responseHandler, context); + } + + /** + * Perform a HTTP POST request, without any parameters. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle post(String url, ResponseHandlerInterface responseHandler) { + return post(null, url, null, responseHandler); + } + + // [-] HTTP POST + // [+] HTTP PUT + + /** + * Perform a HTTP POST request with parameters. + * + * @param url the URL to send the request to. + * @param params additional POST parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle post(String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return post(null, url, params, responseHandler); + } + + /** + * Perform a HTTP POST request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param params additional POST parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle post(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return post(context, url, paramsToEntity(params, responseHandler), null, responseHandler); + } + + /** + * Perform a HTTP POST request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param entity a raw {@link HttpEntity} to send with the request, for + * example, use this to send string/json/xml payloads to a server by + * passing a {@link cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response ha ndler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle post(Context context, String url, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPost(getURI(url)), entity), contentType, responseHandler, context); + } + + /** + * Perform a HTTP POST request and track the Android Context which initiated the request. Set + * headers only for this request + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param headers set headers only for this request + * @param params additional POST parameters to send with the request. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle post(Context context, String url, Header[] headers, RequestParams params, String contentType, + ResponseHandlerInterface responseHandler) { + HttpEntityEnclosingRequestBase request = new HttpPost(getURI(url)); + if (params != null) request.setEntity(paramsToEntity(params, responseHandler)); + if (headers != null) request.setHeaders(headers); + return sendRequest(httpClient, httpContext, request, contentType, + responseHandler, context); + } + + /** + * Perform a HTTP POST request and track the Android Context which initiated the request. Set + * headers only for this request + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param headers set headers only for this request + * @param entity a raw {@link HttpEntity} to send with the request, for example, use + * this to send string/json/xml payloads to a server by passing a {@link + * cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle post(Context context, String url, Header[] headers, HttpEntity entity, String contentType, + ResponseHandlerInterface responseHandler) { + HttpEntityEnclosingRequestBase request = addEntityToRequestBase(new HttpPost(getURI(url)), entity); + if (headers != null) request.setHeaders(headers); + return sendRequest(httpClient, httpContext, request, contentType, responseHandler, context); + } + + /** + * Perform a HTTP PUT request, without any parameters. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle put(String url, ResponseHandlerInterface responseHandler) { + return put(null, url, null, responseHandler); + } + + /** + * Perform a HTTP PUT request with parameters. + * + * @param url the URL to send the request to. + * @param params additional PUT parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle put(String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return put(null, url, params, responseHandler); + } + + /** + * Perform a HTTP PUT request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param params additional PUT parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle put(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return put(context, url, paramsToEntity(params, responseHandler), null, responseHandler); + } + + /** + * Perform a HTTP PUT request and track the Android Context which initiated the request. And set + * one-time headers for the request + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param entity a raw {@link HttpEntity} to send with the request, for example, use + * this to send string/json/xml payloads to a server by passing a {@link + * cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle put(Context context, String url, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPut(getURI(url)), entity), contentType, responseHandler, context); + } + + /** + * Perform a HTTP PUT request and track the Android Context which initiated the request. And set + * one-time headers for the request + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param headers set one-time headers for this request + * @param entity a raw {@link HttpEntity} to send with the request, for example, use + * this to send string/json/xml payloads to a server by passing a {@link + * cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle put(Context context, String url, Header[] headers, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + HttpEntityEnclosingRequestBase request = addEntityToRequestBase(new HttpPut(getURI(url)), entity); + if (headers != null) request.setHeaders(headers); + return sendRequest(httpClient, httpContext, request, contentType, responseHandler, context); + } + + // [-] HTTP PUT + // [+] HTTP DELETE + + /** + * Perform a HTTP + * request, without any parameters. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle patch(String url, ResponseHandlerInterface responseHandler) { + return patch(null, url, null, responseHandler); + } + + /** + * Perform a HTTP PATCH request with parameters. + * + * @param url the URL to send the request to. + * @param params additional PUT parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle patch(String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return patch(null, url, params, responseHandler); + } + + /** + * Perform a HTTP PATCH request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param params additional PUT parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle patch(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) { + return patch(context, url, paramsToEntity(params, responseHandler), null, responseHandler); + } + + /** + * Perform a HTTP PATCH request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @param entity a raw {@link HttpEntity} to send with the request, for example, use + * this to send string/json/xml payloads to a server by passing a {@link + * cz.msebera.android.httpclient.entity.StringEntity} + * @param contentType the content type of the payload you are sending, for example + * "application/json" if sending a json payload. + * @return RequestHandle of future request process + */ + public RequestHandle patch(Context context, String url, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpPatch(getURI(url)), entity), contentType, responseHandler, context); + } + + /** + * Perform a HTTP PATCH request and track the Android Context which initiated the request. And set + * one-time headers for the request + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param headers set one-time headers for this request + * @param entity a raw {@link HttpEntity} to send with the request, for example, use + * this to send string/json/xml payloads to a server by passing a {@link + * cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle patch(Context context, String url, Header[] headers, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + HttpEntityEnclosingRequestBase request = addEntityToRequestBase(new HttpPatch(getURI(url)), entity); + if (headers != null) request.setHeaders(headers); + return sendRequest(httpClient, httpContext, request, contentType, responseHandler, context); + } + + /** + * Perform a HTTP DELETE request. + * + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle delete(String url, ResponseHandlerInterface responseHandler) { + return delete(null, url, responseHandler); + } + + // [-] HTTP DELETE + + /** + * Perform a HTTP DELETE request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle delete(Context context, String url, ResponseHandlerInterface responseHandler) { + final HttpDelete delete = new HttpDelete(getURI(url)); + return sendRequest(httpClient, httpContext, delete, null, responseHandler, context); + } + + /** + * Perform a HTTP DELETE request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param headers set one-time headers for this request + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle delete(Context context, String url, Header[] headers, ResponseHandlerInterface responseHandler) { + final HttpDelete delete = new HttpDelete(getURI(url)); + if (headers != null) delete.setHeaders(headers); + return sendRequest(httpClient, httpContext, delete, null, responseHandler, context); + } + + /** + * Perform a HTTP DELETE request. + * + * @param url the URL to send the request to. + * @param params additional DELETE parameters or files to send with the request. + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle delete(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { + final HttpDelete delete = new HttpDelete(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); + return sendRequest(httpClient, httpContext, delete, null, responseHandler, null); + } + + /** + * Perform a HTTP DELETE request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param headers set one-time headers for this request + * @param params additional DELETE parameters or files to send along with request + * @param responseHandler the response handler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle delete(Context context, String url, Header[] headers, RequestParams params, ResponseHandlerInterface responseHandler) { + HttpDelete httpDelete = new HttpDelete(getUrlWithQueryString(isUrlEncodingEnabled, url, params)); + if (headers != null) httpDelete.setHeaders(headers); + return sendRequest(httpClient, httpContext, httpDelete, null, responseHandler, context); + } + + /** + * Perform a HTTP DELETE request and track the Android Context which initiated the request. + * + * @param context the Android Context which initiated the request. + * @param url the URL to send the request to. + * @param entity a raw {@link HttpEntity} to send with the request, for + * example, use this to send string/json/xml payloads to a server by + * passing a {@link cz.msebera.android.httpclient.entity.StringEntity}. + * @param contentType the content type of the payload you are sending, for example + * application/json if sending a json payload. + * @param responseHandler the response ha ndler instance that should handle the response. + * @return RequestHandle of future request process + */ + public RequestHandle delete(Context context, String url, HttpEntity entity, String contentType, ResponseHandlerInterface responseHandler) { + return sendRequest(httpClient, httpContext, addEntityToRequestBase(new HttpDelete(URI.create(url).normalize()), entity), contentType, responseHandler, context); + } + + /** + * Instantiate a new asynchronous HTTP request for the passed parameters. + * + * @param client HttpClient to be used for request, can differ in single requests + * @param contentType MIME body type, for POST and PUT requests, may be null + * @param context Context of Android application, to hold the reference of request + * @param httpContext HttpContext in which the request will be executed + * @param responseHandler ResponseHandler or its subclass to put the response into + * @param uriRequest instance of HttpUriRequest, which means it must be of HttpDelete, + * HttpPost, HttpGet, HttpPut, etc. + * @return AsyncHttpRequest ready to be dispatched + */ + protected AsyncHttpRequest newAsyncHttpRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) { + return new AsyncHttpRequest(client, httpContext, uriRequest, responseHandler); + } + + /** + * Puts a new request in queue as a new thread in pool to be executed + * + * @param client HttpClient to be used for request, can differ in single requests + * @param contentType MIME body type, for POST and PUT requests, may be null + * @param context Context of Android application, to hold the reference of request + * @param httpContext HttpContext in which the request will be executed + * @param responseHandler ResponseHandler or its subclass to put the response into + * @param uriRequest instance of HttpUriRequest, which means it must be of HttpDelete, + * HttpPost, HttpGet, HttpPut, etc. + * @return RequestHandle of future request process + */ + protected RequestHandle sendRequest(DefaultHttpClient client, HttpContext httpContext, HttpUriRequest uriRequest, String contentType, ResponseHandlerInterface responseHandler, Context context) { + if (uriRequest == null) { + throw new IllegalArgumentException("HttpUriRequest must not be null"); + } + + if (responseHandler == null) { + throw new IllegalArgumentException("ResponseHandler must not be null"); + } + + if (responseHandler.getUseSynchronousMode() && !responseHandler.getUsePoolThread()) { + throw new IllegalArgumentException("Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead."); + } + + if (contentType != null) { + if (uriRequest instanceof HttpEntityEnclosingRequestBase && ((HttpEntityEnclosingRequestBase) uriRequest).getEntity() != null && uriRequest.containsHeader(HEADER_CONTENT_TYPE)) { + log.w(LOG_TAG, "Passed contentType will be ignored because HttpEntity sets content type"); + } else { + uriRequest.setHeader(HEADER_CONTENT_TYPE, contentType); + } + } + + responseHandler.setRequestHeaders(uriRequest.getAllHeaders()); + responseHandler.setRequestURI(uriRequest.getURI()); + + AsyncHttpRequest request = newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context); + threadPool.submit(request); + RequestHandle requestHandle = new RequestHandle(request); + + if (context != null) { + List requestList; + // Add request to request map + synchronized (requestMap) { + requestList = requestMap.get(context); + if (requestList == null) { + requestList = Collections.synchronizedList(new LinkedList()); + requestMap.put(context, requestList); + } + } + + requestList.add(requestHandle); + + Iterator iterator = requestList.iterator(); + while (iterator.hasNext()) { + if (iterator.next().shouldBeGarbageCollected()) { + iterator.remove(); + } + } + } + + return requestHandle; + } + + /** + * Returns a {@link URI} instance for the specified, absolute URL string. + * + * @param url absolute URL string, containing scheme, host and path + * @return URI instance for the URL string + */ + protected URI getURI(String url) { + return URI.create(url).normalize(); + } + + /** + * Sets state of URL encoding feature, see bug #227, this method allows you to turn off and on + * this auto-magic feature on-demand. + * + * @param enabled desired state of feature + */ + public void setURLEncodingEnabled(boolean enabled) { + this.isUrlEncodingEnabled = enabled; + } + + /** + * Returns HttpEntity containing data from RequestParams included with request declaration. + * Allows also passing progress from upload via provided ResponseHandler + * + * @param params additional request params + * @param responseHandler ResponseHandlerInterface or its subclass to be notified on progress + */ + private HttpEntity paramsToEntity(RequestParams params, ResponseHandlerInterface responseHandler) { + HttpEntity entity = null; + + try { + if (params != null) { + entity = params.getEntity(responseHandler); + } + } catch (IOException e) { + if (responseHandler != null) { + responseHandler.sendFailureMessage(0, null, null, e); + } else { + e.printStackTrace(); + } + } + + return entity; + } + + public boolean isUrlEncodingEnabled() { + return isUrlEncodingEnabled; + } + + /** + * Applicable only to HttpRequest methods extending HttpEntityEnclosingRequestBase, which is for + * example not DELETE + * + * @param entity entity to be included within the request + * @param requestBase HttpRequest instance, must not be null + */ + private HttpEntityEnclosingRequestBase addEntityToRequestBase(HttpEntityEnclosingRequestBase requestBase, HttpEntity entity) { + if (entity != null) { + requestBase.setEntity(entity); + } + + return requestBase; + } + + /** + * Enclosing entity to hold stream of gzip decoded data for accessing HttpEntity contents + */ + private static class InflatingEntity extends HttpEntityWrapper { + + InputStream wrappedStream; + PushbackInputStream pushbackStream; + GZIPInputStream gzippedStream; + + public InflatingEntity(HttpEntity wrapped) { + super(wrapped); + } + + @Override + public InputStream getContent() throws IOException { + wrappedStream = wrappedEntity.getContent(); + pushbackStream = new PushbackInputStream(wrappedStream, 2); + if (isInputStreamGZIPCompressed(pushbackStream)) { + gzippedStream = new GZIPInputStream(pushbackStream); + return gzippedStream; + } else { + return pushbackStream; + } + } + + @Override + public long getContentLength() { + return wrappedEntity == null ? 0 : wrappedEntity.getContentLength(); + } + + @Override + public void consumeContent() throws IOException { + AsyncHttpClient.silentCloseInputStream(wrappedStream); + AsyncHttpClient.silentCloseInputStream(pushbackStream); + AsyncHttpClient.silentCloseInputStream(gzippedStream); + super.consumeContent(); + } + } + + /** + * Call this method if your app target android below 4.4 + * This method enable sni in android below 4.4 + */ + public static void useConscryptSSLProvider(){ + ConscryptSSLProvider.install(); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpRequest.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..749f2a383efebd56592345bba590eca0a888b387 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpRequest.java @@ -0,0 +1,257 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.HttpResponse; +import cz.msebera.android.httpclient.client.HttpRequestRetryHandler; +import cz.msebera.android.httpclient.client.methods.HttpUriRequest; +import cz.msebera.android.httpclient.impl.client.AbstractHttpClient; +import cz.msebera.android.httpclient.protocol.HttpContext; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.UnknownHostException; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Internal class, representing the HttpRequest, done in asynchronous manner + */ +public class AsyncHttpRequest implements Runnable { + private final AbstractHttpClient client; + private final HttpContext context; + private final HttpUriRequest request; + private final ResponseHandlerInterface responseHandler; + private final AtomicBoolean isCancelled = new AtomicBoolean(); + private int executionCount; + private boolean cancelIsNotified; + private volatile boolean isFinished; + private boolean isRequestPreProcessed; + + public AsyncHttpRequest(AbstractHttpClient client, HttpContext context, HttpUriRequest request, ResponseHandlerInterface responseHandler) { + this.client = Utils.notNull(client, "client"); + this.context = Utils.notNull(context, "context"); + this.request = Utils.notNull(request, "request"); + this.responseHandler = Utils.notNull(responseHandler, "responseHandler"); + } + + /** + * This method is called once by the system when the request is about to be + * processed by the system. The library makes sure that a single request + * is pre-processed only once. + *

 

+ * Please note: pre-processing does NOT run on the main thread, and thus + * any UI activities that you must perform should be properly dispatched to + * the app's UI thread. + * + * @param request The request to pre-process + */ + public void onPreProcessRequest(AsyncHttpRequest request) { + // default action is to do nothing... + } + + /** + * This method is called once by the system when the request has been fully + * sent, handled and finished. The library makes sure that a single request + * is post-processed only once. + *

 

+ * Please note: post-processing does NOT run on the main thread, and thus + * any UI activities that you must perform should be properly dispatched to + * the app's UI thread. + * + * @param request The request to post-process + */ + public void onPostProcessRequest(AsyncHttpRequest request) { + // default action is to do nothing... + } + + @Override + public void run() { + if (isCancelled()) { + return; + } + + // Carry out pre-processing for this request only once. + if (!isRequestPreProcessed) { + isRequestPreProcessed = true; + onPreProcessRequest(this); + } + + if (isCancelled()) { + return; + } + + responseHandler.sendStartMessage(); + + if (isCancelled()) { + return; + } + + try { + makeRequestWithRetries(); + } catch (IOException e) { + if (!isCancelled()) { + responseHandler.sendFailureMessage(0, null, null, e); + } else { + AsyncHttpClient.log.e("AsyncHttpRequest", "makeRequestWithRetries returned error", e); + } + } + + if (isCancelled()) { + return; + } + + responseHandler.sendFinishMessage(); + + if (isCancelled()) { + return; + } + + // Carry out post-processing for this request. + onPostProcessRequest(this); + + isFinished = true; + } + + private void makeRequest() throws IOException { + if (isCancelled()) { + return; + } + + // Fixes #115 + if (request.getURI().getScheme() == null) { + // subclass of IOException so processed in the caller + throw new MalformedURLException("No valid URI scheme was provided"); + } + + if (responseHandler instanceof RangeFileAsyncHttpResponseHandler) { + ((RangeFileAsyncHttpResponseHandler) responseHandler).updateRequestHeaders(request); + } + + HttpResponse response = client.execute(request, context); + + if (isCancelled()) { + return; + } + + // Carry out pre-processing for this response. + responseHandler.onPreProcessResponse(responseHandler, response); + + if (isCancelled()) { + return; + } + + // The response is ready, handle it. + responseHandler.sendResponseMessage(response); + + if (isCancelled()) { + return; + } + + // Carry out post-processing for this response. + responseHandler.onPostProcessResponse(responseHandler, response); + } + + private void makeRequestWithRetries() throws IOException { + boolean retry = true; + IOException cause = null; + HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler(); + try { + while (retry) { + try { + makeRequest(); + return; + } catch (UnknownHostException e) { + // switching between WI-FI and mobile data networks can cause a retry which then results in an UnknownHostException + // while the WI-FI is initialising. The retry logic will be invoked here, if this is NOT the first retry + // (to assist in genuine cases of unknown host) which seems better than outright failure + cause = new IOException("UnknownHostException exception: " + e.getMessage(), e); + retry = (executionCount > 0) && retryHandler.retryRequest(e, ++executionCount, context); + } catch (NullPointerException e) { + // there's a bug in HttpClient 4.0.x that on some occasions causes + // DefaultRequestExecutor to throw an NPE, see + // https://code.google.com/p/android/issues/detail?id=5255 + cause = new IOException("NPE in HttpClient: " + e.getMessage()); + retry = retryHandler.retryRequest(cause, ++executionCount, context); + } catch (IOException e) { + if (isCancelled()) { + // Eating exception, as the request was cancelled + return; + } + cause = e; + retry = retryHandler.retryRequest(cause, ++executionCount, context); + } + if (retry) { + responseHandler.sendRetryMessage(executionCount); + } + } + } catch (Exception e) { + // catch anything else to ensure failure message is propagated + AsyncHttpClient.log.e("AsyncHttpRequest", "Unhandled exception origin cause", e); + cause = new IOException("Unhandled exception: " + e.getMessage(), cause); + } + + // cleaned up to throw IOException + throw (cause); + } + + public boolean isCancelled() { + boolean cancelled = isCancelled.get(); + if (cancelled) { + sendCancelNotification(); + } + return cancelled; + } + + private synchronized void sendCancelNotification() { + if (!isFinished && isCancelled.get() && !cancelIsNotified) { + cancelIsNotified = true; + responseHandler.sendCancelMessage(); + } + } + + public boolean isDone() { + return isCancelled() || isFinished; + } + + public boolean cancel(boolean mayInterruptIfRunning) { + isCancelled.set(true); + request.abort(); + return isCancelled(); + } + + /** + * Will set Object as TAG to this request, wrapped by WeakReference + * + * @param TAG Object used as TAG to this RequestHandle + * @return this AsyncHttpRequest to allow fluid syntax + */ + public AsyncHttpRequest setRequestTag(Object TAG) { + this.responseHandler.setTag(TAG); + return this; + } + + /** + * Will return TAG of this AsyncHttpRequest + * + * @return Object TAG, can be null, if it's been already garbage collected + */ + public Object getTag() { + return this.responseHandler.getTag(); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..54ce7ce882fd40e62c890b6a39b285ab88b40937 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/AsyncHttpResponseHandler.java @@ -0,0 +1,526 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpEntity; +import cz.msebera.android.httpclient.HttpResponse; +import cz.msebera.android.httpclient.StatusLine; +import cz.msebera.android.httpclient.client.HttpResponseException; +import cz.msebera.android.httpclient.util.ByteArrayBuffer; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.net.URI; +import java.util.Locale; + +/** + * Used to intercept and handle the responses from requests made using {@link AsyncHttpClient}. The + * {@link #onSuccess(int, Header[], byte[])} method is designed to be anonymously + * overridden with your own response handling code.

 

Additionally, you can override the + * {@link #onFailure(int, Header[], byte[], Throwable)}, {@link #onStart()}, {@link + * #onFinish()}, {@link #onRetry(int)} and {@link #onProgress(long, long)} methods as required. + *

 

For example:

 

+ *
+ * AsyncHttpClient client = new AsyncHttpClient();
+ * client.get("https://www.google.com", new AsyncHttpResponseHandler() {
+ *     @Override
+ *     public void onStart() {
+ *         // Initiated the request
+ *     }
+ *
+ *     @Override
+ *     public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
+ *         // Successfully got a response
+ *     }
+ *
+ *     @Override
+ *     public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable
+ * error)
+ * {
+ *         // Response failed :(
+ *     }
+ *
+ *     @Override
+ *     public void onRetry(int retryNo) {
+ *         // Request was retried
+ *     }
+ *
+ *     @Override
+ *     public void onProgress(long bytesWritten, long totalSize) {
+ *         // Progress notification
+ *     }
+ *
+ *     @Override
+ *     public void onFinish() {
+ *         // Completed the request (either success or failure)
+ *     }
+ * });
+ * 
+ */ +@SuppressWarnings("DesignForExtension") +public abstract class AsyncHttpResponseHandler implements ResponseHandlerInterface { + + public static final String DEFAULT_CHARSET = "UTF-8"; + public static final String UTF8_BOM = "\uFEFF"; + protected static final int SUCCESS_MESSAGE = 0; + protected static final int FAILURE_MESSAGE = 1; + protected static final int START_MESSAGE = 2; + protected static final int FINISH_MESSAGE = 3; + protected static final int PROGRESS_MESSAGE = 4; + protected static final int RETRY_MESSAGE = 5; + protected static final int CANCEL_MESSAGE = 6; + protected static final int BUFFER_SIZE = 4096; + private static final String LOG_TAG = "AsyncHttpRH"; + private String responseCharset = DEFAULT_CHARSET; + private EventHandler handler; + private boolean useSynchronousMode; + private boolean usePoolThread; + + private URI requestURI = null; + private Header[] requestHeaders = null; + private EventRunner looper = null; + private WeakReference TAG = new WeakReference(null); + + /** + * Creates a new AsyncHttpResponseHandler + */ + public AsyncHttpResponseHandler() { + this(null); + } + + /** + * Creates a new AsyncHttpResponseHandler with a user-supplied looper. If + * the passed looper is null, the looper attached to the current thread will + * be used. + * + * @param looper The looper to work with + */ + public AsyncHttpResponseHandler(EventRunner looper) { + // Do not use the pool's thread to fire callbacks by default. + this(looper == null ? EventRunner.create(true) : looper, false); + } + + /** + * Creates a new AsyncHttpResponseHandler and decide whether the callbacks + * will be fired on current thread's looper or the pool thread's. + * + * @param usePoolThread Whether to use the pool's thread to fire callbacks + */ + public AsyncHttpResponseHandler(boolean usePoolThread) { + this(usePoolThread ? null : EventRunner.create(true), usePoolThread); + } + + + + public AsyncHttpResponseHandler(EventRunner looper, boolean usePoolThread) { + if (!usePoolThread) { + Utils.asserts(looper != null, "use looper thread, must call Looper.prepare() first!"); + this.looper = looper; + // Create a handler on current thread to submit tasks + this.handler = new ResponderHandler(this, looper); + } else { + Utils.asserts(looper == null, "use pool thread, looper should be null!"); + // If pool thread is to be used, there's no point in keeping a reference + // to the looper and handler. + this.looper = null; + this.handler = null; + } + + this.usePoolThread = usePoolThread; + } + + @Override + public Object getTag() { + return this.TAG.get(); + } + + @Override + public void setTag(Object TAG) { + this.TAG = new WeakReference(TAG); + } + + @Override + public URI getRequestURI() { + return this.requestURI; + } + + @Override + public void setRequestURI(URI requestURI) { + this.requestURI = requestURI; + } + + @Override + public Header[] getRequestHeaders() { + return this.requestHeaders; + } + + @Override + public void setRequestHeaders(Header[] requestHeaders) { + this.requestHeaders = requestHeaders; + } + + @Override + public boolean getUseSynchronousMode() { + return useSynchronousMode; + } + + @Override + public void setUseSynchronousMode(boolean sync) { + // A looper must be prepared before setting asynchronous mode. + if (!sync && looper == null) { + sync = true; + AsyncHttpClient.log.w(LOG_TAG, "Current thread has not called Looper.prepare(). Forcing synchronous mode."); + } + + // If using asynchronous mode. + if (!sync && handler == null) { + // Create a handler on current thread to submit tasks + handler = new ResponderHandler(this, looper); + } else if (sync && handler != null) { + // TODO: Consider adding a flag to remove all queued messages. + handler = null; + } + + useSynchronousMode = sync; + } + + @Override + public boolean getUsePoolThread() { + return usePoolThread; + } + + @Override + public void setUsePoolThread(boolean pool) { + // If pool thread is to be used, there's no point in keeping a reference + // to the looper and no need for a handler. + if (pool) { + looper = null; + handler = null; + } + + usePoolThread = pool; + } + + public String getCharset() { + return this.responseCharset == null ? DEFAULT_CHARSET : this.responseCharset; + } + + /** + * Sets the charset for the response string. If not set, the default is UTF-8. + * + * @param charset to be used for the response string. + * @see Charset + */ + public void setCharset(final String charset) { + this.responseCharset = charset; + } + + /** + * Fired when the request progress, override to handle in your own code + * + * @param bytesWritten offset from start of file + * @param totalSize total size of file + */ + public void onProgress(long bytesWritten, long totalSize) { + AsyncHttpClient.log.v(LOG_TAG, String.format(Locale.US, "Progress %d from %d (%2.0f%%)", bytesWritten, totalSize, (totalSize > 0) ? (bytesWritten * 1.0 / totalSize) * 100 : -1)); + } + + /** + * Fired when the request is started, override to handle in your own code + */ + public void onStart() { + // default log warning is not necessary, because this method is just optional notification + } + + /** + * Fired in all cases when the request is finished, after both success and failure, override to + * handle in your own code + */ + public void onFinish() { + // default log warning is not necessary, because this method is just optional notification + } + + @Override + public void onPreProcessResponse(ResponseHandlerInterface instance, HttpResponse response) { + // default action is to do nothing... + } + + @Override + public void onPostProcessResponse(ResponseHandlerInterface instance, HttpResponse response) { + // default action is to do nothing... + } + + /** + * Fired when a request returns successfully, override to handle in your own code + * + * @param statusCode the status code of the response + * @param headers return headers, if any + * @param responseBody the body of the HTTP response from the server + */ + public abstract void onSuccess(int statusCode, Header[] headers, byte[] responseBody); + + /** + * Fired when a request fails to complete, override to handle in your own code + * + * @param statusCode return HTTP status code + * @param headers return headers, if any + * @param responseBody the response body, if any + * @param error the underlying cause of the failure + */ + public abstract void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error); + + /** + * Fired when a retry occurs, override to handle in your own code + * + * @param retryNo number of retry + */ + public void onRetry(int retryNo) { + AsyncHttpClient.log.d(LOG_TAG, String.format(Locale.US, "Request retry no. %d", retryNo)); + } + + public void onCancel() { + AsyncHttpClient.log.d(LOG_TAG, "Request got cancelled"); + } + + public void onUserException(Throwable error) { + AsyncHttpClient.log.e(LOG_TAG, "User-space exception detected!", error); + throw new RuntimeException(error); + } + + @Override + final public void sendProgressMessage(long bytesWritten, long bytesTotal) { + sendMessage(obtainMessage(PROGRESS_MESSAGE, new Object[]{bytesWritten, bytesTotal})); + } + + @Override + final public void sendSuccessMessage(int statusCode, Header[] headers, byte[] responseBytes) { + sendMessage(obtainMessage(SUCCESS_MESSAGE, new Object[]{statusCode, headers, responseBytes})); + } + + @Override + final public void sendFailureMessage(int statusCode, Header[] headers, byte[] responseBody, Throwable throwable) { + sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[]{statusCode, headers, responseBody, throwable})); + } + + @Override + final public void sendStartMessage() { + sendMessage(obtainMessage(START_MESSAGE, null)); + } + + @Override + final public void sendFinishMessage() { + sendMessage(obtainMessage(FINISH_MESSAGE, null)); + } + + @Override + final public void sendRetryMessage(int retryNo) { + sendMessage(obtainMessage(RETRY_MESSAGE, new Object[]{retryNo})); + } + + @Override + final public void sendCancelMessage() { + sendMessage(obtainMessage(CANCEL_MESSAGE, null)); + } + + // Methods which emulate android's Handler and Message methods + protected void handleMessage(InnerEvent message) { + Object[] response; + + try { + switch (message.eventId) { + case SUCCESS_MESSAGE: + response = (Object[]) message.object; + if (response != null && response.length >= 3) { + onSuccess((Integer) response[0], (Header[]) response[1], (byte[]) response[2]); + } else { + AsyncHttpClient.log.e(LOG_TAG, "SUCCESS_MESSAGE didn't got enough params"); + } + break; + case FAILURE_MESSAGE: + response = (Object[]) message.object; + if (response != null && response.length >= 4) { + onFailure((Integer) response[0], (Header[]) response[1], (byte[]) response[2], (Throwable) response[3]); + } else { + AsyncHttpClient.log.e(LOG_TAG, "FAILURE_MESSAGE didn't got enough params"); + } + break; + case START_MESSAGE: + onStart(); + break; + case FINISH_MESSAGE: + onFinish(); + break; + case PROGRESS_MESSAGE: + response = (Object[]) message.object; + if (response != null && response.length >= 2) { + try { + onProgress((Long) response[0], (Long) response[1]); + } catch (Throwable t) { + AsyncHttpClient.log.e(LOG_TAG, "custom onProgress contains an error", t); + } + } else { + AsyncHttpClient.log.e(LOG_TAG, "PROGRESS_MESSAGE didn't got enough params"); + } + break; + case RETRY_MESSAGE: + response = (Object[]) message.object; + if (response != null && response.length == 1) { + onRetry((Integer) response[0]); + } else { + AsyncHttpClient.log.e(LOG_TAG, "RETRY_MESSAGE didn't get enough params"); + } + break; + case CANCEL_MESSAGE: + onCancel(); + break; + } + } catch (Throwable error) { + onUserException(error); + } + } + + protected void sendMessage(InnerEvent msg) { + if (getUseSynchronousMode() || handler == null) { + handleMessage(msg); + } else if (!Thread.currentThread().isInterrupted()) { // do not send messages if request has been cancelled + Utils.asserts(handler != null, "handler should not be null!"); + AsyncHttpClient.log.d("loop","handler!= null"+looper.toString()); + handler.sendEvent(msg); + //zel +// looper.run(); + } + } + + /** + * Helper method to send runnable into local handler loop + * + * @param runnable runnable instance, can be null + */ + protected void postRunnable(Runnable runnable) { + if (runnable != null) { + if (getUseSynchronousMode() || handler == null) { + // This response handler is synchronous, run on current thread + runnable.run(); + } else { + // Otherwise, run on provided handler + handler.postTask(runnable); + //zel +// looper.run(); + } + } + } + + /** + * Helper method to create Message instance from handler + * + * @param responseMessageId constant to identify Handler message + * @param responseMessageData object to be passed to message receiver + * @return Message instance, should not be null + */ + protected InnerEvent obtainMessage(int responseMessageId, Object responseMessageData) { + InnerEvent event= InnerEvent.get(responseMessageId,responseMessageData); + //zel + return event; + } + + @Override + public void sendResponseMessage(HttpResponse response) throws IOException { + // do not process if request has been cancelled + if (!Thread.currentThread().isInterrupted()) { + StatusLine status = response.getStatusLine(); + byte[] responseBody; + responseBody = getResponseData(response.getEntity()); + // additional cancellation check as getResponseData() can take non-zero time to process + if (!Thread.currentThread().isInterrupted()) { + if (status.getStatusCode() >= 300) { + sendFailureMessage(status.getStatusCode(), response.getAllHeaders(), responseBody, new HttpResponseException(status.getStatusCode(), status.getReasonPhrase())); + } else { + sendSuccessMessage(status.getStatusCode(), response.getAllHeaders(), responseBody); + } + } + } + } + + /** + * Returns byte array of response HttpEntity contents + * + * @param entity can be null + * @return response entity body or null + * @throws IOException if reading entity or creating byte array failed + */ + byte[] getResponseData(HttpEntity entity) throws IOException { + byte[] responseBody = null; + if (entity != null) { + InputStream instream = entity.getContent(); + if (instream != null) { + long contentLength = entity.getContentLength(); + if (contentLength > Integer.MAX_VALUE) { + throw new IllegalArgumentException("HTTP entity too large to be buffered in memory"); + } + int buffersize = (contentLength <= 0) ? BUFFER_SIZE : (int) contentLength; + try { + ByteArrayBuffer buffer = new ByteArrayBuffer(buffersize); + try { + byte[] tmp = new byte[BUFFER_SIZE]; + long count = 0; + int l; + // do not send messages if request has been cancelled + while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) { + count += l; + buffer.append(tmp, 0, l); + sendProgressMessage(count, (contentLength <= 0 ? 1 : contentLength)); + } + } finally { + AsyncHttpClient.silentCloseInputStream(instream); + AsyncHttpClient.endEntityViaReflection(entity); + } + responseBody = buffer.toByteArray(); + } catch (OutOfMemoryError e) { + System.gc(); + throw new IOException("File too large to fit into available memory"); + } + } + } + return responseBody; + } + + /** + * Avoid leaks by using a non-anonymous handler class. + */ + private static class ResponderHandler extends EventHandler { + private final AsyncHttpResponseHandler mResponder; + + ResponderHandler(AsyncHttpResponseHandler mResponder, EventRunner looper) { + super(looper); + this.mResponder = mResponder; + } + + + @Override + protected void processEvent(InnerEvent event) { + super.processEvent(event); + mResponder.handleMessage(event); + } + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64.java new file mode 100644 index 0000000000000000000000000000000000000000..82dfeaf72253dd4d622364a4c7ae476f9172c181 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64.java @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.httplibrary.utils; + +import ohos.agp.render.render3d.BuildConfig; + +import java.io.UnsupportedEncodingException; + +/** + * Utilities for encoding and decoding the Base64 representation of binary data. See RFCs 2045 and 3548. + */ +public class Base64 { + /** + * Default values for encoder/decoder flags. + */ + public static final int DEFAULT = 0; + + /** + * Encoder flag bit to omit the padding '=' characters at the end of the output (if any). + */ + public static final int NO_PADDING = 1; + + /** + * Encoder flag bit to omit all line terminators (i.e., the output will be on one long line). + */ + public static final int NO_WRAP = 2; + + /** + * Encoder flag bit to indicate lines should be terminated with a CRLF pair instead of just an + * LF. Has no effect if {@code NO_WRAP} is specified as well. + */ + public static final int CRLF = 4; + + /** + * Encoder/decoder flag bit to indicate using the "URL and filename safe" variant of Base64 (see + * RFC 3548 section 4) where {@code -} and {@code _} are used in place of {@code +} and {@code + * /}. + */ + public static final int URL_SAFE = 8; + + /** + * Flag to pass to {@link Base64OutputStream} to indicate that it should not close the output + * stream it is wrapping when it itself is closed. + */ + public static final int NO_CLOSE = 16; + + // -------------------------------------------------------- + // shared code + // -------------------------------------------------------- + + private Base64() { + } // don't instantiate + + // -------------------------------------------------------- + // decoding + // -------------------------------------------------------- + + /** + * Decode the Base64-encoded data in input and return the data in a new byte array. + *

 

The padding '=' characters at the end are considered optional, but if any + * are present, there must be the correct number of them. + * + * @param str the input String to decode, which is converted to bytes using the default + * charset + * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode + * standard Base64. + * @return decoded bytes + * @throws IllegalArgumentException if the input contains incorrect padding + */ + public static byte[] decode(String str, int flags) { + return decode(str.getBytes(), flags); + } + + /** + * Decode the Base64-encoded data in input and return the data in a new byte array. + *

 

The padding '=' characters at the end are considered optional, but if any + * are present, there must be the correct number of them. + * + * @param input the input array to decode + * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode + * standard Base64. + * @return decoded bytes + * @throws IllegalArgumentException if the input contains incorrect padding + */ + public static byte[] decode(byte[] input, int flags) { + return decode(input, 0, input.length, flags); + } + + /** + * Decode the Base64-encoded data in input and return the data in a new byte array. + *

 

The padding '=' characters at the end are considered optional, but if any + * are present, there must be the correct number of them. + * + * @param input the data to decode + * @param offset the position within the input array at which to start + * @param len the number of bytes of input to decode + * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode + * standard Base64. + * @return decoded bytes for given offset and length + * @throws IllegalArgumentException if the input contains incorrect padding + */ + public static byte[] decode(byte[] input, int offset, int len, int flags) { + // Allocate space for the most data the input could represent. + // (It could contain less if it contains whitespace, etc.) + Decoder decoder = new Decoder(flags, new byte[len * 3 / 4]); + + if (!decoder.process(input, offset, len, true)) { + throw new IllegalArgumentException("bad base-64"); + } + + // Maybe we got lucky and allocated exactly enough output space. + if (decoder.op == decoder.output.length) { + return decoder.output; + } + + // Need to shorten the array, so allocate a new one of the + // right size and copy. + byte[] temp = new byte[decoder.op]; + System.arraycopy(decoder.output, 0, temp, 0, decoder.op); + return temp; + } + + /** + * Base64-encode the given data and return a newly allocated String with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results + * in output that adheres to RFC 2045. + * @return base64 string containing encoded input + */ + public static String encodeToString(byte[] input, int flags) { + try { + return new String(encode(input, flags), "US-ASCII"); + } catch (UnsupportedEncodingException e) { + // US-ASCII is guaranteed to be available. + throw new AssertionError(e); + } + } + + // -------------------------------------------------------- + // encoding + // -------------------------------------------------------- + + /** + * Base64-encode the given data and return a newly allocated String with the result. + * + * @param input the data to encode + * @param offset the position within the input array at which to start + * @param len the number of bytes of input to encode + * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} + * results in output that adheres to RFC 2045. + * @return base64 string containing encoded range of input + */ + public static String encodeToString(byte[] input, int offset, int len, int flags) { + try { + return new String(encode(input, offset, len, flags), "US-ASCII"); + } catch (UnsupportedEncodingException e) { + // US-ASCII is guaranteed to be available. + throw new AssertionError(e); + } + } + + /** + * Base64-encode the given data and return a newly allocated byte[] with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results + * in output that adheres to RFC 2045. + * @return base64 encoded input as bytes + */ + public static byte[] encode(byte[] input, int flags) { + return encode(input, 0, input.length, flags); + } + + /** + * Base64-encode the given data and return a newly allocated byte[] with the result. + * + * @param input the data to encode + * @param offset the position within the input array at which to start + * @param len the number of bytes of input to encode + * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} + * results in output that adheres to RFC 2045. + * @return base64 encoded input as bytes + */ + public static byte[] encode(byte[] input, int offset, int len, int flags) { + Encoder encoder = new Encoder(flags, null); + + // Compute the exact length of the array we will produce. + int output_len = len / 3 * 4; + + // Account for the tail of the data and the padding bytes, if any. + if (encoder.do_padding) { + if (len % 3 > 0) { + output_len += 4; + } + } else { + switch (len % 3) { + case 0: + break; + case 1: + output_len += 2; + break; + case 2: + output_len += 3; + break; + } + } + + // Account for the newlines, if any. + if (encoder.do_newline && len > 0) { + output_len += (((len - 1) / (3 * Encoder.LINE_GROUPS)) + 1) * + (encoder.do_cr ? 2 : 1); + } + + encoder.output = new byte[output_len]; + encoder.process(input, offset, len, true); + + if (BuildConfig.DEBUG && encoder.op != output_len) { + throw new AssertionError(); + } + + return encoder.output; + } + + /* package */ static abstract class Coder { + public byte[] output; + public int op; + + /** + * Encode/decode another block of input data. this.output is provided by the caller, and + * must be big enough to hold all the coded data. On exit, this.opwill be set to the length + * of the coded data. + * + * @param finish true if this is the final call to process for this object. Will finalize + * the coder state and include any final bytes in the output. + * @return true if the input so far is good; false if some error has been detected in the + * input stream.. + */ + public abstract boolean process(byte[] input, int offset, int len, boolean finish); + + /** + * @return the maximum number of bytes a call to process() could produce for the given + * number of input bytes. This may be an overestimate. + */ + public abstract int maxOutputSize(int len); + } + + /* package */ static class Decoder extends Coder { + /** + * Lookup table for turning bytes into their position in the Base64 alphabet. + */ + private static final int DECODE[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + /** + * Decode lookup table for the "web safe" variant (RFC 3548 sec. 4) where - and _ replace + + * and /. + */ + private static final int DECODE_WEBSAFE[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + /** + * Non-data values in the DECODE arrays. + */ + private static final int SKIP = -1; + private static final int EQUALS = -2; + final private int[] alphabet; + /** + * States 0-3 are reading through the next input tuple. State 4 is having read one '=' and + * expecting exactly one more. State 5 is expecting no more data or padding characters in + * the input. State 6 is the error state; an error has been detected in the input and no + * future input can "fix" it. + */ + private int state; // state number (0 to 6) + private int value; + + public Decoder(int flags, byte[] output) { + this.output = output; + + alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE; + state = 0; + value = 0; + } + + /** + * @return an overestimate for the number of bytes {@code len} bytes could decode to. + */ + public int maxOutputSize(int len) { + return len * 3 / 4 + 10; + } + + /** + * Decode another block of input data. + * + * @return true if the state machine is still healthy. false if bad base-64 data has been + * detected in the input stream. + */ + public boolean process(byte[] input, int offset, int len, boolean finish) { + if (this.state == 6) return false; + + int p = offset; + len += offset; + + // Using local variables makes the decoder about 12% + // faster than if we manipulate the member variables in + // the loop. (Even alphabet makes a measurable + // difference, which is somewhat surprising to me since + // the member variable is final.) + int state = this.state; + int value = this.value; + int op = 0; + final byte[] output = this.output; + final int[] alphabet = this.alphabet; + + while (p < len) { + // Try the fast path: we're starting a new tuple and the + // next four bytes of the input stream are all data + // bytes. This corresponds to going through states + // 0-1-2-3-0. We expect to use this method for most of + // the data. + // + // If any of the next four bytes of input are non-data + // (whitespace, etc.), value will end up negative. (All + // the non-data values in decode are small negative + // numbers, so shifting any of them up and or'ing them + // together will result in a value with its top bit set.) + // + // You can remove this whole block and the output should + // be the same, just slower. + if (state == 0) { + while (p + 4 <= len && + (value = ((alphabet[input[p] & 0xff] << 18) | + (alphabet[input[p + 1] & 0xff] << 12) | + (alphabet[input[p + 2] & 0xff] << 6) | + (alphabet[input[p + 3] & 0xff]))) >= 0) { + output[op + 2] = (byte) value; + output[op + 1] = (byte) (value >> 8); + output[op] = (byte) (value >> 16); + op += 3; + p += 4; + } + if (p >= len) break; + } + + // The fast path isn't available -- either we've read a + // partial tuple, or the next four input bytes aren't all + // data, or whatever. Fall back to the slower state + // machine implementation. + + int d = alphabet[input[p++] & 0xff]; + + switch (state) { + case 0: + if (d >= 0) { + value = d; + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 1: + if (d >= 0) { + value = (value << 6) | d; + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 2: + if (d >= 0) { + value = (value << 6) | d; + ++state; + } else if (d == EQUALS) { + // Emit the last (partial) output tuple; + // expect exactly one more padding character. + output[op++] = (byte) (value >> 4); + state = 4; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 3: + if (d >= 0) { + // Emit the output triple and return to state 0. + value = (value << 6) | d; + output[op + 2] = (byte) value; + output[op + 1] = (byte) (value >> 8); + output[op] = (byte) (value >> 16); + op += 3; + state = 0; + } else if (d == EQUALS) { + // Emit the last (partial) output tuple; + // expect no further data or padding characters. + output[op + 1] = (byte) (value >> 2); + output[op] = (byte) (value >> 10); + op += 2; + state = 5; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 4: + if (d == EQUALS) { + ++state; + } else if (d != SKIP) { + this.state = 6; + return false; + } + break; + + case 5: + if (d != SKIP) { + this.state = 6; + return false; + } + break; + } + } + + if (!finish) { + // We're out of input, but a future call could provide + // more. + this.state = state; + this.value = value; + this.op = op; + return true; + } + + // Done reading input. Now figure out where we are left in + // the state machine and finish up. + + switch (state) { + case 0: + // Output length is a multiple of three. Fine. + break; + case 1: + // Read one extra input byte, which isn't enough to + // make another output byte. Illegal. + this.state = 6; + return false; + case 2: + // Read two extra input bytes, enough to emit 1 more + // output byte. Fine. + output[op++] = (byte) (value >> 4); + break; + case 3: + // Read three extra input bytes, enough to emit 2 more + // output bytes. Fine. + output[op++] = (byte) (value >> 10); + output[op++] = (byte) (value >> 2); + break; + case 4: + // Read one padding '=' when we expected 2. Illegal. + this.state = 6; + return false; + case 5: + // Read all the padding '='s we expected and no more. + // Fine. + break; + } + + this.state = state; + this.op = op; + return true; + } + } + + /* package */ static class Encoder extends Coder { + /** + * Emit a new line every this many output tuples. Corresponds to a 76-character line length + * (the maximum allowable according to RFC + * 2045). + */ + public static final int LINE_GROUPS = 19; + + /** + * Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. + */ + private static final byte ENCODE[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', + }; + + /** + * Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. + */ + private static final byte ENCODE_WEBSAFE[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', + }; + final public boolean do_padding; + final public boolean do_newline; + final public boolean do_cr; + final private byte[] tail; + final private byte[] alphabet; + /* package */ int tailLen; + private int count; + + public Encoder(int flags, byte[] output) { + this.output = output; + + do_padding = (flags & NO_PADDING) == 0; + do_newline = (flags & NO_WRAP) == 0; + do_cr = (flags & CRLF) != 0; + alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE; + + tail = new byte[2]; + tailLen = 0; + + count = do_newline ? LINE_GROUPS : -1; + } + + /** + * @return an overestimate for the number of bytes {@code len} bytes could encode to. + */ + public int maxOutputSize(int len) { + return len * 8 / 5 + 10; + } + + public boolean process(byte[] input, int offset, int len, boolean finish) { + // Using local variables makes the encoder about 9% faster. + final byte[] alphabet = this.alphabet; + final byte[] output = this.output; + int op = 0; + int count = this.count; + + int p = offset; + len += offset; + int v = -1; + + // First we need to concatenate the tail of the previous call + // with any input bytes available now and see if we can empty + // the tail. + + switch (tailLen) { + case 0: + // There was no tail. + break; + + case 1: + if (p + 2 <= len) { + // A 1-byte tail with at least 2 bytes of + // input available now. + v = ((tail[0] & 0xff) << 16) | + ((input[p++] & 0xff) << 8) | + (input[p++] & 0xff); + tailLen = 0; + } + break; + + case 2: + if (p + 1 <= len) { + // A 2-byte tail with at least 1 byte of input. + v = ((tail[0] & 0xff) << 16) | + ((tail[1] & 0xff) << 8) | + (input[p++] & 0xff); + tailLen = 0; + } + break; + } + + if (v != -1) { + output[op++] = alphabet[(v >> 18) & 0x3f]; + output[op++] = alphabet[(v >> 12) & 0x3f]; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (--count == 0) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + count = LINE_GROUPS; + } + } + + // At this point either there is no tail, or there are fewer + // than 3 bytes of input available. + + // The main loop, turning 3 input bytes into 4 output bytes on + // each iteration. + while (p + 3 <= len) { + v = ((input[p] & 0xff) << 16) | + ((input[p + 1] & 0xff) << 8) | + (input[p + 2] & 0xff); + output[op] = alphabet[(v >> 18) & 0x3f]; + output[op + 1] = alphabet[(v >> 12) & 0x3f]; + output[op + 2] = alphabet[(v >> 6) & 0x3f]; + output[op + 3] = alphabet[v & 0x3f]; + p += 3; + op += 4; + if (--count == 0) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + count = LINE_GROUPS; + } + } + + if (finish) { + // Finish up the tail of the input. Note that we need to + // consume any bytes in tail before any bytes + // remaining in input; there should be at most two bytes + // total. + + if (p - tailLen == len - 1) { + int t = 0; + v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4; + tailLen -= t; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (do_padding) { + output[op++] = '='; + output[op++] = '='; + } + if (do_newline) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + } else if (p - tailLen == len - 2) { + int t = 0; + v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) | + (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2); + tailLen -= t; + output[op++] = alphabet[(v >> 12) & 0x3f]; + output[op++] = alphabet[(v >> 6) & 0x3f]; + output[op++] = alphabet[v & 0x3f]; + if (do_padding) { + output[op++] = '='; + } + if (do_newline) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + } else if (do_newline && op > 0 && count != LINE_GROUPS) { + if (do_cr) output[op++] = '\r'; + output[op++] = '\n'; + } + + if (BuildConfig.DEBUG && (tailLen != 0 || p != len)) { + throw new AssertionError(); + } + } else { + // Save the leftovers in tail to be consumed on the next + // call to encodeInternal. + + if (p == len - 1) { + tail[tailLen++] = input[p]; + } else if (p == len - 2) { + tail[tailLen++] = input[p]; + tail[tailLen++] = input[p + 1]; + } + } + + this.op = op; + this.count = count; + + return true; + } + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64DataException.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64DataException.java new file mode 100644 index 0000000000000000000000000000000000000000..4ce9a012ecfda3e8b6bbf5d049da03a37869e7aa --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64DataException.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.httplibrary.utils; + +import java.io.IOException; + +public class Base64DataException extends IOException { + public Base64DataException(String detailMessage) { + super(detailMessage); + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64OutputStream.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64OutputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..96a3b8da187eeea6f14746e42ebc55914fc33ca9 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Base64OutputStream.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.httplibrary.utils; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Base64OutputStream extends FilterOutputStream { + private static final byte[] EMPTY = new byte[0]; + private final Base64.Coder coder; + private final int flags; + private byte[] buffer = null; + private int bpos = 0; + + /** + * Performs Base64 encoding on the data written to the stream, writing the encoded data to + * another OutputStream. + * + * @param out the OutputStream to write the encoded data to + * @param flags bit flags for controlling the encoder; see the constants in {@link Base64} + */ + public Base64OutputStream(OutputStream out, int flags) { + this(out, flags, true); + } + + /** + * Performs Base64 encoding or decoding on the data written to the stream, writing the + * encoded/decoded data to another OutputStream. + * + * @param out the OutputStream to write the encoded data to + * @param flags bit flags for controlling the encoder; see the constants in {@link Base64} + * @param encode true to encode, false to decode + */ + public Base64OutputStream(OutputStream out, int flags, boolean encode) { + super(out); + this.flags = flags; + if (encode) { + coder = new Base64.Encoder(flags, null); + } else { + coder = new Base64.Decoder(flags, null); + } + } + + @Override + public void write(int b) throws IOException { + // To avoid invoking the encoder/decoder routines for single + // bytes, we buffer up calls to write(int) in an internal + // byte array to transform them into writes of decently-sized + // arrays. + + if (buffer == null) { + buffer = new byte[1024]; + } + if (bpos >= buffer.length) { + // internal buffer full; write it out. + internalWrite(buffer, 0, bpos, false); + bpos = 0; + } + buffer[bpos++] = (byte) b; + } + + /** + * Flush any buffered data from calls to write(int). Needed before doing a write(byte[], int, + * int) or a close(). + */ + private void flushBuffer() throws IOException { + if (bpos > 0) { + internalWrite(buffer, 0, bpos, false); + bpos = 0; + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (len <= 0) return; + flushBuffer(); + internalWrite(b, off, len, false); + } + + @Override + public void close() throws IOException { + IOException thrown = null; + try { + flushBuffer(); + internalWrite(EMPTY, 0, 0, true); + } catch (IOException e) { + thrown = e; + } + + try { + if ((flags & Base64.NO_CLOSE) == 0) { + out.close(); + } else { + out.flush(); + } + } catch (IOException e) { + if (thrown != null) { + thrown = e; + } + } + + if (thrown != null) { + throw thrown; + } + } + + /** + * Write the given bytes to the encoder/decoder. + * + * @param finish true if this is the last batch of input, to cause encoder/decoder state to be + * finalized. + */ + private void internalWrite(byte[] b, int off, int len, boolean finish) throws IOException { + coder.output = embiggen(coder.output, coder.maxOutputSize(len)); + if (!coder.process(b, off, len, finish)) { + throw new Base64DataException("bad base-64"); + } + out.write(coder.output, 0, coder.op); + } + + /** + * If b.length is at least len, return b. Otherwise return a new byte array of length len. + */ + private byte[] embiggen(byte[] b, int len) { + if (b == null || b.length < len) { + return new byte[len]; + } else { + return b; + } + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BaseJsonHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BaseJsonHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..f96eb04d8454d573b32d2e68438519bff0f3287e --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BaseJsonHttpResponseHandler.java @@ -0,0 +1,155 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpStatus; + +/** + * Class meant to be used with custom JSON parser (such as GSON or Jackson JSON)

 

+ * {@link #parseResponse(String, boolean)} should be overriden and must return type of generic param + * class, response will be then handled to implementation of abstract methods {@link #onSuccess(int, + * Header[], String, Object)} or {@link #onFailure(int, Header[], + * Throwable, String, Object)}, depending of response HTTP status line (result http code) + * + * @param Generic type meant to be returned in callback + */ +public abstract class BaseJsonHttpResponseHandler extends TextHttpResponseHandler { + private static final String LOG_TAG = "BaseJsonHttpRH"; + + /** + * Creates a new JsonHttpResponseHandler with default charset "UTF-8" + */ + public BaseJsonHttpResponseHandler() { + this(DEFAULT_CHARSET); + } + + /** + * Creates a new JsonHttpResponseHandler with given string encoding + * + * @param encoding result string encoding, see Charset + */ + public BaseJsonHttpResponseHandler(String encoding) { + super(encoding); + } + + /** + * Base abstract method, handling defined generic type + * + * @param statusCode HTTP status line + * @param headers response headers + * @param rawJsonResponse string of response, can be null + * @param response response returned by {@link #parseResponse(String, boolean)} + */ + public abstract void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, JSON_TYPE response); + + /** + * Base abstract method, handling defined generic type + * + * @param statusCode HTTP status line + * @param headers response headers + * @param throwable error thrown while processing request + * @param rawJsonData raw string data returned if any + * @param errorResponse response returned by {@link #parseResponse(String, boolean)} + */ + public abstract void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, JSON_TYPE errorResponse); + + @Override + public final void onSuccess(final int statusCode, final Header[] headers, final String responseString) { + if (statusCode != HttpStatus.SC_NO_CONTENT) { + Runnable parser = new Runnable() { + @Override + public void run() { + try { + final JSON_TYPE jsonResponse = parseResponse(responseString, false); + postRunnable(new Runnable() { + @Override + public void run() { + onSuccess(statusCode, headers, responseString, jsonResponse); + } + }); + } catch (final Throwable t) { + AsyncHttpClient.log.d(LOG_TAG, "parseResponse thrown an problem", t); + postRunnable(new Runnable() { + @Override + public void run() { + onFailure(statusCode, headers, t, responseString, null); + } + }); + } + } + }; + if (!getUseSynchronousMode() && !getUsePoolThread()) { + new Thread(parser).start(); + } else { + // In synchronous mode everything should be run on one thread + parser.run(); + } + } else { + onSuccess(statusCode, headers, null, null); + } + } + + @Override + public final void onFailure(final int statusCode, final Header[] headers, final String responseString, final Throwable throwable) { + if (responseString != null) { + Runnable parser = new Runnable() { + @Override + public void run() { + try { + final JSON_TYPE jsonResponse = parseResponse(responseString, true); + postRunnable(new Runnable() { + @Override + public void run() { + onFailure(statusCode, headers, throwable, responseString, jsonResponse); + } + }); + } catch (Throwable t) { + AsyncHttpClient.log.d(LOG_TAG, "parseResponse thrown an problem", t); + postRunnable(new Runnable() { + @Override + public void run() { + onFailure(statusCode, headers, throwable, responseString, null); + } + }); + } + } + }; + if (!getUseSynchronousMode() && !getUsePoolThread()) { + new Thread(parser).start(); + } else { + // In synchronous mode everything should be run on one thread + parser.run(); + } + } else { + onFailure(statusCode, headers, throwable, null, null); + } + } + + /** + * Should return deserialized instance of generic type, may return object for more vague + * handling + * + * @param rawJsonData response string, may be null + * @param isFailure indicating if this method is called from onFailure or not + * @return object of generic type or possibly null if you choose so + * @throws Throwable allows you to throw anything from within deserializing JSON response + */ + protected abstract JSON_TYPE parseResponse(String rawJsonData, boolean isFailure) throws Throwable; +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BearerAuthSchemeFactory.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BearerAuthSchemeFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7bfd898c47b1b6c3e01e832cde68593cd7db5403 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BearerAuthSchemeFactory.java @@ -0,0 +1,83 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpRequest; +import cz.msebera.android.httpclient.auth.*; +import cz.msebera.android.httpclient.message.BufferedHeader; +import cz.msebera.android.httpclient.params.HttpParams; +import cz.msebera.android.httpclient.protocol.HttpContext; +import cz.msebera.android.httpclient.util.CharArrayBuffer; + +public class BearerAuthSchemeFactory implements AuthSchemeFactory { + + @Override + public AuthScheme newInstance(HttpParams params) { + return new BearerAuthScheme(); + } + + public static class BearerAuthScheme implements ContextAwareAuthScheme { + private boolean complete = false; + + @Override + public void processChallenge(Header header) throws MalformedChallengeException { + this.complete = true; + } + + @Override + public Header authenticate(Credentials credentials, HttpRequest request) throws AuthenticationException { + return authenticate(credentials, request, null); + } + + @Override + public Header authenticate(Credentials credentials, HttpRequest request, HttpContext httpContext) + throws AuthenticationException { + CharArrayBuffer buffer = new CharArrayBuffer(32); + buffer.append(AUTH.WWW_AUTH_RESP); + buffer.append(": Bearer "); + buffer.append(credentials.getUserPrincipal().getName()); + return new BufferedHeader(buffer); + } + + @Override + public String getSchemeName() { + return "Bearer"; + } + + @Override + public String getParameter(String name) { + return null; + } + + @Override + public String getRealm() { + return null; + } + + @Override + public boolean isConnectionBased() { + return false; + } + + @Override + public boolean isComplete() { + return this.complete; + } + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BinaryHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BinaryHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..e1f76837ffade4af576e8a65099c3c463407aaa1 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BinaryHttpResponseHandler.java @@ -0,0 +1,160 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpResponse; +import cz.msebera.android.httpclient.StatusLine; +import cz.msebera.android.httpclient.client.HttpResponseException; +import ohos.eventhandler.EventRunner; + +import java.io.IOException; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Used to intercept and handle the responses from requests made using {@link AsyncHttpClient}. + * Receives response body as byte array with a content-type whitelist. (e.g. checks Content-Type + * against allowed list, Content-length).

 

For example:

 

+ *
+ * AsyncHttpClient client = new AsyncHttpClient();
+ * String[] allowedTypes = new String[] { "image/png" };
+ * client.get("https://www.example.com/image.png", new BinaryHttpResponseHandler(allowedTypes) {
+ *     @Override
+ *     public void onSuccess(byte[] imageData) {
+ *         // Successfully got a response
+ *     }
+ *
+ *     @Override
+ *     public void onFailure(Throwable e, byte[] imageData) {
+ *         // Response failed :(
+ *     }
+ * });
+ * 
+ */ +public abstract class BinaryHttpResponseHandler extends AsyncHttpResponseHandler { + + private static final String LOG_TAG = "BinaryHttpRH"; + + private String[] mAllowedContentTypes = new String[]{ + RequestParams.APPLICATION_OCTET_STREAM, + "image/jpeg", + "image/png", + "image/gif" + }; + + /** + * Creates a new BinaryHttpResponseHandler + */ + public BinaryHttpResponseHandler() { + super(); + } + + /** + * Creates a new BinaryHttpResponseHandler, and overrides the default allowed content types with + * passed String array (hopefully) of content types. + * + * @param allowedContentTypes content types array, eg. 'image/jpeg' or pattern '.*' + */ + public BinaryHttpResponseHandler(String[] allowedContentTypes) { + super(); + if (allowedContentTypes != null) { + mAllowedContentTypes = allowedContentTypes; + } else { + AsyncHttpClient.log.e(LOG_TAG, "Constructor passed allowedContentTypes was null !"); + } + } + + /** + * Creates a new BinaryHttpResponseHandler with a user-supplied looper, and overrides the default allowed content types with + * passed String array (hopefully) of content types. + * + * @param allowedContentTypes content types array, eg. 'image/jpeg' or pattern '.*' + * @param looper The looper to work with + */ + public BinaryHttpResponseHandler(String[] allowedContentTypes, EventRunner looper) { + super(looper); + if (allowedContentTypes != null) { + mAllowedContentTypes = allowedContentTypes; + } else { + AsyncHttpClient.log.e(LOG_TAG, "Constructor passed allowedContentTypes was null !"); + } + } + + /** + * Method can be overriden to return allowed content types, can be sometimes better than passing + * data in constructor + * + * @return array of content-types or Pattern string templates (eg. '.*' to match every response) + */ + public String[] getAllowedContentTypes() { + return mAllowedContentTypes; + } + + @Override + public abstract void onSuccess(int statusCode, Header[] headers, byte[] binaryData); + + @Override + public abstract void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error); + + @Override + public final void sendResponseMessage(HttpResponse response) throws IOException { + StatusLine status = response.getStatusLine(); + Header[] contentTypeHeaders = response.getHeaders(AsyncHttpClient.HEADER_CONTENT_TYPE); + if (contentTypeHeaders.length != 1) { + //malformed/ambiguous HTTP Header, ABORT! + sendFailureMessage( + status.getStatusCode(), + response.getAllHeaders(), + null, + new HttpResponseException( + status.getStatusCode(), + "None, or more than one, Content-Type Header found!" + ) + ); + return; + } + Header contentTypeHeader = contentTypeHeaders[0]; + boolean foundAllowedContentType = false; + for (String anAllowedContentType : getAllowedContentTypes()) { + try { + if (Pattern.matches(anAllowedContentType, contentTypeHeader.getValue())) { + foundAllowedContentType = true; + } + } catch (PatternSyntaxException e) { + AsyncHttpClient.log.e(LOG_TAG, "Given pattern is not valid: " + anAllowedContentType, e); + } + } + if (!foundAllowedContentType) { + //Content-Type not in allowed list, ABORT! + sendFailureMessage( + status.getStatusCode(), + response.getAllHeaders(), + null, + new HttpResponseException( + status.getStatusCode(), + "Content-Type (" + contentTypeHeader.getValue() + ") not allowed!" + ) + ); + return; + } + super.sendResponseMessage(response); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BlackholeHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BlackholeHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..1fb925eae35786fd42a57996af66ccaf306f2573 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/BlackholeHttpResponseHandler.java @@ -0,0 +1,64 @@ +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpResponse; + +/** + * Blank implementation of ResponseHandlerInterface, which ignores all contents returned by + * remote HTTP endpoint, and discards all various log messages + *

 

+ * Use this implementation, if you deliberately want to ignore all response, because you cannot + * pass null ResponseHandlerInterface into AsyncHttpClient implementation + */ +public class BlackholeHttpResponseHandler extends AsyncHttpResponseHandler { + + @Override + public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { + + } + + @Override + public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { + + } + + @Override + public void onProgress(long bytesWritten, long totalSize) { + + } + + @Override + public void onCancel() { + + } + + @Override + public void onFinish() { + + } + + @Override + public void onPostProcessResponse(ResponseHandlerInterface instance, HttpResponse response) { + + } + + @Override + public void onPreProcessResponse(ResponseHandlerInterface instance, HttpResponse response) { + + } + + @Override + public void onRetry(int retryNo) { + + } + + @Override + public void onStart() { + + } + + @Override + public void onUserException(Throwable error) { + + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/ConscryptSSLProvider.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/ConscryptSSLProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..772c5d2d446fbb0c8640e23843049b72eb986aa5 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/ConscryptSSLProvider.java @@ -0,0 +1,16 @@ +package com.example.httplibrary.utils; + +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +public class ConscryptSSLProvider { + static final HiLogLabel label=new HiLogLabel(HiLog.ERROR,0x00101,"网络请求"); + public static void install(){ + try { +// Security.insertProviderAt(Conscrypt.newProviderBuilder().build(),1); + }catch (NoClassDefFoundError ex){ + HiLog.error(label, "","java.lang.NoClassDefFoundError: org.conscrypt.Conscrypt, Please add org.conscrypt.Conscrypt to your dependency"); + } + + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/DataAsyncHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/DataAsyncHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..cdbe32eba01e525435b172703134fe85bb4e44b7 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/DataAsyncHttpResponseHandler.java @@ -0,0 +1,153 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.HttpEntity; +import cz.msebera.android.httpclient.util.ByteArrayBuffer; +import ohos.eventhandler.InnerEvent; + +import java.io.IOException; +import java.io.InputStream; + +@SuppressWarnings("ALL") +public abstract class DataAsyncHttpResponseHandler extends AsyncHttpResponseHandler { + protected static final int PROGRESS_DATA_MESSAGE = 7; + private static final String LOG_TAG = "DataAsyncHttpRH"; + + /** + * Creates a new AsyncHttpResponseHandler + */ + public DataAsyncHttpResponseHandler() { + super(); + } + + /** + * Copies elements from {@code original} into a new array, from indexes start (inclusive) to end + * (exclusive). The original order of elements is preserved. If {@code end} is greater than + * {@code original.length}, the result is padded with the value {@code (byte) 0}. + * + * @param original the original array + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the new array + * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} + * @throws IllegalArgumentException if {@code start > end} + * @throws NullPointerException if {@code original == null} + * @see java.util.Arrays + * @since 1.6 + */ + public static byte[] copyOfRange(byte[] original, int start, int end) throws ArrayIndexOutOfBoundsException, IllegalArgumentException, NullPointerException { + if (start > end) { + throw new IllegalArgumentException(); + } + int originalLength = original.length; + if (start < 0 || start > originalLength) { + throw new ArrayIndexOutOfBoundsException(); + } + int resultLength = end - start; + int copyLength = Math.min(resultLength, originalLength - start); + byte[] result = new byte[resultLength]; + System.arraycopy(original, start, result, 0, copyLength); + return result; + } + + /** + * Fired when the request progress, override to handle in your own code + * + * @param responseBody response body received so far + */ + public void onProgressData(byte[] responseBody) { + AsyncHttpClient.log.d(LOG_TAG, "onProgressData(byte[]) was not overriden, but callback was received"); + } + + final public void sendProgressDataMessage(byte[] responseBytes) { + sendMessage(obtainMessage(PROGRESS_DATA_MESSAGE, new Object[]{responseBytes})); + } + + // Methods which emulate android's Handler and Message methods + @Override + protected void handleMessage(InnerEvent message) { + super.handleMessage(message); + Object[] response; + + switch (message.eventId) { + case PROGRESS_DATA_MESSAGE: + response = (Object[]) message.object; + if (response != null && response.length >= 1) { + try { + onProgressData((byte[]) response[0]); + } catch (Throwable t) { + AsyncHttpClient.log.e(LOG_TAG, "custom onProgressData contains an error", t); + } + } else { + AsyncHttpClient.log.e(LOG_TAG, "PROGRESS_DATA_MESSAGE didn't got enough params"); + } + break; + } + } + + /** + * Returns byte array of response HttpEntity contents + * + * @param entity can be null + * @return response entity body or null + * @throws IOException if reading entity or creating byte array failed + */ + @Override + byte[] getResponseData(HttpEntity entity) throws IOException { + + byte[] responseBody = null; + if (entity != null) { + InputStream instream = entity.getContent(); + if (instream != null) { + long contentLength = entity.getContentLength(); + if (contentLength > Integer.MAX_VALUE) { + throw new IllegalArgumentException("HTTP entity too large to be buffered in memory"); + } + if (contentLength < 0) { + contentLength = BUFFER_SIZE; + } + try { + ByteArrayBuffer buffer = new ByteArrayBuffer((int) contentLength); + try { + byte[] tmp = new byte[BUFFER_SIZE]; + int l, count = 0; + // do not send messages if request has been cancelled + while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) { + buffer.append(tmp, 0, l); + sendProgressDataMessage(copyOfRange(tmp, 0, l)); + sendProgressMessage(count, contentLength); + } + } finally { + AsyncHttpClient.silentCloseInputStream(instream); + } + responseBody = buffer.toByteArray(); + } catch (OutOfMemoryError e) { + System.gc(); + throw new IOException("File too large to fit into available memory"); + } + } + } + return responseBody; + } + + +} + diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/FileAsyncHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/FileAsyncHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..dac61790ad3482a77ffbc85058e13e0212643974 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/FileAsyncHttpResponseHandler.java @@ -0,0 +1,242 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpEntity; +import ohos.app.Context; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + + +public abstract class FileAsyncHttpResponseHandler extends AsyncHttpResponseHandler { + + private static final String LOG_TAG = "FileAsyncHttpRH"; + protected final File file; + protected final boolean append; + protected final boolean renameIfExists; + protected File frontendFile; + + /** + * Obtains new FileAsyncHttpResponseHandler and stores response in passed file + * + * @param file File to store response within, must not be null + */ + public FileAsyncHttpResponseHandler(File file) { + this(file, false); + } + + /** + * Obtains new FileAsyncHttpResponseHandler and stores response in passed file + * + * @param file File to store response within, must not be null + * @param append whether data should be appended to existing file + */ + public FileAsyncHttpResponseHandler(File file, boolean append) { + this(file, append, false); + } + + /** + * Obtains new FileAsyncHttpResponseHandler and stores response in passed file + * + * @param file File to store response within, must not be null + * @param append whether data should be appended to existing file + * @param renameTargetFileIfExists whether target file should be renamed if it already exists + */ + public FileAsyncHttpResponseHandler(File file, boolean append, boolean renameTargetFileIfExists) { + this(file,append,renameTargetFileIfExists,false); + } + + + /** + * Obtains new FileAsyncHttpResponseHandler and stores response in passed file + * + * @param file File to store response within, must not be null + * @param append whether data should be appended to existing file + * @param renameTargetFileIfExists whether target file should be renamed if it already exists + * @param usePoolThread Whether to use the pool's thread to fire callbacks + */ + public FileAsyncHttpResponseHandler(File file, boolean append, boolean renameTargetFileIfExists,boolean usePoolThread) { + super(usePoolThread); + Utils.asserts(file != null, "File passed into FileAsyncHttpResponseHandler constructor must not be null"); + if (!file.isDirectory() && !file.getParentFile().isDirectory()) { + Utils.asserts(file.getParentFile().mkdirs(), "Cannot create parent directories for requested File location"); + } + if (file.isDirectory()) { + if (!file.mkdirs()) { + AsyncHttpClient.log.d(LOG_TAG, "Cannot create directories for requested Directory location, might not be a problem"); + } + } + this.file = file; + this.append = append; + this.renameIfExists = renameTargetFileIfExists; + } + + /** + * Obtains new FileAsyncHttpResponseHandler against context with target being temporary file + * + * @param context Context, must not be null + */ + public FileAsyncHttpResponseHandler(Context context) { + super(); + this.file = getTemporaryFile(context); + this.append = false; + this.renameIfExists = false; + } + + /** + * Attempts to delete file with stored response + * + * @return false if the file does not exist or is null, true if it was successfully deleted + */ + public boolean deleteTargetFile() { + return getTargetFile() != null && getTargetFile().delete(); + } + + /** + * Used when there is no file to be used when calling constructor + * + * @param context Context, must not be null + * @return temporary file or null if creating file failed + */ + protected File getTemporaryFile(Context context) { + Utils.asserts(context != null, "Tried creating temporary file without having Context"); + try { + return File.createTempFile("temp_", "_handled", context.getCacheDir()); + } catch (IOException e) { + AsyncHttpClient.log.e(LOG_TAG, "Cannot create temporary file", e); + } + return null; + } + + /** + * Retrieves File object in which the response is stored + * + * @return File file in which the response was to be stored + */ + protected File getOriginalFile() { + Utils.asserts(file != null, "Target file is null, fatal!"); + return file; + } + + /** + * Retrieves File which represents response final location after possible renaming + * + * @return File final target file + */ + public File getTargetFile() { + if (frontendFile == null) { + frontendFile = getOriginalFile().isDirectory() ? getTargetFileByParsingURL() : getOriginalFile(); + } + return frontendFile; + } + + /** + * Will return File instance for file representing last URL segment in given folder. + * If file already exists and renameTargetFileIfExists was set as true, will try to find file + * which doesn't exist, naming template for such cases is "filename.ext" => "filename (%d).ext", + * or without extension "filename" => "filename (%d)" + * + * @return File in given directory constructed by last segment of request URL + */ + protected File getTargetFileByParsingURL() { + Utils.asserts(getOriginalFile().isDirectory(), "Target file is not a directory, cannot proceed"); + Utils.asserts(getRequestURI() != null, "RequestURI is null, cannot proceed"); + String requestURL = getRequestURI().toString(); + String filename = requestURL.substring(requestURL.lastIndexOf('/') + 1, requestURL.length()); + File targetFileRtn = new File(getOriginalFile(), filename); + if (targetFileRtn.exists() && renameIfExists) { + String format; + if (!filename.contains(".")) { + format = filename + " (%d)"; + } else { + format = filename.substring(0, filename.lastIndexOf('.')) + " (%d)" + filename.substring(filename.lastIndexOf('.'), filename.length()); + } + int index = 0; + while (true) { + targetFileRtn = new File(getOriginalFile(), String.format(format, index)); + if (!targetFileRtn.exists()) + return targetFileRtn; + index++; + } + } + return targetFileRtn; + } + + @Override + public final void onFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { + onFailure(statusCode, headers, throwable, getTargetFile()); + } + + /** + * Method to be overriden, receives as much of file as possible Called when the file is + * considered failure or if there is error when retrieving file + * + * @param statusCode http file status line + * @param headers file http headers if any + * @param throwable returned throwable + * @param file file in which the file is stored + */ + public abstract void onFailure(int statusCode, Header[] headers, Throwable throwable, File file); + + @Override + public final void onSuccess(int statusCode, Header[] headers, byte[] responseBytes) { + onSuccess(statusCode, headers, getTargetFile()); + } + + /** + * Method to be overriden, receives as much of response as possible + * + * @param statusCode http response status line + * @param headers response http headers if any + * @param file file in which the response is stored + */ + public abstract void onSuccess(int statusCode, Header[] headers, File file); + + @Override + protected byte[] getResponseData(HttpEntity entity) throws IOException { + if (entity != null) { + InputStream instream = entity.getContent(); + long contentLength = entity.getContentLength(); + FileOutputStream buffer = new FileOutputStream(getTargetFile(), this.append); + if (instream != null) { + try { + byte[] tmp = new byte[BUFFER_SIZE]; + int l, count = 0; + // do not send messages if request has been cancelled + while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) { + count += l; + buffer.write(tmp, 0, l); + sendProgressMessage(count, contentLength); + } + } finally { + AsyncHttpClient.silentCloseInputStream(instream); + buffer.flush(); + AsyncHttpClient.silentCloseOutputStream(buffer); + } + } + } + return null; + } + +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/HttpDelete.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/HttpDelete.java new file mode 100644 index 0000000000000000000000000000000000000000..c9130006e426622f8131f0cb46f51ad7f70e5f38 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/HttpDelete.java @@ -0,0 +1,59 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.client.methods.HttpEntityEnclosingRequestBase; + +import java.net.URI; + +/** + * The current Android (API level 21) bundled version of the Apache Http Client does not implement + * a HttpEntityEnclosingRequestBase type of HTTP DELETE method. + * Until the Android version is updated this can serve in it's stead. + * This implementation can and should go away when the official solution arrives. + */ +public final class HttpDelete extends HttpEntityEnclosingRequestBase { + public final static String METHOD_NAME = "DELETE"; + + public HttpDelete() { + super(); + } + + /** + * @param uri target url as URI + */ + public HttpDelete(final URI uri) { + super(); + setURI(uri); + } + + /** + * @param uri target url as String + * @throws IllegalArgumentException if the uri is invalid. + */ + public HttpDelete(final String uri) { + super(); + setURI(URI.create(uri)); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/HttpGet.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/HttpGet.java new file mode 100644 index 0000000000000000000000000000000000000000..cab73ae1d9476caeb4dde46d68b83e1f983633d4 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/HttpGet.java @@ -0,0 +1,60 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.client.methods.HttpEntityEnclosingRequestBase; + +import java.net.URI; + +/** + * The current Android (API level 21) bundled version of the Apache Http Client does not implement + * a HttpEntityEnclosingRequestBase type of HTTP GET method. + * Until the Android version is updated this can serve in it's stead. + * This implementation can and should go away when the official solution arrives. + */ +public final class HttpGet extends HttpEntityEnclosingRequestBase { + + public final static String METHOD_NAME = "GET"; + + public HttpGet() { + super(); + } + + /** + * @param uri target url as URI + */ + public HttpGet(final URI uri) { + super(); + setURI(uri); + } + + /** + * @param uri target url as String + * @throws IllegalArgumentException if the uri is invalid. + */ + public HttpGet(final String uri) { + super(); + setURI(URI.create(uri)); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..85bd67eeb3f9124d492661a2a01a1e9d36da5f3c --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonHttpResponseHandler.java @@ -0,0 +1,284 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpStatus; + +/** + * Used to intercept and handle the responses from requests made using {@link AsyncHttpClient}, with + * automatic parsing into a {@link JsonObject} or {@link JsonArray}.

 

This class is + * designed to be passed to get, post, put and delete requests with the or methods anonymously overridden.

 

+ * Additionally, you can override the other event methods from the parent class. + */ +public class JsonHttpResponseHandler extends TextHttpResponseHandler { + + private static final String LOG_TAG = "JsonHttpRH"; + + + private boolean useRFC5179CompatibilityMode = true; + + /** + * Creates new JsonHttpResponseHandler, with JSON String encoding UTF-8 + */ + public JsonHttpResponseHandler() { + super(DEFAULT_CHARSET); + } + + /** + * Creates new JsonHttpResponseHandler with given JSON String encoding + * + * @param encoding String encoding to be used when parsing JSON + */ + public JsonHttpResponseHandler(String encoding) { + super(encoding); + } + + /** + * Creates new JsonHttpResponseHandler with JSON String encoding UTF-8 and given RFC5179CompatibilityMode + * + * @param useRFC5179CompatibilityMode Boolean mode to use RFC5179 or latest + */ + public JsonHttpResponseHandler(boolean useRFC5179CompatibilityMode) { + super(DEFAULT_CHARSET); + this.useRFC5179CompatibilityMode = useRFC5179CompatibilityMode; + } + + /** + * Creates new JsonHttpResponseHandler with given JSON String encoding and RFC5179CompatibilityMode + * + * @param encoding String encoding to be used when parsing JSON + * @param useRFC5179CompatibilityMode Boolean mode to use RFC5179 or latest + */ + public JsonHttpResponseHandler(String encoding, boolean useRFC5179CompatibilityMode) { + super(encoding); + this.useRFC5179CompatibilityMode = useRFC5179CompatibilityMode; + } + + /** + * Returns when request succeeds + * + * @param statusCode http response status line + * @param headers response headers if any + * @param response parsed response if any + */ + public void onSuccess(int statusCode, Header[] headers, JsonObject response) { + AsyncHttpClient.log.w(LOG_TAG, "onSuccess(int, Header[], JSONObject) was not overriden, but callback was received"); + } + + /** + * Returns when request succeeds + * + * @param statusCode http response status line + * @param headers response headers if any + * @param response parsed response if any + */ + public void onSuccess(int statusCode, Header[] headers, JsonArray response) { + AsyncHttpClient.log.w(LOG_TAG, "onSuccess(int, Header[], JSONArray) was not overriden, but callback was received"); + } + + /** + * Returns when request failed + * + * @param statusCode http response status line + * @param headers response headers if any + * @param throwable throwable describing the way request failed + * @param errorResponse parsed response if any + */ + public void onFailure(int statusCode, Header[] headers, Throwable throwable, JsonObject errorResponse) { + AsyncHttpClient.log.w(LOG_TAG, "onFailure(int, Header[], Throwable, JSONObject) was not overriden, but callback was received", throwable); + } + + /** + * Returns when request failed + * + * @param statusCode http response status line + * @param headers response headers if any + * @param throwable throwable describing the way request failed + * @param errorResponse parsed response if any + */ + public void onFailure(int statusCode, Header[] headers, Throwable throwable, JsonArray errorResponse) { + AsyncHttpClient.log.w(LOG_TAG, "onFailure(int, Header[], Throwable, JSONArray) was not overriden, but callback was received", throwable); + } + + @Override + public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { + AsyncHttpClient.log.w(LOG_TAG, "onFailure(int, Header[], String, Throwable) was not overriden, but callback was received", throwable); + } + + @Override + public void onSuccess(int statusCode, Header[] headers, String responseString) { + AsyncHttpClient.log.w(LOG_TAG, "onSuccess(int, Header[], String) was not overriden, but callback was received"); + } + + @Override + public final void onSuccess(final int statusCode, final Header[] headers, final byte[] responseBytes) { + if (statusCode != HttpStatus.SC_NO_CONTENT) { + Runnable parser = new Runnable() { + @Override + public void run() { + try { + final Object jsonResponse = parseResponse(responseBytes); + postRunnable(new Runnable() { + @Override + public void run() { + // In RFC5179 a null value is not a valid JSON + if (!useRFC5179CompatibilityMode && jsonResponse == null) { + onSuccess(statusCode, headers, (String) null); + } else if (jsonResponse instanceof JsonObject) { + onSuccess(statusCode, headers, (JsonObject) jsonResponse); + } else if (jsonResponse instanceof JsonArray) { + onSuccess(statusCode, headers, (JsonArray) jsonResponse); + } else if (jsonResponse instanceof String) { + // In RFC5179 a simple string value is not a valid JSON + if (useRFC5179CompatibilityMode) { + AsyncHttpClient.log.e(LOG_TAG, "失败1"); +// onFailure(statusCode, headers, (String) jsonResponse, new JsonParseException("Response cannot be parsed as JSON data")); + onSuccess(statusCode, headers, (String) jsonResponse); + } else { + onSuccess(statusCode, headers, (String) jsonResponse); + } + } else { + AsyncHttpClient.log.e(LOG_TAG, "失败2"); + onFailure(statusCode, headers, new JsonParseException("Unexpected response type " + jsonResponse.getClass().getName()), (JsonObject) null); +// onSuccess(statusCode,headers,(String) jsonResponse); + } + } + }); + } catch (final Exception ex) { + postRunnable(new Runnable() { + @Override + public void run() { + onFailure(statusCode, headers, ex, (JsonObject) null); + } + }); + } + } + }; + if (!getUseSynchronousMode() && !getUsePoolThread()) { + new Thread(parser).start(); + } else { + // In synchronous mode everything should be run on one thread + parser.run(); + } + } else { + onSuccess(statusCode, headers, new JsonObject()); + } + } + + @Override + public final void onFailure(final int statusCode, final Header[] headers, final byte[] responseBytes, final Throwable throwable) { + if (responseBytes != null) { + Runnable parser = new Runnable() { + @Override + public void run() { + try { + final Object jsonResponse = parseResponse(responseBytes); + postRunnable(new Runnable() { + @Override + public void run() { + // In RFC5179 a null value is not a valid JSON + if (!useRFC5179CompatibilityMode && jsonResponse == null) { + onFailure(statusCode, headers, (String) null, throwable); + } else if (jsonResponse instanceof JsonObject) { + onFailure(statusCode, headers, throwable, (JsonObject) jsonResponse); + } else if (jsonResponse instanceof JsonArray) { + onFailure(statusCode, headers, throwable, (JsonArray) jsonResponse); + } else if (jsonResponse instanceof String) { + onFailure(statusCode, headers, (String) jsonResponse, throwable); + } else { + onFailure(statusCode, headers, new JsonParseException("Unexpected response type " + jsonResponse.getClass().getName()), (JsonObject) null); + } + } + }); + + } catch (final Exception ex) { + postRunnable(new Runnable() { + @Override + public void run() { + onFailure(statusCode, headers, ex, (JsonObject) null); + } + }); + + } + } + }; + if (!getUseSynchronousMode() && !getUsePoolThread()) { + new Thread(parser).start(); + } else { + // In synchronous mode everything should be run on one thread + parser.run(); + } + } else { + AsyncHttpClient.log.v(LOG_TAG, "response body is null, calling onFailure(Throwable, JSONObject)"); + onFailure(statusCode, headers, throwable, (JsonObject) null); + } + } + + + protected Object parseResponse(byte[] responseBody) throws JsonParseException { + if (null == responseBody) + return null; + Object result = null; + //trim the string to prevent start with blank, and test if the string is valid JSON, because the parser don't do this :(. If JSON is not valid this will return null + String jsonString = getResponseString(responseBody, getCharset()); + result=jsonString; + AsyncHttpClient.log.v(LOG_TAG, "zel-ResponseString:"+jsonString); + +// if (jsonString != null) { +// jsonString = jsonString.trim(); +// if (useRFC5179CompatibilityMode) { +// if (jsonString.startsWith("{") || jsonString.startsWith("[")) { +// result = new Gson().toJson(jsonString); +// } +// } else { +// // Check if the string is an JSONObject style {} or JSONArray style [] +// // If not we consider this as a string +// if ((jsonString.startsWith("{") && jsonString.endsWith("}")) +// || jsonString.startsWith("[") && jsonString.endsWith("]")) { +// result = new JSONTokener(jsonString).nextValue(); +// result = new Gson().toJson(jsonString); +// } +// // Check if this is a String "my String value" and remove quote +// // Other value type (numerical, boolean) should be without quote +// else if (jsonString.startsWith("\"") && jsonString.endsWith("\"")) { +// result = jsonString.substring(1, jsonString.length() - 1); +// } +// } +// } + if (result == null) { + result = jsonString; + } + return result; + } + + public boolean isUseRFC5179CompatibilityMode() { + return useRFC5179CompatibilityMode; + } + + public void setUseRFC5179CompatibilityMode(boolean useRFC5179CompatibilityMode) { + this.useRFC5179CompatibilityMode = useRFC5179CompatibilityMode; + } + +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonStreamerEntity.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonStreamerEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..601299c0a80d234f82acc0f170c496d4f395e0ff --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonStreamerEntity.java @@ -0,0 +1,391 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + +import com.google.gson.JsonObject; +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpEntity; +import cz.msebera.android.httpclient.message.BasicHeader; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.zip.GZIPOutputStream; + +/** + * HTTP entity to upload JSON data using streams. This has very low memory footprint; suitable for + * uploading large files using base64 encoding. + */ +public class JsonStreamerEntity implements HttpEntity { + + private static final String LOG_TAG = "JsonStreamerEntity"; + + private static final UnsupportedOperationException ERR_UNSUPPORTED = + new UnsupportedOperationException("Unsupported operation in this implementation."); + + // Size of the byte-array buffer used in I/O streams. + private static final int BUFFER_SIZE = 4096; + private static final byte[] JSON_TRUE = "true".getBytes(); + private static final byte[] JSON_FALSE = "false".getBytes(); + private static final byte[] JSON_NULL = "null".getBytes(); + private static final byte[] STREAM_NAME = escape("name"); + private static final byte[] STREAM_TYPE = escape("type"); + private static final byte[] STREAM_CONTENTS = escape("contents"); + private static final Header HEADER_JSON_CONTENT = + new BasicHeader( + AsyncHttpClient.HEADER_CONTENT_TYPE, + RequestParams.APPLICATION_JSON); + private static final Header HEADER_GZIP_ENCODING = + new BasicHeader( + AsyncHttpClient.HEADER_CONTENT_ENCODING, + AsyncHttpClient.ENCODING_GZIP); + // Buffer used for reading from input streams. + private final byte[] buffer = new byte[BUFFER_SIZE]; + // JSON data and associated meta-data to be uploaded. + private final Map jsonParams = new HashMap(); + + // Whether to use gzip compression while uploading + private final Header contentEncoding; + + private final byte[] elapsedField; + + private final ResponseHandlerInterface progressHandler; + + public JsonStreamerEntity(ResponseHandlerInterface progressHandler, boolean useGZipCompression, String elapsedField) { + this.progressHandler = progressHandler; + this.contentEncoding = useGZipCompression ? HEADER_GZIP_ENCODING : null; + this.elapsedField = elapsedField.isEmpty() + ? null + : escape(elapsedField); + } + + // Curtosy of Simple-JSON: https://goo.gl/XoW8RF + // Changed a bit to suit our needs in this class. + static byte[] escape(String string) { + // If it's null, just return prematurely. + if (string == null) { + return JSON_NULL; + } + + // Create a string builder to generate the escaped string. + StringBuilder sb = new StringBuilder(128); + + // Surround with quotations. + sb.append('"'); + + int length = string.length(), pos = -1; + while (++pos < length) { + char ch = string.charAt(pos); + switch (ch) { + case '"': + sb.append("\\\""); + break; + case '\\': + sb.append("\\\\"); + break; + case '\b': + sb.append("\\b"); + break; + case '\f': + sb.append("\\f"); + break; + case '\n': + sb.append("\\n"); + break; + case '\r': + sb.append("\\r"); + break; + case '\t': + sb.append("\\t"); + break; + default: + // Reference: https://www.unicode.org/versions/Unicode5.1.0/ + if ((ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) { + String intString = Integer.toHexString(ch); + sb.append("\\u"); + int intLength = 4 - intString.length(); + for (int zero = 0; zero < intLength; zero++) { + sb.append('0'); + } + sb.append(intString.toUpperCase(Locale.US)); + } else { + sb.append(ch); + } + break; + } + } + + // Surround with quotations. + sb.append('"'); + + return sb.toString().getBytes(); + } + + /** + * Add content parameter, identified by the given key, to the request. + * + * @param key entity's name + * @param value entity's value (Scalar, FileWrapper, StreamWrapper) + */ + public void addPart(String key, Object value) { + jsonParams.put(key, value); + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public boolean isChunked() { + return false; + } + + @Override + public boolean isStreaming() { + return false; + } + + @Override + public long getContentLength() { + return -1; + } + + @Override + public Header getContentEncoding() { + return contentEncoding; + } + + @Override + public Header getContentType() { + return HEADER_JSON_CONTENT; + } + + @Override + public void consumeContent() throws IOException, UnsupportedOperationException { + } + + @Override + public InputStream getContent() throws IOException, UnsupportedOperationException { + throw ERR_UNSUPPORTED; + } + + @Override + public void writeTo(final OutputStream out) throws IOException { + if (out == null) { + throw new IllegalStateException("Output stream cannot be null."); + } + + // Record the time when uploading started. + long now = System.currentTimeMillis(); + + // Use GZIP compression when sending streams, otherwise just use + // a buffered output stream to speed things up a bit. + OutputStream os = contentEncoding != null + ? new GZIPOutputStream(out, BUFFER_SIZE) + : out; + + // Always send a JSON object. + os.write('{'); + + // Keys used by the HashMaps. + Set keys = jsonParams.keySet(); + + int keysCount = keys.size(); + if (0 < keysCount) { + int keysProcessed = 0; + boolean isFileWrapper; + + // Go over all keys and handle each's value. + for (String key : keys) { + // Indicate that this key has been processed. + keysProcessed++; + + try { + // Evaluate the value (which cannot be null). + Object value = jsonParams.get(key); + + // Write the JSON object's key. + os.write(escape(key)); + os.write(':'); + + // Bail out prematurely if value's null. + if (value == null) { + os.write(JSON_NULL); + } else { + // Check if this is a FileWrapper. + isFileWrapper = value instanceof RequestParams.FileWrapper; + + // If a file should be uploaded. + if (isFileWrapper || value instanceof RequestParams.StreamWrapper) { + // All uploads are sent as an object containing the file's details. + os.write('{'); + + // Determine how to handle this entry. + if (isFileWrapper) { + writeToFromFile(os, (RequestParams.FileWrapper) value); + } else { + writeToFromStream(os, (RequestParams.StreamWrapper) value); + } + + // End the file's object and prepare for next one. + os.write('}'); + } else if (value instanceof JsonValueInterface) { + os.write(((JsonValueInterface) value).getEscapedJsonValue()); + } else if (value instanceof JsonObject) { + os.write(value.toString().getBytes()); + } else if (value instanceof JsonObject) { + os.write(value.toString().getBytes()); + } else if (value instanceof Boolean) { + os.write((Boolean) value ? JSON_TRUE : JSON_FALSE); + } else if (value instanceof Long) { + os.write((((Number) value).longValue() + "").getBytes()); + } else if (value instanceof Double) { + os.write((((Number) value).doubleValue() + "").getBytes()); + } else if (value instanceof Float) { + os.write((((Number) value).floatValue() + "").getBytes()); + } else if (value instanceof Integer) { + os.write((((Number) value).intValue() + "").getBytes()); + } else { + os.write(escape(value.toString())); + } + } + } finally { + // Separate each K:V with a comma, except the last one. + if (elapsedField != null || keysProcessed < keysCount) { + os.write(','); + } + } + } + + // Calculate how many milliseconds it took to upload the contents. + long elapsedTime = System.currentTimeMillis() - now; + + // Include the elapsed time taken to upload everything. + // This might be useful for somebody, but it serves us well since + // there will almost always be a ',' as the last sent character. + if (elapsedField != null) { + os.write(elapsedField); + os.write(':'); + os.write((elapsedTime + "").getBytes()); + } + + AsyncHttpClient.log.i(LOG_TAG, "Uploaded JSON in " + Math.floor(elapsedTime / 1000) + " seconds"); + } + + // Close the JSON object. + os.write('}'); + + // Flush the contents up the stream. + os.flush(); + AsyncHttpClient.silentCloseOutputStream(os); + } + + private void writeToFromStream(OutputStream os, RequestParams.StreamWrapper entry) + throws IOException { + + // Send the meta data. + writeMetaData(os, entry.name, entry.contentType); + + int bytesRead; + + // Upload the file's contents in Base64. + Base64OutputStream bos = + new Base64OutputStream(os, Base64.NO_CLOSE | Base64.NO_WRAP); + + // Read from input stream until no more data's left to read. + while ((bytesRead = entry.inputStream.read(buffer)) != -1) { + bos.write(buffer, 0, bytesRead); + } + + // Close the Base64 output stream. + AsyncHttpClient.silentCloseOutputStream(bos); + + // End the meta data. + endMetaData(os); + + // Close input stream. + if (entry.autoClose) { + // Safely close the input stream. + AsyncHttpClient.silentCloseInputStream(entry.inputStream); + } + } + + private void writeToFromFile(OutputStream os, RequestParams.FileWrapper wrapper) + throws IOException { + + // Send the meta data. + writeMetaData(os, wrapper.file.getName(), wrapper.contentType); + + int bytesRead; + long bytesWritten = 0, totalSize = wrapper.file.length(); + + // Open the file for reading. + FileInputStream in = new FileInputStream(wrapper.file); + + // Upload the file's contents in Base64. + Base64OutputStream bos = + new Base64OutputStream(os, Base64.NO_CLOSE | Base64.NO_WRAP); + + // Read from file until no more data's left to read. + while ((bytesRead = in.read(buffer)) != -1) { + bos.write(buffer, 0, bytesRead); + bytesWritten += bytesRead; + progressHandler.sendProgressMessage(bytesWritten, totalSize); + } + + // Close the Base64 output stream. + AsyncHttpClient.silentCloseOutputStream(bos); + + // End the meta data. + endMetaData(os); + + // Safely close the input stream. + AsyncHttpClient.silentCloseInputStream(in); + } + + private void writeMetaData(OutputStream os, String name, String contentType) throws IOException { + // Send the streams's name. + os.write(STREAM_NAME); + os.write(':'); + os.write(escape(name)); + os.write(','); + + // Send the streams's content type. + os.write(STREAM_TYPE); + os.write(':'); + os.write(escape(contentType)); + os.write(','); + + // Prepare the file content's key. + os.write(STREAM_CONTENTS); + os.write(':'); + os.write('"'); + } + + private void endMetaData(OutputStream os) throws IOException { + os.write('"'); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonValueInterface.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonValueInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..1bb03fbfc3d12820973642f4526d935362ed7679 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/JsonValueInterface.java @@ -0,0 +1,30 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + +public interface JsonValueInterface { + + /** + * Returns the escaped, ready-to-be used value of this encapsulated object. + * + * @return byte array holding the data to be used (as-is) in a JSON object + */ + byte[] getEscapedJsonValue(); +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/LogHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/LogHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..470d17d8d17da24793a533e9905cc0be62d683f9 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/LogHandler.java @@ -0,0 +1,129 @@ +package com.example.httplibrary.utils; + +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +public class LogHandler implements LogInterface { + static final HiLogLabel label=new HiLogLabel(HiLog.DEBUG,0x00101,"网络请求"); + + boolean mLoggingEnabled = true; + int mLoggingLevel = VERBOSE; + + @Override + public boolean isLoggingEnabled() { + return mLoggingEnabled; + } + + @Override + public void setLoggingEnabled(boolean loggingEnabled) { + this.mLoggingEnabled = loggingEnabled; + } + + @Override + public int getLoggingLevel() { + return mLoggingLevel; + } + + @Override + public void setLoggingLevel(int loggingLevel) { + this.mLoggingLevel = loggingLevel; + } + + @Override + public boolean shouldLog(int logLevel) { + return logLevel >= mLoggingLevel; + } + + public void log(int logLevel, String tag, String msg) { + logWithThrowable(logLevel, tag, msg, null); + } + + public void logWithThrowable(int logLevel, String tag, String msg, Throwable t) { + if (isLoggingEnabled() && shouldLog(logLevel)) { + switch (logLevel) { + case VERBOSE: + HiLog.fatal(label, msg, t); + break; + case WARN: + HiLog.warn(label, msg, t); + break; + case ERROR: + HiLog.error(label, msg, t); + break; + case DEBUG: + HiLog.debug(label, msg, t); + break; + case WTF: + checkedWtf(tag, msg, t); + break; + case INFO: + HiLog.info(label, msg, t); + break; + } + } + } + + private void checkedWtf(String tag, String msg, Throwable t) { + HiLog.error(label, msg, t); + } + + @Override + public void v(String tag, String msg) { + log(VERBOSE, tag, msg); + } + + @Override + public void v(String tag, String msg, Throwable t) { + logWithThrowable(VERBOSE, tag, msg, t); + } + + @Override + public void d(String tag, String msg) { + log(VERBOSE, tag, msg); + } + + @Override + public void d(String tag, String msg, Throwable t) { + logWithThrowable(DEBUG, tag, msg, t); + } + + @Override + public void i(String tag, String msg) { + log(INFO, tag, msg); + } + + @Override + public void i(String tag, String msg, Throwable t) { + logWithThrowable(INFO, tag, msg, t); + } + + @Override + public void w(String tag, String msg) { + log(WARN, tag, msg); + } + + @Override + public void w(String tag, String msg, Throwable t) { + logWithThrowable(WARN, tag, msg, t); + } + + @Override + public void e(String tag, String msg) { + log(ERROR, tag, msg); + } + + @Override + public void e(String tag, String msg, Throwable t) { + logWithThrowable(ERROR, tag, msg, t); + } + + @Override + public void wtf(String tag, String msg) { + log(WTF, tag, msg); + } + + @Override + public void wtf(String tag, String msg, Throwable t) { + logWithThrowable(WTF, tag, msg, t); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/LogInterface.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/LogInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..280cf94c68d12302f43a100653ba043aba8e7175 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/LogInterface.java @@ -0,0 +1,47 @@ +package com.example.httplibrary.utils; + +public interface LogInterface { + + int VERBOSE = 2; + int DEBUG = 3; + int INFO = 4; + int WARN = 5; + int ERROR = 6; + int WTF = 8; + + boolean isLoggingEnabled(); + + void setLoggingEnabled(boolean loggingEnabled); + + int getLoggingLevel(); + + void setLoggingLevel(int loggingLevel); + + boolean shouldLog(int logLevel); + + void v(String tag, String msg); + + void v(String tag, String msg, Throwable t); + + void d(String tag, String msg); + + void d(String tag, String msg, Throwable t); + + void i(String tag, String msg); + + void i(String tag, String msg, Throwable t); + + void w(String tag, String msg); + + void w(String tag, String msg, Throwable t); + + void e(String tag, String msg); + + void e(String tag, String msg, Throwable t); + + void wtf(String tag, String msg); + + void wtf(String tag, String msg, Throwable t); + + +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/MyRedirectHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/MyRedirectHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..f86db445999e3be52bb1d1f37afe2040a5768f79 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/MyRedirectHandler.java @@ -0,0 +1,161 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2014 Aymon Fournier + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.*; +import cz.msebera.android.httpclient.client.CircularRedirectException; +import cz.msebera.android.httpclient.client.params.ClientPNames; +import cz.msebera.android.httpclient.client.utils.URIUtils; +import cz.msebera.android.httpclient.impl.client.DefaultRedirectHandler; +import cz.msebera.android.httpclient.impl.client.RedirectLocations; +import cz.msebera.android.httpclient.params.HttpParams; +import cz.msebera.android.httpclient.protocol.ExecutionContext; +import cz.msebera.android.httpclient.protocol.HttpContext; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Taken from StackOverflow + * + * @author Aymon Fournier, aymon.fournier@gmail.com + * @see https://stackoverflow.com/questions/3420767/httpclient-redirecting-to-url-with-spaces-throwing-exception + */ +class MyRedirectHandler extends DefaultRedirectHandler { + + private static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations"; + private final boolean enableRedirects; + + public MyRedirectHandler(final boolean allowRedirects) { + super(); + this.enableRedirects = allowRedirects; + } + + @Override + public boolean isRedirectRequested( + final HttpResponse response, + final HttpContext context) { + if (!enableRedirects) { + return false; + } + if (response == null) { + throw new IllegalArgumentException("HTTP response may not be null"); + } + int statusCode = response.getStatusLine().getStatusCode(); + switch (statusCode) { + case HttpStatus.SC_MOVED_TEMPORARILY: + case HttpStatus.SC_MOVED_PERMANENTLY: + case HttpStatus.SC_SEE_OTHER: + case HttpStatus.SC_TEMPORARY_REDIRECT: + return true; + default: + return false; + } //end of switch + } + + @Override + public URI getLocationURI( + final HttpResponse response, + final HttpContext context) throws ProtocolException { + if (response == null) { + throw new IllegalArgumentException("HTTP response may not be null"); + } + //get the location header to find out where to redirect to + Header locationHeader = response.getFirstHeader("location"); + if (locationHeader == null) { + // got a redirect response, but no location header + throw new ProtocolException( + "Received redirect response " + response.getStatusLine() + + " but no location header" + ); + } + //HERE IS THE MODIFIED LINE OF CODE + String location = locationHeader.getValue().replaceAll(" ", "%20"); + + URI uri; + try { + uri = new URI(location); + } catch (URISyntaxException ex) { + throw new ProtocolException("Invalid redirect URI: " + location, ex); + } + + HttpParams params = response.getParams(); + // rfc2616 demands the location value be a complete URI + // Location = "Location" ":" absoluteURI + if (!uri.isAbsolute()) { + if (params.isParameterTrue(ClientPNames.REJECT_RELATIVE_REDIRECT)) { + throw new ProtocolException("Relative redirect location '" + + uri + "' not allowed"); + } + // Adjust location URI + HttpHost target = (HttpHost) context.getAttribute( + ExecutionContext.HTTP_TARGET_HOST); + if (target == null) { + throw new IllegalStateException("Target host not available " + + "in the HTTP context"); + } + + HttpRequest request = (HttpRequest) context.getAttribute( + ExecutionContext.HTTP_REQUEST); + + try { + URI requestURI = new URI(request.getRequestLine().getUri()); + URI absoluteRequestURI = URIUtils.rewriteURI(requestURI, target, true); + uri = URIUtils.resolve(absoluteRequestURI, uri); + } catch (URISyntaxException ex) { + throw new ProtocolException(ex.getMessage(), ex); + } + } + + if (params.isParameterFalse(ClientPNames.ALLOW_CIRCULAR_REDIRECTS)) { + + RedirectLocations redirectLocations = (RedirectLocations) context.getAttribute( + REDIRECT_LOCATIONS); + + if (redirectLocations == null) { + redirectLocations = new RedirectLocations(); + context.setAttribute(REDIRECT_LOCATIONS, redirectLocations); + } + + URI redirectURI; + if (uri.getFragment() != null) { + try { + HttpHost target = new HttpHost( + uri.getHost(), + uri.getPort(), + uri.getScheme()); + redirectURI = URIUtils.rewriteURI(uri, target, true); + } catch (URISyntaxException ex) { + throw new ProtocolException(ex.getMessage(), ex); + } + } else { + redirectURI = uri; + } + + if (redirectLocations.contains(redirectURI)) { + throw new CircularRedirectException("Circular redirect to '" + + redirectURI + "'"); + } else { + redirectLocations.add(redirectURI); + } + } + + return uri; + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/MySSLSocketFactory.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/MySSLSocketFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d30ba4b4ff78fe3b25cf5130eed6112ae812ed78 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/MySSLSocketFactory.java @@ -0,0 +1,220 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.HttpVersion; +import cz.msebera.android.httpclient.conn.ClientConnectionManager; +import cz.msebera.android.httpclient.conn.scheme.PlainSocketFactory; +import cz.msebera.android.httpclient.conn.scheme.Scheme; +import cz.msebera.android.httpclient.conn.scheme.SchemeRegistry; +import cz.msebera.android.httpclient.conn.ssl.SSLSocketFactory; +import cz.msebera.android.httpclient.impl.client.DefaultHttpClient; +import cz.msebera.android.httpclient.impl.conn.tsccm.ThreadSafeClientConnManager; +import cz.msebera.android.httpclient.params.BasicHttpParams; +import cz.msebera.android.httpclient.params.HttpParams; +import cz.msebera.android.httpclient.params.HttpProtocolParams; +import cz.msebera.android.httpclient.protocol.HTTP; + +import javax.net.ssl.*; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * This file is introduced to fix HTTPS Post bug on API < ICS see + * https://code.google.com/p/android/issues/detail?id=13117#c14

 

Warning! This omits SSL + * certificate validation on every device, use with caution + */ +public class MySSLSocketFactory extends SSLSocketFactory { + final SSLContext sslContext = SSLContext.getInstance("TLS"); + + /** + * Creates a new SSL Socket Factory with the given KeyStore. + * + * @param truststore A KeyStore to create the SSL Socket Factory in context of + * @throws NoSuchAlgorithmException NoSuchAlgorithmException + * @throws KeyManagementException KeyManagementException + * @throws KeyStoreException KeyStoreException + * @throws UnrecoverableKeyException UnrecoverableKeyException + */ + public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + super(truststore); + + X509TrustManager tm = new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + chain[0].checkValidity(); + } catch (Exception e) { + throw new CertificateException("Certificate not valid or trusted."); + } + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + chain[0].checkValidity(); + } catch (Exception e) { + throw new CertificateException("Certificate not valid or trusted."); + } + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + + sslContext.init(null, new TrustManager[]{tm}, null); + } + + /** + * Gets a KeyStore containing the Certificate + * + * @param cert InputStream of the Certificate + * @return KeyStore + */ + public static KeyStore getKeystoreOfCA(InputStream cert) { + + // Load CAs from an InputStream + InputStream caInput = null; + Certificate ca = null; + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + caInput = new BufferedInputStream(cert); + ca = cf.generateCertificate(caInput); + } catch (CertificateException e1) { + e1.printStackTrace(); + } finally { + try { + if (caInput != null) { + caInput.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Create a KeyStore containing our trusted CAs + String keyStoreType = KeyStore.getDefaultType(); + KeyStore keyStore = null; + try { + keyStore = KeyStore.getInstance(keyStoreType); + keyStore.load(null, null); + keyStore.setCertificateEntry("ca", ca); + } catch (Exception e) { + e.printStackTrace(); + } + return keyStore; + } + + /** + * Gets a Default KeyStore + * + * @return KeyStore + */ + public static KeyStore getKeystore() { + KeyStore trustStore = null; + try { + trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + } catch (Throwable t) { + t.printStackTrace(); + } + return trustStore; + } + + /** + * Returns a SSlSocketFactory which trusts all certificates + * + * @return SSLSocketFactory + */ + public static SSLSocketFactory getFixedSocketFactory() { + SSLSocketFactory socketFactory; + try { + socketFactory = new MySSLSocketFactory(getKeystore()); + socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + } catch (Throwable t) { + t.printStackTrace(); + socketFactory = SSLSocketFactory.getSocketFactory(); + } + return socketFactory; + } + + /** + * Gets a DefaultHttpClient which trusts a set of certificates specified by the KeyStore + * + * @param keyStore custom provided KeyStore instance + * @return DefaultHttpClient + */ + public static DefaultHttpClient getNewHttpClient(KeyStore keyStore) { + + try { + SSLSocketFactory sf = new MySSLSocketFactory(keyStore); + SchemeRegistry registry = new SchemeRegistry(); + registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); + registry.register(new Scheme("https", sf, 443)); + + HttpParams params = new BasicHttpParams(); + HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); + HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); + + ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); + + return new DefaultHttpClient(ccm, params); + } catch (Exception e) { + return new DefaultHttpClient(); + } + } + + @Override + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { + Socket localSocket = sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); + enableSecureProtocols(localSocket); + return localSocket; + } + + @Override + public Socket createSocket() throws IOException { + Socket socket = sslContext.getSocketFactory().createSocket(); + enableSecureProtocols(socket); + return socket; + } + + /** + * Activate supported protocols on the socket. + * + * @param socket The socket on which to activate secure protocols. + */ + private void enableSecureProtocols(Socket socket) { + // set all supported protocols + SSLParameters params = sslContext.getSupportedSSLParameters(); + ((SSLSocket) socket).setEnabledProtocols(params.getProtocols()); + } + + /** + * Makes HttpsURLConnection trusts a set of certificates specified by the KeyStore + */ + public void fixHttpsURLConnection() { + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/PersistentCookieStore.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/PersistentCookieStore.java new file mode 100644 index 0000000000000000000000000000000000000000..dfc770bee4284a2b71bdba3419c5c42eb0b7efe6 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/PersistentCookieStore.java @@ -0,0 +1,259 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.client.CookieStore; +import cz.msebera.android.httpclient.cookie.Cookie; +import ohos.app.Context; +import ohos.data.DatabaseHelper; +import ohos.data.preferences.Preferences; + +import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A persistent cookie store which implements the Apache HttpClient {@link CookieStore} interface. + * Cookies are stored and will persist on the user's device between application sessions since they + * are serialized and stored in {@link Preferences}.

 

Instances of this class are + * designed to be used with {@link AsyncHttpClient#setCookieStore}, but can also be used with a + * regular old apache HttpClient/HttpContext if you prefer. + */ +public class PersistentCookieStore implements CookieStore { + private static final String LOG_TAG = "PersistentCookieStore"; + private static final String COOKIE_PREFS = "CookiePrefsFile"; + private static final String COOKIE_NAME_STORE = "names"; + private static final String COOKIE_NAME_PREFIX = "cookie_"; + private final ConcurrentHashMap cookies; + private final Preferences cookiePrefs; + private boolean omitNonPersistentCookies = false; + + /** + * Construct a persistent cookie store. + * + * @param context Context to attach cookie store to + */ + public PersistentCookieStore(Context context) { + DatabaseHelper helper=new DatabaseHelper(context); + cookiePrefs=helper.getPreferences("COOKIE_PREFS"); +// cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0); + cookies = new ConcurrentHashMap(); + + // Load any previously stored cookies into the store + String storedCookieNames = cookiePrefs.getString(COOKIE_NAME_STORE, null); + if (storedCookieNames != null) { + String[] cookieNames = storedCookieNames.split( ","); + for (String name : cookieNames) { + String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null); + if (encodedCookie != null) { + Cookie decodedCookie = decodeCookie(encodedCookie); + if (decodedCookie != null) { + cookies.put(name, decodedCookie); + } + } + } + + // Clear out expired cookies + clearExpired(new Date()); + } + } + + @Override + public void addCookie(Cookie cookie) { + if (omitNonPersistentCookies && !cookie.isPersistent()) + return; + String name = cookie.getName() + cookie.getDomain(); + + // Save cookie into local store, or remove if expired + if (!cookie.isExpired(new Date())) { + cookies.put(name, cookie); + } else { + cookies.remove(name); + } + + // Save cookie into persistent store +// SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); + cookiePrefs.putString(COOKIE_NAME_STORE, getKeySetString(cookies.keySet())); + cookiePrefs.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableCookie(cookie))); +// prefsWriter.putString(COOKIE_NAME_STORE, TextUtils.join(",", cookies.keySet())); +// prefsWriter.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableCookie(cookie))); + cookiePrefs.flush(); + } + + @Override + public void clear() { + // Clear cookies from persistent store +// SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); + for (String name : cookies.keySet()) { + cookiePrefs.delete(COOKIE_NAME_PREFIX + name); + } + cookiePrefs.delete(COOKIE_NAME_STORE); + cookiePrefs.flush(); + + // Clear cookies from local store + cookies.clear(); + } + + @Override + public boolean clearExpired(Date date) { + boolean clearedAny = false; +// SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); + + for (ConcurrentHashMap.Entry entry : cookies.entrySet()) { + String name = entry.getKey(); + Cookie cookie = entry.getValue(); + if (cookie.isExpired(date)) { + // Clear cookies from local store + cookies.remove(name); + + // Clear cookies from persistent store + cookiePrefs.delete(COOKIE_NAME_PREFIX + name); + + // We've cleared at least one + clearedAny = true; + } + } + + // Update names in persistent store + if (clearedAny) { + cookiePrefs.putString(COOKIE_NAME_STORE, getKeySetString(cookies.keySet())); + } + cookiePrefs.flush(); + + return clearedAny; + } + + @Override + public List getCookies() { + return new ArrayList(cookies.values()); + } + + /** + * Will make PersistentCookieStore instance ignore Cookies, which are non-persistent by + * signature (`Cookie.isPersistent`) + * + * @param omitNonPersistentCookies true if non-persistent cookies should be omited + */ + public void setOmitNonPersistentCookies(boolean omitNonPersistentCookies) { + this.omitNonPersistentCookies = omitNonPersistentCookies; + } + + /** + * Non-standard helper method, to delete cookie + * + * @param cookie cookie to be removed + */ + public void deleteCookie(Cookie cookie) { + String name = cookie.getName() + cookie.getDomain(); + cookies.remove(name); +// SharedPreferences.Editor prefsWriter = cookiePrefs.edit(); + cookiePrefs.delete(COOKIE_NAME_PREFIX + name); + cookiePrefs.flush(); +// prefsWriter.apply(); + } + + /** + * Serializes Cookie object into String + * + * @param cookie cookie to be encoded, can be null + * @return cookie encoded as String + */ + protected String encodeCookie(SerializableCookie cookie) { + if (cookie == null) + return null; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + ObjectOutputStream outputStream = new ObjectOutputStream(os); + outputStream.writeObject(cookie); + } catch (IOException e) { + AsyncHttpClient.log.d(LOG_TAG, "IOException in encodeCookie", e); + return null; + } + + return byteArrayToHexString(os.toByteArray()); + } + + /** + * Returns cookie decoded from cookie string + * + * @param cookieString string of cookie as returned from http request + * @return decoded cookie or null if exception occured + */ + protected Cookie decodeCookie(String cookieString) { + byte[] bytes = hexStringToByteArray(cookieString); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); + Cookie cookie = null; + try { + ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); + cookie = ((SerializableCookie) objectInputStream.readObject()).getCookie(); + } catch (IOException e) { + AsyncHttpClient.log.d(LOG_TAG, "IOException in decodeCookie", e); + } catch (ClassNotFoundException e) { + AsyncHttpClient.log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e); + } + + return cookie; + } + + /** + * Using some super basic byte array <-> hex conversions so we don't have to rely on any + * large Base64 libraries. Can be overridden if you like! + * + * @param bytes byte array to be converted + * @return string containing hex values + */ + protected String byteArrayToHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 2); + for (byte element : bytes) { + int v = element & 0xff; + if (v < 16) { + sb.append('0'); + } + sb.append(Integer.toHexString(v)); + } + return sb.toString().toUpperCase(Locale.US); + } + + /** + * Converts hex values from strings to byte arra + * + * @param hexString string of hex-encoded values + * @return decoded byte array + */ + protected byte[] hexStringToByteArray(String hexString) { + int len = hexString.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16)); + } + return data; + } + + + private String getKeySetString(Setkeyset){ + IteratorstringIterator=keyset.iterator(); + StringBuffer stringBuffer=new StringBuffer(); + while (stringIterator.hasNext()){ + stringBuffer.append(stringIterator.next()).append(","); + } + String key=stringBuffer.substring(0,stringBuffer.length()-1); + return key; + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/PreemptiveAuthorizationHttpRequestInterceptor.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/PreemptiveAuthorizationHttpRequestInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..b163aa59ddf8c72f8ae7bbca499f96015b0d7693 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/PreemptiveAuthorizationHttpRequestInterceptor.java @@ -0,0 +1,54 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2014 Marek Sebera + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.HttpException; +import cz.msebera.android.httpclient.HttpHost; +import cz.msebera.android.httpclient.HttpRequest; +import cz.msebera.android.httpclient.HttpRequestInterceptor; +import cz.msebera.android.httpclient.auth.AuthScope; +import cz.msebera.android.httpclient.auth.AuthState; +import cz.msebera.android.httpclient.auth.Credentials; +import cz.msebera.android.httpclient.client.CredentialsProvider; +import cz.msebera.android.httpclient.client.protocol.ClientContext; +import cz.msebera.android.httpclient.impl.auth.BasicScheme; +import cz.msebera.android.httpclient.protocol.ExecutionContext; +import cz.msebera.android.httpclient.protocol.HttpContext; + +import java.io.IOException; + +public class PreemptiveAuthorizationHttpRequestInterceptor implements HttpRequestInterceptor { + + public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException { + AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE); + CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute( + ClientContext.CREDS_PROVIDER); + HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST); + + if (authState.getAuthScheme() == null) { + AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort()); + Credentials creds = credsProvider.getCredentials(authScope); + if (creds != null) { + authState.setAuthScheme(new BasicScheme()); + authState.setCredentials(creds); + } + } + } + +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RangeFileAsyncHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RangeFileAsyncHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..21964c091ceaf509543c6c4accd625b10337dbea --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RangeFileAsyncHttpResponseHandler.java @@ -0,0 +1,105 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2014 Marek Sebera + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.*; +import cz.msebera.android.httpclient.client.HttpResponseException; +import cz.msebera.android.httpclient.client.methods.HttpUriRequest; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + + +public abstract class RangeFileAsyncHttpResponseHandler extends FileAsyncHttpResponseHandler { + private static final String LOG_TAG = "RangeFileAsyncHttpRH"; + + private long current = 0; + private boolean append = false; + + /** + * Obtains new RangeFileAsyncHttpResponseHandler and stores response in passed file + * + * @param file File to store response within, must not be null + */ + public RangeFileAsyncHttpResponseHandler(File file) { + super(file); + } + + @Override + public void sendResponseMessage(HttpResponse response) throws IOException { + if (!Thread.currentThread().isInterrupted()) { + StatusLine status = response.getStatusLine(); + if (status.getStatusCode() == HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE) { + //already finished + if (!Thread.currentThread().isInterrupted()) + sendSuccessMessage(status.getStatusCode(), response.getAllHeaders(), null); + } else if (status.getStatusCode() >= 300) { + if (!Thread.currentThread().isInterrupted()) + sendFailureMessage(status.getStatusCode(), response.getAllHeaders(), null, new HttpResponseException(status.getStatusCode(), status.getReasonPhrase())); + } else { + if (!Thread.currentThread().isInterrupted()) { + Header header = response.getFirstHeader(AsyncHttpClient.HEADER_CONTENT_RANGE); + if (header == null) { + append = false; + current = 0; + } else { + AsyncHttpClient.log.v(LOG_TAG, AsyncHttpClient.HEADER_CONTENT_RANGE + ": " + header.getValue()); + } + sendSuccessMessage(status.getStatusCode(), response.getAllHeaders(), getResponseData(response.getEntity())); + } + } + } + } + + @Override + protected byte[] getResponseData(HttpEntity entity) throws IOException { + if (entity != null) { + InputStream instream = entity.getContent(); + long contentLength = entity.getContentLength() + current; + FileOutputStream buffer = new FileOutputStream(getTargetFile(), append); + if (instream != null) { + try { + byte[] tmp = new byte[BUFFER_SIZE]; + int l; + while (current < contentLength && (l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) { + current += l; + buffer.write(tmp, 0, l); + sendProgressMessage(current, contentLength); + } + } finally { + instream.close(); + buffer.flush(); + buffer.close(); + } + } + } + return null; + } + + public void updateRequestHeaders(HttpUriRequest uriRequest) { + if (file.exists() && file.canWrite()) + current = file.length(); + if (current > 0) { + append = true; + uriRequest.setHeader("Range", "bytes=" + current + "-"); + } + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RequestHandle.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RequestHandle.java new file mode 100644 index 0000000000000000000000000000000000000000..bb714f5b10333fe1116ae02219479805231ad733 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RequestHandle.java @@ -0,0 +1,121 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2013 Jason Choy + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import ohos.eventhandler.EventRunner; + +import java.lang.ref.WeakReference; + +/** + * A Handle to an AsyncRequest which can be used to cancel a running request. + */ +public class RequestHandle { + private final WeakReference request; + + public RequestHandle(AsyncHttpRequest request) { + this.request = new WeakReference(request); + } + + /** + * Attempts to cancel this request. This attempt will fail if the request has already completed, + * has already been cancelled, or could not be cancelled for some other reason. If successful, + * and this request has not started when cancel is called, this request should never run. If the + * request has already started, then the mayInterruptIfRunning parameter determines whether the + * thread executing this request should be interrupted in an attempt to stop the request. + *

 

After this method returns, subsequent calls to isDone() will always return + * true. Subsequent calls to isCancelled() will always return true if this method returned + * true. Subsequent calls to isDone() will return true either if the request got cancelled by + * this method, or if the request completed normally + * + * @param mayInterruptIfRunning true if the thread executing this request should be interrupted; + * otherwise, in-progress requests are allowed to complete + * @return false if the request could not be cancelled, typically because it has already + * completed normally; true otherwise + */ + public boolean cancel(final boolean mayInterruptIfRunning) { + final AsyncHttpRequest _request = request.get(); + if (_request != null) { + if (EventRunner.current() == EventRunner.getMainEventRunner()) { + new Thread(new Runnable() { + @Override + public void run() { + _request.cancel(mayInterruptIfRunning); + } + }).start(); + // Cannot reliably tell if the request got immediately canceled at this point + // we'll assume it got cancelled + return true; + } else { + return _request.cancel(mayInterruptIfRunning); + } + } + return false; + } + + /** + * Returns true if this task completed. Completion may be due to normal termination, an + * exception, or cancellation -- in all of these cases, this method will return true. + * + * @return true if this task completed + */ + public boolean isFinished() { + AsyncHttpRequest _request = request.get(); + return _request == null || _request.isDone(); + } + + /** + * Returns true if this task was cancelled before it completed normally. + * + * @return true if this task was cancelled before it completed + */ + public boolean isCancelled() { + AsyncHttpRequest _request = request.get(); + return _request == null || _request.isCancelled(); + } + + public boolean shouldBeGarbageCollected() { + boolean should = isCancelled() || isFinished(); + if (should) + request.clear(); + return should; + } + + /** + * Will return TAG of underlying AsyncHttpRequest if it's not already GCed + * + * @return Object TAG, can be null + */ + public Object getTag() { + AsyncHttpRequest _request = request.get(); + return _request == null ? null : _request.getTag(); + } + + /** + * Will set Object as TAG to underlying AsyncHttpRequest + * + * @param tag Object used as TAG to underlying AsyncHttpRequest + * @return this RequestHandle to allow fluid syntax + */ + public RequestHandle setTag(Object tag) { + AsyncHttpRequest _request = request.get(); + if (_request != null) + _request.setRequestTag(tag); + return this; + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RequestParams.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RequestParams.java new file mode 100644 index 0000000000000000000000000000000000000000..7f0badcff79cca1dffc38eb50267b8641ebde638 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RequestParams.java @@ -0,0 +1,693 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.HttpEntity; +import cz.msebera.android.httpclient.client.entity.UrlEncodedFormEntity; +import cz.msebera.android.httpclient.client.utils.URLEncodedUtils; +import cz.msebera.android.httpclient.message.BasicNameValuePair; +import cz.msebera.android.httpclient.protocol.HTTP; + +import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentSkipListMap; + +//import java.util.concurrent.ConcurrentSkipList; + +/** + * A collection of string request parameters or files to send along with requests made from an + * {@link AsyncHttpClient} instance.

 

For example:

 

+ *
+ * RequestParams params = new RequestParams();
+ * params.put("username", "james");
+ * params.put("password", "123456");
+ * params.put("email", "my@email.com");
+ * params.put("profile_picture", new File("pic.jpg")); // Upload a File
+ * params.put("profile_picture2", someInputStream); // Upload an InputStream
+ * params.put("profile_picture3", new ByteArrayInputStream(someBytes)); // Upload some bytes
+ *
+ * Map<String, String> map = new HashMap<String, String>();
+ * map.put("first_name", "James");
+ * map.put("last_name", "Smith");
+ * params.put("user", map); // url params: "user[first_name]=James&user[last_name]=Smith"
+ *
+ * Set<String> set = new HashSet<String>(); // unordered collection
+ * set.add("music");
+ * set.add("art");
+ * params.put("like", set); // url params: "like=music&like=art"
+ *
+ * List<String> list = new ArrayList<String>(); // Ordered collection
+ * list.add("Java");
+ * list.add("C");
+ * params.put("languages", list); // url params: "languages[0]=Java&languages[1]=C"
+ *
+ * String[] colors = { "blue", "yellow" }; // Ordered collection
+ * params.put("colors", colors); // url params: "colors[0]=blue&colors[1]=yellow"
+ *
+ * File[] files = { new File("pic.jpg"), new File("pic1.jpg") }; // Ordered collection
+ * params.put("files", files); // url params: "files[]=pic.jpg&files[]=pic1.jpg"
+ *
+ * List<Map<String, String>> listOfMaps = new ArrayList<Map<String,
+ * String>>();
+ * Map<String, String> user1 = new HashMap<String, String>();
+ * user1.put("age", "30");
+ * user1.put("gender", "male");
+ * Map<String, String> user2 = new HashMap<String, String>();
+ * user2.put("age", "25");
+ * user2.put("gender", "female");
+ * listOfMaps.add(user1);
+ * listOfMaps.add(user2);
+ * params.put("users", listOfMaps); // url params: "users[][age]=30&users[][gender]=male&users[][age]=25&users[][gender]=female"
+ *
+ * AsyncHttpClient client = new AsyncHttpClient();
+ * client.post("https://myendpoint.com", params, responseHandler);
+ * 
+ */ +public class RequestParams implements Serializable { + + public final static String APPLICATION_OCTET_STREAM = + "application/octet-stream"; + + public final static String APPLICATION_JSON = + "application/json"; + + protected final static String LOG_TAG = "RequestParams"; + protected final ConcurrentSkipListMap urlParams = new ConcurrentSkipListMap(); + protected final ConcurrentSkipListMap streamParams = new ConcurrentSkipListMap(); + protected final ConcurrentSkipListMap fileParams = new ConcurrentSkipListMap(); + protected final ConcurrentSkipListMap> fileArrayParams = new ConcurrentSkipListMap>(); + protected final ConcurrentSkipListMap urlParamsWithObjects = new ConcurrentSkipListMap(); + protected boolean isRepeatable; + protected boolean forceMultipartEntity = false; + protected boolean useJsonStreamer; + protected String elapsedFieldInJsonStreamer = "_elapsed"; + protected boolean autoCloseInputStreams; + protected String contentEncoding = HTTP.UTF_8; + + /** + * Constructs a new empty {@code RequestParams} instance. + */ + public RequestParams() { + this((Map) null); + } + + /** + * Constructs a new RequestParams instance containing the key/value string params from the + * specified map. + * + * @param source the source key/value string map to add. + */ + public RequestParams(Map source) { + if (source != null) { + for (Map.Entry entry : source.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + } + + /** + * Constructs a new RequestParams instance and populate it with a single initial key/value + * string param. + * + * @param key the key name for the intial param. + * @param value the value string for the initial param. + */ + public RequestParams(final String key, final String value) { + this(new HashMap() {{ + put(key, value); + }}); + } + + /** + * Constructs a new RequestParams instance and populate it with multiple initial key/value + * string param. + * + * @param keysAndValues a sequence of keys and values. Objects are automatically converted to + * Strings (including the value {@code null}). + * @throws IllegalArgumentException if the number of arguments isn't even. + */ + public RequestParams(Object... keysAndValues) { + int len = keysAndValues.length; + if (len % 2 != 0) + throw new IllegalArgumentException("Supplied arguments must be even"); + for (int i = 0; i < len; i += 2) { + String key = String.valueOf(keysAndValues[i]); + String val = String.valueOf(keysAndValues[i + 1]); + put(key, val); + } + } + + /** + * Sets content encoding for return value of {@link #getParamString()} and {@link + * #createFormEntity()}

 

Default encoding is "UTF-8" + * + * @param encoding String constant from {@link HTTP} + */ + public void setContentEncoding(final String encoding) { + if (encoding != null) { + this.contentEncoding = encoding; + } else { + AsyncHttpClient.log.d(LOG_TAG, "setContentEncoding called with null attribute"); + } + } + + /** + * If set to true will force Content-Type header to `multipart/form-data` + * even if there are not Files or Streams to be send + *

 

+ * Default value is false + * + * @param force boolean, should declare content-type multipart/form-data even without files or streams present + */ + public void setForceMultipartEntityContentType(boolean force) { + this.forceMultipartEntity = force; + } + + /** + * Adds a key/value string pair to the request. + * + * @param key the key name for the new param. + * @param value the value string for the new param. + */ + public void put(String key, String value) { + if (key != null && value != null) { + urlParams.put(key, value); + } + } + + /** + * Adds files array to the request. + * + * @param key the key name for the new param. + * @param files the files array to add. + * @throws FileNotFoundException if one of passed files is not found at time of assembling the requestparams into request + */ + public void put(String key, File files[]) throws FileNotFoundException { + put(key, files, null, null); + } + + /** + * Adds files array to the request with both custom provided file content-type and files name + * + * @param key the key name for the new param. + * @param files the files array to add. + * @param contentType the content type of the file, eg. application/json + * @param customFileName file name to use instead of real file name + * @throws FileNotFoundException throws if wrong File argument was passed + */ + public void put(String key, File files[], String contentType, String customFileName) throws FileNotFoundException { + + if (key != null) { + List fileWrappers = new ArrayList(); + for (File file : files) { + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + fileWrappers.add(new FileWrapper(file, contentType, customFileName)); + } + fileArrayParams.put(key, fileWrappers); + } + } + + /** + * Adds a file to the request. + * + * @param key the key name for the new param. + * @param file the file to add. + * @throws FileNotFoundException throws if wrong File argument was passed + */ + public void put(String key, File file) throws FileNotFoundException { + put(key, file, null, null); + } + + /** + * Adds a file to the request with custom provided file name + * + * @param key the key name for the new param. + * @param file the file to add. + * @param customFileName file name to use instead of real file name + * @throws FileNotFoundException throws if wrong File argument was passed + */ + public void put(String key, String customFileName, File file) throws FileNotFoundException { + put(key, file, null, customFileName); + } + + /** + * Adds a file to the request with custom provided file content-type + * + * @param key the key name for the new param. + * @param file the file to add. + * @param contentType the content type of the file, eg. application/json + * @throws FileNotFoundException throws if wrong File argument was passed + */ + public void put(String key, File file, String contentType) throws FileNotFoundException { + put(key, file, contentType, null); + } + + /** + * Adds a file to the request with both custom provided file content-type and file name + * + * @param key the key name for the new param. + * @param file the file to add. + * @param contentType the content type of the file, eg. application/json + * @param customFileName file name to use instead of real file name + * @throws FileNotFoundException throws if wrong File argument was passed + */ + public void put(String key, File file, String contentType, String customFileName) throws FileNotFoundException { + if (file == null || !file.exists()) { + throw new FileNotFoundException(); + } + if (key != null) { + fileParams.put(key, new FileWrapper(file, contentType, customFileName)); + } + } + + /** + * Adds an input stream to the request. + * + * @param key the key name for the new param. + * @param stream the input stream to add. + */ + public void put(String key, InputStream stream) { + put(key, stream, null); + } + + /** + * Adds an input stream to the request. + * + * @param key the key name for the new param. + * @param stream the input stream to add. + * @param name the name of the stream. + */ + public void put(String key, InputStream stream, String name) { + put(key, stream, name, null); + } + + /** + * Adds an input stream to the request. + * + * @param key the key name for the new param. + * @param stream the input stream to add. + * @param name the name of the stream. + * @param contentType the content type of the file, eg. application/json + */ + public void put(String key, InputStream stream, String name, String contentType) { + put(key, stream, name, contentType, autoCloseInputStreams); + } + + /** + * Adds an input stream to the request. + * + * @param key the key name for the new param. + * @param stream the input stream to add. + * @param name the name of the stream. + * @param contentType the content type of the file, eg. application/json + * @param autoClose close input stream automatically on successful upload + */ + public void put(String key, InputStream stream, String name, String contentType, boolean autoClose) { + if (key != null && stream != null) { + streamParams.put(key, StreamWrapper.newInstance(stream, name, contentType, autoClose)); + } + } + + /** + * Adds param with non-string value (e.g. Map, List, Set). + * + * @param key the key name for the new param. + * @param value the non-string value object for the new param. + */ + public void put(String key, Object value) { + if (key != null && value != null) { + urlParamsWithObjects.put(key, value); + } + } + + /** + * Adds a int value to the request. + * + * @param key the key name for the new param. + * @param value the value int for the new param. + */ + public void put(String key, int value) { + if (key != null) { + urlParams.put(key, String.valueOf(value)); + } + } + + /** + * Adds a long value to the request. + * + * @param key the key name for the new param. + * @param value the value long for the new param. + */ + public void put(String key, long value) { + if (key != null) { + urlParams.put(key, String.valueOf(value)); + } + } + + /** + * Adds string value to param which can have more than one value. + * + * @param key the key name for the param, either existing or new. + * @param value the value string for the new param. + */ + public void add(String key, String value) { + if (key != null && value != null) { + Object params = urlParamsWithObjects.get(key); + if (params == null) { + // Backward compatible, which will result in "k=v1&k=v2&k=v3" + params = new HashSet(); + this.put(key, params); + } + if (params instanceof List) { + ((List) params).add(value); + } else if (params instanceof Set) { + ((Set) params).add(value); + } + } + } + + /** + * Removes a parameter from the request. + * + * @param key the key name for the parameter to remove. + */ + public void remove(String key) { + urlParams.remove(key); + streamParams.remove(key); + fileParams.remove(key); + urlParamsWithObjects.remove(key); + fileArrayParams.remove(key); + } + + /** + * Check if a parameter is defined. + * + * @param key the key name for the parameter to check existence. + * @return Boolean + */ + public boolean has(String key) { + return urlParams.get(key) != null || + streamParams.get(key) != null || + fileParams.get(key) != null || + urlParamsWithObjects.get(key) != null || + fileArrayParams.get(key) != null; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for (ConcurrentSkipListMap.Entry entry : urlParams.entrySet()) { + if (result.length() > 0) + result.append("&"); + + result.append(entry.getKey()); + result.append("="); + result.append(entry.getValue()); + } + + for (ConcurrentSkipListMap.Entry entry : streamParams.entrySet()) { + if (result.length() > 0) + result.append("&"); + + result.append(entry.getKey()); + result.append("="); + result.append("STREAM"); + } + + for (ConcurrentSkipListMap.Entry entry : fileParams.entrySet()) { + if (result.length() > 0) + result.append("&"); + + result.append(entry.getKey()); + result.append("="); + result.append("FILE"); + } + + for (ConcurrentSkipListMap.Entry> entry : fileArrayParams.entrySet()) { + if (result.length() > 0) + result.append("&"); + + result.append(entry.getKey()); + result.append("="); + result.append("FILES(SIZE=").append(entry.getValue().size()).append(")"); + } + + List params = getParamsList(null, urlParamsWithObjects); + for (BasicNameValuePair kv : params) { + if (result.length() > 0) + result.append("&"); + + result.append(kv.getName()); + result.append("="); + result.append(kv.getValue()); + } + + return result.toString(); + } + + public void setHttpEntityIsRepeatable(boolean flag) { + this.isRepeatable = flag; + } + + public void setUseJsonStreamer(boolean flag) { + this.useJsonStreamer = flag; + } + + /** + * Sets an additional field when upload a JSON object through the streamer + * to hold the time, in milliseconds, it took to upload the payload. By + * default, this field is set to "_elapsed". + *

 

+ * To disable this feature, call this method with null as the field value. + * + * @param value field name to add elapsed time, or null to disable + */ + public void setElapsedFieldInJsonStreamer(String value) { + this.elapsedFieldInJsonStreamer = value; + } + + /** + * Set global flag which determines whether to automatically close input streams on successful + * upload. + * + * @param flag boolean whether to automatically close input streams + */ + public void setAutoCloseInputStreams(boolean flag) { + autoCloseInputStreams = flag; + } + + /** + * Returns an HttpEntity containing all request parameters. + * + * @param progressHandler HttpResponseHandler for reporting progress on entity submit + * @return HttpEntity resulting HttpEntity to be included along with {@link + * cz.msebera.android.httpclient.client.methods.HttpEntityEnclosingRequestBase} + * @throws IOException if one of the streams cannot be read + */ + public HttpEntity getEntity(ResponseHandlerInterface progressHandler) throws IOException { + if (useJsonStreamer) { + return createJsonStreamerEntity(progressHandler); + } else if (!forceMultipartEntity && streamParams.isEmpty() && fileParams.isEmpty() && fileArrayParams.isEmpty()) { + return createFormEntity(); + } else { + return createMultipartEntity(progressHandler); + } + } + + private HttpEntity createJsonStreamerEntity(ResponseHandlerInterface progressHandler) throws IOException { + JsonStreamerEntity entity = new JsonStreamerEntity( + progressHandler, + !fileParams.isEmpty() || !streamParams.isEmpty(), + elapsedFieldInJsonStreamer); + + // Add string params + for (ConcurrentSkipListMap.Entry entry : urlParams.entrySet()) { + entity.addPart(entry.getKey(), entry.getValue()); + } + + // Add non-string params + for (ConcurrentSkipListMap.Entry entry : urlParamsWithObjects.entrySet()) { + entity.addPart(entry.getKey(), entry.getValue()); + } + + // Add file params + for (ConcurrentSkipListMap.Entry entry : fileParams.entrySet()) { + entity.addPart(entry.getKey(), entry.getValue()); + } + + // Add stream params + for (ConcurrentSkipListMap.Entry entry : streamParams.entrySet()) { + StreamWrapper stream = entry.getValue(); + if (stream.inputStream != null) { + entity.addPart(entry.getKey(), + StreamWrapper.newInstance( + stream.inputStream, + stream.name, + stream.contentType, + stream.autoClose) + ); + } + } + + return entity; + } + + private HttpEntity createFormEntity() { + try { + return new UrlEncodedFormEntity(getParamsList(), contentEncoding); + } catch (UnsupportedEncodingException e) { + AsyncHttpClient.log.e(LOG_TAG, "createFormEntity failed", e); + return null; // Can happen, if the 'contentEncoding' won't be HTTP.UTF_8 + } + } + + private HttpEntity createMultipartEntity(ResponseHandlerInterface progressHandler) throws IOException { + SimpleMultipartEntity entity = new SimpleMultipartEntity(progressHandler); + entity.setIsRepeatable(isRepeatable); + + // Add string params + for (ConcurrentSkipListMap.Entry entry : urlParams.entrySet()) { + entity.addPartWithCharset(entry.getKey(), entry.getValue(), contentEncoding); + } + + // Add non-string params + List params = getParamsList(null, urlParamsWithObjects); + for (BasicNameValuePair kv : params) { + entity.addPartWithCharset(kv.getName(), kv.getValue(), contentEncoding); + } + + // Add stream params + for (ConcurrentSkipListMap.Entry entry : streamParams.entrySet()) { + StreamWrapper stream = entry.getValue(); + if (stream.inputStream != null) { + entity.addPart(entry.getKey(), stream.name, stream.inputStream, + stream.contentType); + } + } + + // Add file params + for (ConcurrentSkipListMap.Entry entry : fileParams.entrySet()) { + FileWrapper fileWrapper = entry.getValue(); + entity.addPart(entry.getKey(), fileWrapper.file, fileWrapper.contentType, fileWrapper.customFileName); + } + + // Add file collection + for (ConcurrentSkipListMap.Entry> entry : fileArrayParams.entrySet()) { + List fileWrapper = entry.getValue(); + for (FileWrapper fw : fileWrapper) { + entity.addPart(entry.getKey(), fw.file, fw.contentType, fw.customFileName); + } + } + + return entity; + } + + protected List getParamsList() { + List lparams = new LinkedList(); + + for (ConcurrentSkipListMap.Entry entry : urlParams.entrySet()) { + lparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + + lparams.addAll(getParamsList(null, urlParamsWithObjects)); + + return lparams; + } + + private List getParamsList(String key, Object value) { + List params = new LinkedList(); + if (value instanceof Map) { + Map map = (Map) value; + List list = new ArrayList(map.keySet()); + // Ensure consistent ordering in query string + if (list.size() > 0 && list.get(0) instanceof Comparable) { + Collections.sort(list); + } + for (Object nestedKey : list) { + if (nestedKey instanceof String) { + Object nestedValue = map.get(nestedKey); + if (nestedValue != null) { + params.addAll(getParamsList(key == null ? (String) nestedKey : String.format(Locale.US, "%s[%s]", key, nestedKey), + nestedValue)); + } + } + } + } else if (value instanceof List) { + List list = (List) value; + int listSize = list.size(); + for (int nestedValueIndex = 0; nestedValueIndex < listSize; nestedValueIndex++) { + params.addAll(getParamsList(String.format(Locale.US, "%s[%d]", key, nestedValueIndex), list.get(nestedValueIndex))); + } + } else if (value instanceof Object[]) { + Object[] array = (Object[]) value; + int arrayLength = array.length; + for (int nestedValueIndex = 0; nestedValueIndex < arrayLength; nestedValueIndex++) { + params.addAll(getParamsList(String.format(Locale.US, "%s[%d]", key, nestedValueIndex), array[nestedValueIndex])); + } + } else if (value instanceof Set) { + Set set = (Set) value; + for (Object nestedValue : set) { + params.addAll(getParamsList(key, nestedValue)); + } + } else { + params.add(new BasicNameValuePair(key, value.toString())); + } + return params; + } + + protected String getParamString() { + return URLEncodedUtils.format(getParamsList(), contentEncoding); + } + + public static class FileWrapper implements Serializable { + public final File file; + public final String contentType; + public final String customFileName; + + public FileWrapper(File file, String contentType, String customFileName) { + this.file = file; + this.contentType = contentType; + this.customFileName = customFileName; + } + } + + public static class StreamWrapper { + public final InputStream inputStream; + public final String name; + public final String contentType; + public final boolean autoClose; + + public StreamWrapper(InputStream inputStream, String name, String contentType, boolean autoClose) { + this.inputStream = inputStream; + this.name = name; + this.contentType = contentType; + this.autoClose = autoClose; + } + + static StreamWrapper newInstance(InputStream inputStream, String name, String contentType, boolean autoClose) { + return new StreamWrapper( + inputStream, + name, + contentType == null ? APPLICATION_OCTET_STREAM : contentType, + autoClose); + } + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/ResponseHandlerInterface.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/ResponseHandlerInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..820906ff7d58d320e59467c50fdb327a17543537 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/ResponseHandlerInterface.java @@ -0,0 +1,189 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2013 Marek Sebera + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpResponse; + +import java.io.IOException; +import java.net.URI; + +/** + * Interface to standardize implementations + */ +public interface ResponseHandlerInterface { + + /** + * Returns data whether request completed successfully + * + * @param response HttpResponse object with data + * @throws IOException if retrieving data from response fails + */ + void sendResponseMessage(HttpResponse response) throws IOException; + + /** + * Notifies callback, that request started execution + */ + void sendStartMessage(); + + /** + * Notifies callback, that request was completed and is being removed from thread pool + */ + void sendFinishMessage(); + + /** + * Notifies callback, that request (mainly uploading) has progressed + * + * @param bytesWritten number of written bytes + * @param bytesTotal number of total bytes to be written + */ + void sendProgressMessage(long bytesWritten, long bytesTotal); + + /** + * Notifies callback, that request was cancelled + */ + void sendCancelMessage(); + + /** + * Notifies callback, that request was handled successfully + * + * @param statusCode HTTP status code + * @param headers returned headers + * @param responseBody returned data + */ + void sendSuccessMessage(int statusCode, Header[] headers, byte[] responseBody); + + /** + * Returns if request was completed with error code or failure of implementation + * + * @param statusCode returned HTTP status code + * @param headers returned headers + * @param responseBody returned data + * @param error cause of request failure + */ + void sendFailureMessage(int statusCode, Header[] headers, byte[] responseBody, Throwable error); + + /** + * Notifies callback of retrying request + * + * @param retryNo number of retry within one request + */ + void sendRetryMessage(int retryNo); + + /** + * Returns URI which was used to request + * + * @return uri of origin request + */ + URI getRequestURI(); + + /** + * Helper for handlers to receive Request URI info + * + * @param requestURI claimed request URI + */ + void setRequestURI(URI requestURI); + + /** + * Returns Header[] which were used to request + * + * @return headers from origin request + */ + Header[] getRequestHeaders(); + + /** + * Helper for handlers to receive Request Header[] info + * + * @param requestHeaders Headers, claimed to be from original request + */ + void setRequestHeaders(Header[] requestHeaders); + + /** + * Returns whether the handler is asynchronous or synchronous + * + * @return boolean if the ResponseHandler is running in synchronous mode + */ + boolean getUseSynchronousMode(); + + /** + * Can set, whether the handler should be asynchronous or synchronous + * + * @param useSynchronousMode whether data should be handled on background Thread on UI Thread + */ + void setUseSynchronousMode(boolean useSynchronousMode); + + /** + * Returns whether the handler should be executed on the pool's thread + * or the UI thread + * + * @return boolean if the ResponseHandler should run on pool's thread + */ + boolean getUsePoolThread(); + + /** + * Sets whether the handler should be executed on the pool's thread or the + * UI thread + * + * @param usePoolThread if the ResponseHandler should run on pool's thread + */ + void setUsePoolThread(boolean usePoolThread); + + /** + * This method is called once by the system when the response is about to be + * processed by the system. The library makes sure that a single response + * is pre-processed only once. + *

 

+ * Please note: pre-processing does NOT run on the main thread, and thus + * any UI activities that you must perform should be properly dispatched to + * the app's UI thread. + * + * @param instance An instance of this response object + * @param response The response to pre-processed + */ + void onPreProcessResponse(ResponseHandlerInterface instance, HttpResponse response); + + /** + * This method is called once by the system when the request has been fully + * sent, handled and finished. The library makes sure that a single response + * is post-processed only once. + *

 

+ * Please note: post-processing does NOT run on the main thread, and thus + * any UI activities that you must perform should be properly dispatched to + * the app's UI thread. + * + * @param instance An instance of this response object + * @param response The response to post-process + */ + void onPostProcessResponse(ResponseHandlerInterface instance, HttpResponse response); + + /** + * Will retrieve TAG Object if it's not already freed from memory + * + * @return Object TAG or null if it's been garbage collected + */ + Object getTag(); + + /** + * Will set TAG to ResponseHandlerInterface implementation, which can be then obtained + * in implemented methods, such as onSuccess, onFailure, ... + * + * @param TAG Object to be set as TAG, will be placed in WeakReference + */ + void setTag(Object TAG); +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RetryHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RetryHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..d6649464fa31ccb55d03bc556613a1c0812f7e25 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/RetryHandler.java @@ -0,0 +1,122 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + Some of the retry logic in this class is heavily borrowed from the + fantastic droid-fu project: https://github.com/donnfelker/droid-fu +*/ + +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.NoHttpResponseException; +import cz.msebera.android.httpclient.client.HttpRequestRetryHandler; +import cz.msebera.android.httpclient.client.methods.HttpUriRequest; +import cz.msebera.android.httpclient.protocol.ExecutionContext; +import cz.msebera.android.httpclient.protocol.HttpContext; +import ohos.miscservices.timeutility.Time; + +import javax.net.ssl.SSLException; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.HashSet; + +class RetryHandler implements HttpRequestRetryHandler { + private final static HashSet> exceptionWhitelist = new HashSet>(); + private final static HashSet> exceptionBlacklist = new HashSet>(); + + static { + // Retry if the server dropped connection on us + exceptionWhitelist.add(NoHttpResponseException.class); + // retry-this, since it may happens as part of a Wi-Fi to 3G failover + exceptionWhitelist.add(UnknownHostException.class); + // retry-this, since it may happens as part of a Wi-Fi to 3G failover + exceptionWhitelist.add(SocketException.class); + + // never retry timeouts + exceptionBlacklist.add(InterruptedIOException.class); + // never retry SSL handshake failures + exceptionBlacklist.add(SSLException.class); + } + + private final int maxRetries; + private final int retrySleepTimeMS; + + public RetryHandler(int maxRetries, int retrySleepTimeMS) { + this.maxRetries = maxRetries; + this.retrySleepTimeMS = retrySleepTimeMS; + } + + static void addClassToWhitelist(Class cls) { + exceptionWhitelist.add(cls); + } + + static void addClassToBlacklist(Class cls) { + exceptionBlacklist.add(cls); + } + + @Override + public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { + boolean retry = true; + + Boolean b = (Boolean) context.getAttribute(ExecutionContext.HTTP_REQ_SENT); + boolean sent = (b != null && b); + + if (executionCount > maxRetries) { + // Do not retry if over max retry count + retry = false; + } else if (isInList(exceptionWhitelist, exception)) { + // immediately retry if error is whitelisted + retry = true; + } else if (isInList(exceptionBlacklist, exception)) { + // immediately cancel retry if the error is blacklisted + retry = false; + } else if (!sent) { + // for most other errors, retry only if request hasn't been fully sent yet + retry = true; + } + + if (retry) { + // resend all idempotent requests + HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST); + if (currentReq == null) { + return false; + } + } + + if (retry) { + Time.sleep(retrySleepTimeMS); +// SystemClock.sleep(retrySleepTimeMS); + } else { + exception.printStackTrace(); + } + + return retry; + } + + protected boolean isInList(HashSet> list, Throwable error) { + for (Class aList : list) { + if (aList.isInstance(error)) { + return true; + } + } + return false; + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SerializableCookie.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SerializableCookie.java new file mode 100644 index 0000000000000000000000000000000000000000..ef2013f3bf816c61807af91ba1a4ba1aff48f837 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SerializableCookie.java @@ -0,0 +1,74 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.cookie.Cookie; +import cz.msebera.android.httpclient.impl.cookie.BasicClientCookie; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Date; + +/** + * A wrapper class around {@link Cookie} and/or {@link BasicClientCookie} designed for use in {@link + * PersistentCookieStore}. + */ +public class SerializableCookie implements Serializable { + private static final long serialVersionUID = 6374381828722046732L; + + private transient final Cookie cookie; + private transient BasicClientCookie clientCookie; + + public SerializableCookie(Cookie cookie) { + this.cookie = cookie; + } + + public Cookie getCookie() { + Cookie bestCookie = cookie; + if (clientCookie != null) { + bestCookie = clientCookie; + } + return bestCookie; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.writeObject(cookie.getName()); + out.writeObject(cookie.getValue()); + out.writeObject(cookie.getComment()); + out.writeObject(cookie.getDomain()); + out.writeObject(cookie.getExpiryDate()); + out.writeObject(cookie.getPath()); + out.writeInt(cookie.getVersion()); + out.writeBoolean(cookie.isSecure()); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + String key = (String) in.readObject(); + String value = (String) in.readObject(); + clientCookie = new BasicClientCookie(key, value); + clientCookie.setComment((String) in.readObject()); + clientCookie.setDomain((String) in.readObject()); + clientCookie.setExpiryDate((Date) in.readObject()); + clientCookie.setPath((String) in.readObject()); + clientCookie.setVersion(in.readInt()); + clientCookie.setSecure(in.readBoolean()); + } +} \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SimpleMultipartEntity.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SimpleMultipartEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..89e3481ff0df283ef5e7fa563ec4e4bad94cd6d6 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SimpleMultipartEntity.java @@ -0,0 +1,291 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + This code is taken from Rafael Sanches' blog. Link is no longer working (as of 17th July 2015) + https://blog.rafaelsanches.com/2011/01/29/upload-using-multipart-post-using-httpclient-in-android/ +*/ + +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.Header; +import cz.msebera.android.httpclient.HttpEntity; +import cz.msebera.android.httpclient.message.BasicHeader; +import cz.msebera.android.httpclient.protocol.HTTP; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Simplified multipart entity mainly used for sending one or more files. + */ +class SimpleMultipartEntity implements HttpEntity { + + private static final String LOG_TAG = "SimpleMultipartEntity"; + + private static final String STR_CR_LF = "\r\n"; + private static final byte[] CR_LF = STR_CR_LF.getBytes(); + private static final byte[] TRANSFER_ENCODING_BINARY = + ("Content-Transfer-Encoding: binary" + STR_CR_LF).getBytes(); + + private final static char[] MULTIPART_CHARS = + "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + + private final String boundary; + private final byte[] boundaryLine; + private final byte[] boundaryEnd; + private final List fileParts = new ArrayList(); + // The buffer we use for building the message excluding files and the last + // boundary + private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + private final ResponseHandlerInterface progressHandler; + private boolean isRepeatable; + private long bytesWritten; + + private long totalSize; + + public SimpleMultipartEntity(ResponseHandlerInterface progressHandler) { + final StringBuilder buf = new StringBuilder(); + final Random rand = new Random(); + for (int i = 0; i < 30; i++) { + buf.append(MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)]); + } + + boundary = buf.toString(); + boundaryLine = ("--" + boundary + STR_CR_LF).getBytes(); + boundaryEnd = ("--" + boundary + "--" + STR_CR_LF).getBytes(); + + this.progressHandler = progressHandler; + } + + public void addPart(String key, String value, String contentType) { + try { + out.write(boundaryLine); + out.write(createContentDisposition(key)); + out.write(createContentType(contentType)); + out.write(CR_LF); + out.write(value.getBytes()); + out.write(CR_LF); + } catch (final IOException e) { + // Shall not happen on ByteArrayOutputStream + AsyncHttpClient.log.e(LOG_TAG, "addPart ByteArrayOutputStream exception", e); + } + } + + public void addPartWithCharset(String key, String value, String charset) { + if (charset == null) charset = HTTP.UTF_8; + addPart(key, value, "text/plain; charset=" + charset); + } + + public void addPart(String key, String value) { + addPartWithCharset(key, value, null); + } + + public void addPart(String key, File file) { + addPart(key, file, null); + } + + public void addPart(String key, File file, String type) { + fileParts.add(new FilePart(key, file, normalizeContentType(type))); + } + + public void addPart(String key, File file, String type, String customFileName) { + fileParts.add(new FilePart(key, file, normalizeContentType(type), customFileName)); + } + + public void addPart(String key, String streamName, InputStream inputStream, String type) + throws IOException { + + out.write(boundaryLine); + + // Headers + out.write(createContentDisposition(key, streamName)); + out.write(createContentType(type)); + out.write(TRANSFER_ENCODING_BINARY); + out.write(CR_LF); + + // Stream (file) + final byte[] tmp = new byte[4096]; + int l; + while ((l = inputStream.read(tmp)) != -1) { + out.write(tmp, 0, l); + } + + out.write(CR_LF); + out.flush(); + } + + private String normalizeContentType(String type) { + return type == null ? RequestParams.APPLICATION_OCTET_STREAM : type; + } + + private byte[] createContentType(String type) { + String result = AsyncHttpClient.HEADER_CONTENT_TYPE + ": " + normalizeContentType(type) + STR_CR_LF; + return result.getBytes(); + } + + private byte[] createContentDisposition(String key) { + return ( + AsyncHttpClient.HEADER_CONTENT_DISPOSITION + + ": form-data; name=\"" + key + "\"" + STR_CR_LF).getBytes(); + } + + private byte[] createContentDisposition(String key, String fileName) { + return ( + AsyncHttpClient.HEADER_CONTENT_DISPOSITION + + ": form-data; name=\"" + key + "\"" + + "; filename=\"" + fileName + "\"" + STR_CR_LF).getBytes(); + } + + private void updateProgress(long count) { + bytesWritten += count; + progressHandler.sendProgressMessage(bytesWritten, totalSize); + } + + @Override + public long getContentLength() { + long contentLen = out.size(); + for (FilePart filePart : fileParts) { + long len = filePart.getTotalLength(); + if (len < 0) { + return -1; // Should normally not happen + } + contentLen += len; + } + contentLen += boundaryEnd.length; + return contentLen; + } + + // The following methods are from the HttpEntity interface + + @Override + public Header getContentType() { + return new BasicHeader( + AsyncHttpClient.HEADER_CONTENT_TYPE, + "multipart/form-data; boundary=" + boundary); + } + + @Override + public boolean isChunked() { + return false; + } + + public void setIsRepeatable(boolean isRepeatable) { + this.isRepeatable = isRepeatable; + } + + @Override + public boolean isRepeatable() { + return isRepeatable; + } + + @Override + public boolean isStreaming() { + return false; + } + + @Override + public void writeTo(final OutputStream outstream) throws IOException { + bytesWritten = 0; + totalSize = (int) getContentLength(); + out.writeTo(outstream); + updateProgress(out.size()); + + for (FilePart filePart : fileParts) { + filePart.writeTo(outstream); + } + outstream.write(boundaryEnd); + updateProgress(boundaryEnd.length); + } + + @Override + public Header getContentEncoding() { + return null; + } + + @Override + public void consumeContent() throws IOException, UnsupportedOperationException { + if (isStreaming()) { + throw new UnsupportedOperationException( + "Streaming entity does not implement #consumeContent()"); + } + } + + @Override + public InputStream getContent() throws IOException, UnsupportedOperationException { + throw new UnsupportedOperationException( + "getContent() is not supported. Use writeTo() instead."); + } + + private class FilePart { + public final File file; + public final byte[] header; + + public FilePart(String key, File file, String type, String customFileName) { + header = createHeader(key, customFileName.isEmpty() ? file.getName() : customFileName, type); + this.file = file; + } + + public FilePart(String key, File file, String type) { + header = createHeader(key, file.getName(), type); + this.file = file; + } + + private byte[] createHeader(String key, String filename, String type) { + ByteArrayOutputStream headerStream = new ByteArrayOutputStream(); + try { + headerStream.write(boundaryLine); + + // Headers + headerStream.write(createContentDisposition(key, filename)); + headerStream.write(createContentType(type)); + headerStream.write(TRANSFER_ENCODING_BINARY); + headerStream.write(CR_LF); + } catch (IOException e) { + // Can't happen on ByteArrayOutputStream + AsyncHttpClient.log.e(LOG_TAG, "createHeader ByteArrayOutputStream exception", e); + } + return headerStream.toByteArray(); + } + + public long getTotalLength() { + long streamLength = file.length() + CR_LF.length; + return header.length + streamLength; + } + + public void writeTo(OutputStream out) throws IOException { + out.write(header); + updateProgress(header.length); + + FileInputStream inputStream = new FileInputStream(file); + final byte[] tmp = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(tmp)) != -1) { + out.write(tmp, 0, bytesRead); + updateProgress(bytesRead); + } + out.write(CR_LF); + updateProgress(CR_LF.length); + out.flush(); + AsyncHttpClient.silentCloseInputStream(inputStream); + } + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SyncHttpClient.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SyncHttpClient.java new file mode 100644 index 0000000000000000000000000000000000000000..115139cee6215b96eea2ee859a9936b9c7a8bc54 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/SyncHttpClient.java @@ -0,0 +1,100 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.example.httplibrary.utils; + + +import cz.msebera.android.httpclient.client.methods.HttpUriRequest; +import cz.msebera.android.httpclient.conn.scheme.SchemeRegistry; +import cz.msebera.android.httpclient.impl.client.DefaultHttpClient; +import cz.msebera.android.httpclient.protocol.HttpContext; +import ohos.app.Context; + +/** + * Processes http requests in synchronous mode, so your caller thread will be blocked on each + * request + * + */ +public class SyncHttpClient extends AsyncHttpClient { + + /** + * Creates a new SyncHttpClient with default constructor arguments values + */ + public SyncHttpClient() { + super(false, 80, 443); + } + + /** + * Creates a new SyncHttpClient. + * + * @param httpPort non-standard HTTP-only port + */ + public SyncHttpClient(int httpPort) { + super(false, httpPort, 443); + } + + /** + * Creates a new SyncHttpClient. + * + * @param httpPort non-standard HTTP-only port + * @param httpsPort non-standard HTTPS-only port + */ + public SyncHttpClient(int httpPort, int httpsPort) { + super(false, httpPort, httpsPort); + } + + /** + * Creates new SyncHttpClient using given params + * + * @param fixNoHttpResponseException Whether to fix or not issue, by ommiting SSL verification + * @param httpPort HTTP port to be used, must be greater than 0 + * @param httpsPort HTTPS port to be used, must be greater than 0 + */ + public SyncHttpClient(boolean fixNoHttpResponseException, int httpPort, int httpsPort) { + super(fixNoHttpResponseException, httpPort, httpsPort); + } + + /** + * Creates a new SyncHttpClient. + * + * @param schemeRegistry SchemeRegistry to be used + */ + public SyncHttpClient(SchemeRegistry schemeRegistry) { + super(schemeRegistry); + } + + @Override + protected RequestHandle sendRequest(DefaultHttpClient client, + HttpContext httpContext, HttpUriRequest uriRequest, + String contentType, ResponseHandlerInterface responseHandler, + Context context) { + if (contentType != null) { + uriRequest.addHeader(AsyncHttpClient.HEADER_CONTENT_TYPE, contentType); + } + + responseHandler.setUseSynchronousMode(true); + + /* + * will execute the request directly + */ + newAsyncHttpRequest(client, httpContext, uriRequest, contentType, responseHandler, context).run(); + + // Return a Request Handle that cannot be used to cancel the request + // because it is already complete by the time this returns + return new RequestHandle(null); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/TextHttpResponseHandler.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/TextHttpResponseHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..b2e1be73b01f1a0842765f3b9da3376227e2bcea --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/TextHttpResponseHandler.java @@ -0,0 +1,125 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.Header; + +import java.io.UnsupportedEncodingException; + +/** + * Used to intercept and handle the responses from requests made using {@link AsyncHttpClient}. The + * {@link #onSuccess(int, Header[], String)} method is designed to be anonymously + * overridden with your own response handling code.

 

Additionally, you can override the + * {@link #onFailure(int, Header[], String, Throwable)}, {@link #onStart()}, and + * {@link #onFinish()} methods as required.

 

For example:

 

+ *
+ * AsyncHttpClient client = new AsyncHttpClient();
+ * client.get("https://www.google.com", new TextHttpResponseHandler() {
+ *     @Override
+ *     public void onStart() {
+ *         // Initiated the request
+ *     }
+ *
+ *     @Override
+ *     public void onSuccess(String responseBody) {
+ *         // Successfully got a response
+ *     }
+ *
+ *     @Override
+ *     public void onFailure(String responseBody, Throwable e) {
+ *         // Response failed :(
+ *     }
+ *
+ *     @Override
+ *     public void onFinish() {
+ *         // Completed the request (either success or failure)
+ *     }
+ * });
+ * 
+ */ +public abstract class TextHttpResponseHandler extends AsyncHttpResponseHandler { + + private static final String LOG_TAG = "TextHttpRH"; + + /** + * Creates new instance with default UTF-8 encoding + */ + public TextHttpResponseHandler() { + this(DEFAULT_CHARSET); + } + + /** + * Creates new instance with given string encoding + * + * @param encoding String encoding, see {@link #setCharset(String)} + */ + public TextHttpResponseHandler(String encoding) { + super(); + setCharset(encoding); + } + + /** + * Attempts to encode response bytes as string of set encoding + * + * @param charset charset to create string with + * @param stringBytes response bytes + * @return String of set encoding or null + */ + public static String getResponseString(byte[] stringBytes, String charset) { + try { + String toReturn = (stringBytes == null) ? null : new String(stringBytes, charset); + if (toReturn != null && toReturn.startsWith(UTF8_BOM)) { + return toReturn.substring(1); + } + return toReturn; + } catch (UnsupportedEncodingException e) { + AsyncHttpClient.log.e(LOG_TAG, "Encoding response into string failed", e); + return null; + } + } + + /** + * Called when request fails + * + * @param statusCode http response status line + * @param headers response headers if any + * @param responseString string response of given charset + * @param throwable throwable returned when processing request + */ + public abstract void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable); + + /** + * Called when request succeeds + * + * @param statusCode http response status line + * @param headers response headers if any + * @param responseString string response of given charset + */ + public abstract void onSuccess(int statusCode, Header[] headers, String responseString); + + @Override + public void onSuccess(int statusCode, Header[] headers, byte[] responseBytes) { + onSuccess(statusCode, headers, getResponseString(responseBytes, getCharset())); + } + + @Override + public void onFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { + onFailure(statusCode, headers, getResponseString(responseBytes, getCharset()), throwable); + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/TokenCredentials.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/TokenCredentials.java new file mode 100644 index 0000000000000000000000000000000000000000..07c88e364e5acf6b92519a142eed902cf993188b --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/TokenCredentials.java @@ -0,0 +1,42 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package com.example.httplibrary.utils; + +import cz.msebera.android.httpclient.auth.BasicUserPrincipal; +import cz.msebera.android.httpclient.auth.Credentials; + +import java.security.Principal; + +public class TokenCredentials implements Credentials { + private Principal userPrincipal; + + public TokenCredentials(String token) { + this.userPrincipal = new BasicUserPrincipal(token); + } + + @Override + public Principal getUserPrincipal() { + return userPrincipal; + } + + @Override + public String getPassword() { + return null; + } + +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Utils.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Utils.java new file mode 100644 index 0000000000000000000000000000000000000000..7b9fa4f3a982012dde5d654616d3e869277a54eb --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/Utils.java @@ -0,0 +1,56 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; + +/** + * Provides general assert utils, which are stripped by Android SDK on + * compile/runtime, to work on release builds + */ +class Utils { + + private Utils() { + } + + /** + * Will throw AssertionError, if expression is not true + * + * @param expression result of your asserted condition + * @param failedMessage message to be included in error log + * @throws AssertionError + */ + public static void asserts(final boolean expression, final String failedMessage) { + if (!expression) { + throw new AssertionError(failedMessage); + } + } + + /** + * Will throw IllegalArgumentException if provided object is null on runtime + * + * @param argument object that should be asserted as not null + * @param name name of the object asserted + * @throws IllegalArgumentException + */ + public static T notNull(final T argument, final String name) { + if (argument == null) { + throw new IllegalArgumentException(name + " should not be null!"); + } + return argument; + } +} diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/package-info.java b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..1b8166c26b7e14dee208465410f13c507e26852b --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/java/com/example/httplibrary/utils/package-info.java @@ -0,0 +1,19 @@ +/* + Android Asynchronous Http Client + Copyright (c) 2011 James Smith + https://github.com/android-async-http/android-async-http + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.example.httplibrary.utils; \ No newline at end of file diff --git a/001.Http_OpenHarmony-master/code/httplibrary/src/main/resources/base/element/string.json b/001.Http_OpenHarmony-master/code/httplibrary/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..8aa48534037b5902315b7dd8e76a3d9c419dbe91 --- /dev/null +++ b/001.Http_OpenHarmony-master/code/httplibrary/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "HttpLibrary" + } + ] +} diff --git a/001.Http_OpenHarmony-master/code/settings.gradle b/001.Http_OpenHarmony-master/code/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..6e0ed4f335108197250ce8162aa0b17c51104cca --- /dev/null +++ b/001.Http_OpenHarmony-master/code/settings.gradle @@ -0,0 +1 @@ +include ':entry', ':httplibrary' diff --git "a/001.Http_OpenHarmony-master/doc/001.\345\237\272\344\272\216\351\270\277\350\222\231\347\263\273\347\273\237\347\232\204AsyncHttpt\347\275\221\347\273\234\350\257\267\346\261\202\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.docx" "b/001.Http_OpenHarmony-master/doc/001.\345\237\272\344\272\216\351\270\277\350\222\231\347\263\273\347\273\237\347\232\204AsyncHttpt\347\275\221\347\273\234\350\257\267\346\261\202\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.docx" new file mode 100644 index 0000000000000000000000000000000000000000..9ed0e297b99f3283a77157135747bd0dce90096a Binary files /dev/null and "b/001.Http_OpenHarmony-master/doc/001.\345\237\272\344\272\216\351\270\277\350\222\231\347\263\273\347\273\237\347\232\204AsyncHttpt\347\275\221\347\273\234\350\257\267\346\261\202\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.docx" differ diff --git a/002.Logger_OpenHarmony-master/code/.gitignore b/002.Logger_OpenHarmony-master/code/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..603b14077394cd2294ac6922fe619669630ef3ab --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/002.Logger_OpenHarmony-master/code/.idea/.gitignore b/002.Logger_OpenHarmony-master/code/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/002.Logger_OpenHarmony-master/code/.idea/compiler.xml b/002.Logger_OpenHarmony-master/code/.idea/compiler.xml new file mode 100644 index 0000000000000000000000000000000000000000..61a9130cd9669c3843e6445dfe1fee2d493869bc --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/.idea/gradle.xml b/002.Logger_OpenHarmony-master/code/.idea/gradle.xml new file mode 100644 index 0000000000000000000000000000000000000000..c2d076d2f02152eacadf306e0af929d2c18ea97f --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/gradle.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/.idea/jarRepositories.xml b/002.Logger_OpenHarmony-master/code/.idea/jarRepositories.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba2e7443424bc5abb3b2c16dd9751cfceb69faed --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/jarRepositories.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/.idea/misc.xml b/002.Logger_OpenHarmony-master/code/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..f43837a9d879322d3f3c732d212a3e507d555196 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/.idea/previewer/phone/phoneSettingConfig_106113203.json b/002.Logger_OpenHarmony-master/code/.idea/previewer/phone/phoneSettingConfig_106113203.json new file mode 100644 index 0000000000000000000000000000000000000000..78eb57dc08fbe128df6330c0cca9865faa8e367d --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/previewer/phone/phoneSettingConfig_106113203.json @@ -0,0 +1,25 @@ +{ + "setting": { + "1.0.1": { + "Language": { + "args": { + "Language": "zh-CN" + } + } + } + }, + "frontend": { + "1.0.0": { + "Resolution": { + "args": { + "Resolution": "360*750" + } + }, + "DeviceType": { + "args": { + "DeviceType": "phone" + } + } + } + } +} \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/.idea/previewer/previewConfig.json b/002.Logger_OpenHarmony-master/code/.idea/previewer/previewConfig.json new file mode 100644 index 0000000000000000000000000000000000000000..aa81fdc628c6b30a045626455caf76cfe2c52d1c --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/previewer/previewConfig.json @@ -0,0 +1,9 @@ +{ + "1.0.0": { + "LastPreviewDevice": { + "E:\\MyApplication\\entry": [ + "phone" + ] + } + } +} \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/.idea/vcs.xml b/002.Logger_OpenHarmony-master/code/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/.gitignore b/002.Logger_OpenHarmony-master/code/Logger_harmony/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/.gitignore @@ -0,0 +1 @@ +/build diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/build.gradle b/002.Logger_OpenHarmony-master/code/Logger_harmony/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..972645f6b0acde106dafede80a9c0852f6f7df0d --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/build.gradle @@ -0,0 +1,14 @@ +apply plugin: 'com.huawei.ohos.library' +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 4 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + testCompile'junit:junit:4.12' + implementation 'org.jetbrains:annotations:15.0' +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/config.json b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..47fbf57e303cd4ae130f29c4823b87af0a7a4821 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/config.json @@ -0,0 +1,28 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 4, + "releaseType": "Beta1" + } + }, + "deviceConfig": { + }, + "module": { + "package": "com.example.logger_harmony", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "Logger_harmony", + "moduleType": "har" + } + } +} \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/CsvFormatStrategy.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/CsvFormatStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..31e87a3d49d0bf720783b879b03e69b46ef46024 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/CsvFormatStrategy.java @@ -0,0 +1,153 @@ +package com.example.logger_harmony; + + +import ohos.app.Context; +import ohos.app.Environment; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import static com.example.logger_harmony.Utils.checkNotNull; + + +/** + * CSV formatted file logging for Android. + * Writes to CSV the following data: + * epoch timestamp, ISO8601 timestamp (human-readable), log level, tag, log message. + */ +public class CsvFormatStrategy implements FormatStrategy { + + private static final String NEW_LINE = System.getProperty("line.separator"); + private static final String NEW_LINE_REPLACEMENT = "
"; + private static final String SEPARATOR = ","; + + private final Date date; + private final SimpleDateFormat dateFormat; + private final LogStrategy logStrategy; + @Nullable + private final String tag; + + private CsvFormatStrategy(Builder builder) { + checkNotNull(builder); + + date = builder.date; + dateFormat = builder.dateFormat; + logStrategy = builder.logStrategy; + tag = builder.tag; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public void log(int priority, @Nullable String onceOnlyTag, String message) { + checkNotNull(message); + + String tag = formatTag(onceOnlyTag); + + date.setTime(System.currentTimeMillis()); + + StringBuilder builder = new StringBuilder(); + + // machine-readable date/time + builder.append(Long.toString(date.getTime())); + + // human-readable date/time + builder.append(SEPARATOR); + builder.append(dateFormat.format(date)); + + // level + builder.append(SEPARATOR); + builder.append(Utils.logLevel(priority)); + + // tag + builder.append(SEPARATOR); + builder.append(tag); + + // message + if (message.contains(NEW_LINE)) { + // a new line would break the CSV format, so we replace it here + message = message.replaceAll(NEW_LINE, NEW_LINE_REPLACEMENT); + } + builder.append(SEPARATOR); + builder.append(message); + + // new line + builder.append(NEW_LINE); + + logStrategy.log(priority, tag, builder.toString()); + } + + @Nullable + private String formatTag(@Nullable String tag) { + if (!Utils.isEmpty(tag) && !Utils.equals(this.tag, tag)) { + return this.tag + "-" + tag; + } + return this.tag; + } + + public static final class Builder { + private static final int MAX_BYTES = 500 * 1024; // 500K averages to a 4000 lines per file + + Date date; + SimpleDateFormat dateFormat; + LogStrategy logStrategy; + String tag = "PRETTY_LOGGER"; + + private Builder() { + } + + public Builder date(@Nullable Date val) { + date = val; + return this; + } + + public Builder dateFormat(@Nullable SimpleDateFormat val) { + dateFormat = val; + return this; + } + + public Builder logStrategy(@Nullable LogStrategy val) { + logStrategy = val; + return this; + } + + public Builder tag(@Nullable String tag) { + this.tag = tag; + return this; + } + + public CsvFormatStrategy build(Context context) { + if (date == null) { + date = new Date(); + } + if (dateFormat == null) { + dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS", Locale.UK); + } + if (logStrategy == null) { +// String diskPath = Environment.DIRECTORY_DOCUMENTS; +// String folder = diskPath + File.separatorChar + "logger"; + +// +//// HandlerThread ht = new HandlerThread("AndroidFileLogger." + folder); +//// ht.start(); +//// Handler handler = new DiskLogStrategy.WriteHandler(ht.getLooper(), folder, MAX_BYTES); +// + File distDir = context.getDistributedDir(); + String filePath = distDir + File.separator + "logger.csv"; + + EventRunner eventRunner = EventRunner.create(true); + EventHandler eventHandler = new DiskLogStrategy.WriteHandler(eventRunner, filePath); + logStrategy = new DiskLogStrategy(eventHandler); + + } + return new CsvFormatStrategy(this); + } + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/DiskLogAdapter.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/DiskLogAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..28985ff04542b89d06014e222f788624bd2f1988 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/DiskLogAdapter.java @@ -0,0 +1,34 @@ +package com.example.logger_harmony; + + +import ohos.app.Context; +import org.jetbrains.annotations.Nullable; + +import static com.example.logger_harmony.Utils.checkNotNull; + +/** + * This is used to saves log messages to the disk. + * By default it uses {@link CsvFormatStrategy} to translates text message into CSV format. + */ +public class DiskLogAdapter implements LogAdapter { + + private final FormatStrategy formatStrategy; + + public DiskLogAdapter(Context context) { + formatStrategy = CsvFormatStrategy.newBuilder().build(context); + } + + public DiskLogAdapter( FormatStrategy formatStrategy) { + this.formatStrategy = checkNotNull(formatStrategy); + } + + @Override + public boolean isLoggable(int priority, @Nullable String tag) { + return true; + } + + @Override + public void log(int priority, @Nullable String tag, String message) { + formatStrategy.log(priority, tag, message); + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/DiskLogStrategy.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/DiskLogStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..8d2912e6b02def31999e276815464630449dfeb8 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/DiskLogStrategy.java @@ -0,0 +1,62 @@ +package com.example.logger_harmony; + + +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; +import ohos.hiviewdfx.HiLog; +import org.jetbrains.annotations.Nullable; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static com.example.logger_harmony.Utils.checkNotNull; + +/** + * Abstract class that takes care of background threading the file log operation on Android. + * implementing classes are free to directly perform I/O operations there. + *

+ * Writes all logs to the disk with CSV format. + */ +public class DiskLogStrategy implements LogStrategy { + + private final EventHandler handler; + + public DiskLogStrategy(EventHandler handler) { + this.handler = checkNotNull(handler); + } + + @Override + public void log(int level, @Nullable String tag, String message) { + checkNotNull(message); + + InnerEvent event = InnerEvent.get(0, message); + handler.sendEvent(event); + } + + static class WriteHandler extends EventHandler { + + private String folder; + + public WriteHandler(EventRunner runner, String filePath) throws IllegalArgumentException { + super(runner); + this.folder = filePath; + } + + @Override + protected void processEvent(InnerEvent event) { + super.processEvent(event); + try { + String param = event.object.toString(); + FileWriter fileWriter = new FileWriter(folder, true); + fileWriter.write(param); + fileWriter.flush(); + fileWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/FormatStrategy.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/FormatStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..9ee837896017593b9a97eeac713cf1958baef6bc --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/FormatStrategy.java @@ -0,0 +1,14 @@ +package com.example.logger_harmony; + +import org.jetbrains.annotations.Nullable; + +/** + * Used to determine how messages should be printed or saved. + * + * @see PrettyFormatStrategy + * @see CsvFormatStrategy + */ +public interface FormatStrategy { + + void log(int priority, @Nullable String tag, String message); +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/HarmonyOsLogAdapter.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/HarmonyOsLogAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..a30a323724e01622e2b2f0ab949d68ea5c778b27 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/HarmonyOsLogAdapter.java @@ -0,0 +1,43 @@ +package com.example.logger_harmony; + + +import org.jetbrains.annotations.Nullable; + +import static com.example.logger_harmony.Utils.checkNotNull; + +/** + * Android terminal log output implementation for {@link LogAdapter}. + * + * Prints output to LogCat with pretty borders. + * + *

+ *  ┌──────────────────────────
+ *  │ Method stack history
+ *  ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
+ *  │ Log message
+ *  └──────────────────────────
+ * 
+ */ +public class HarmonyOsLogAdapter implements LogAdapter { + + private final FormatStrategy formatStrategy; + + public HarmonyOsLogAdapter() { + this.formatStrategy = PrettyFormatStrategy.newBuilder().build(); + } + + public HarmonyOsLogAdapter(FormatStrategy formatStrategy) { + this.formatStrategy = checkNotNull(formatStrategy); + } + + @Override + public boolean isLoggable(int priority, @Nullable String tag) { + return true; + } + + @Override + public void log(int priority, @Nullable String tag, String message) { + formatStrategy.log(priority, tag, message); + } + +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogAdapter.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..ba8cd7f21039ed6a4037617e2d2e285cd6576a0c --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogAdapter.java @@ -0,0 +1,31 @@ +package com.example.logger_harmony; + +import org.jetbrains.annotations.Nullable; + +/** + * Provides a common interface to emits logs through. This is a required contract for Logger. + * + * @see HarmonyOsLogAdapter + * @see DiskLogAdapter + */ +public interface LogAdapter { + + /** + * Used to determine whether log should be printed out or not. + * + * @param priority is the log level e.g. DEBUG, WARNING + * @param tag is the given tag for the log message + * @return is used to determine if log should printed. + * If it is true, it will be printed, otherwise it'll be ignored. + */ + boolean isLoggable(int priority, @Nullable String tag); + + /** + * Each log will use this pipeline + * + * @param priority is the log level e.g. DEBUG, WARNING + * @param tag is the given tag for the log message. + * @param message is the given message for the log message. + */ + void log(int priority, @Nullable String tag, String message); +} \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogStrategy.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..b8af639d7fe1ca3829c235241cee1948a0b3d389 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogStrategy.java @@ -0,0 +1,22 @@ +package com.example.logger_harmony; + +import org.jetbrains.annotations.Nullable; + +/** + * Determines destination target for the logs such as Disk, Logcat etc. + * + * @see LogcatLogStrategy + * @see DiskLogStrategy + */ +public interface LogStrategy { + + /** + * This is invoked by Logger each time a log message is processed. + * Interpret this method as last destination of the log in whole pipeline. + * + * @param priority is the log level e.g. DEBUG, WARNING + * @param tag is the given tag for the log message. + * @param message is the given message for the log message. + */ + void log(int priority, @Nullable String tag, String message); +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogcatLogStrategy.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogcatLogStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..88266823a0afaebc0c12eeb10e7e0e179952dfde --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LogcatLogStrategy.java @@ -0,0 +1,54 @@ +package com.example.logger_harmony; + +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; +import org.jetbrains.annotations.Nullable; + +import static com.example.logger_harmony.Utils.checkNotNull; + +/** + * LogCat implementation for {@link LogStrategy} + *

+ * This simply prints out all logs to Logcat by using standard {@link} class. + */ +public class LogcatLogStrategy implements LogStrategy { + + static final String DEFAULT_TAG = "NO_TAG"; + + + @Override + public void log(int priority, @Nullable String tag, String message) { + checkNotNull(message); + + if (tag == null) { + tag = DEFAULT_TAG; + } + HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, tag); + +// public static final int DEBUG = 3; +// public static final int INFO = 4; +// public static final int WARN = 5; +// public static final int ERROR = 6; +// public static final int ASSERT = 7; + + + switch (priority) { + case Logger.DEBUG: + HiLog.debug(label, message); + break; + case Logger.INFO: + HiLog.info(label, message); + break; + case Logger.WARN: + HiLog.warn(label, message); + break; + case Logger.ERROR: + HiLog.error(label, message); + break; + case Logger.ASSERT: + HiLog.fatal(label, message); + break; + + } + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Logger.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Logger.java new file mode 100644 index 0000000000000000000000000000000000000000..8856ff2e2bae8a4cbdb79dea69742f0db8f120a8 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Logger.java @@ -0,0 +1,163 @@ +package com.example.logger_harmony; + + +import org.jetbrains.annotations.Nullable; + +import static com.example.logger_harmony.Utils.checkNotNull; + +/** + *

+ *  ┌────────────────────────────────────────────
+ *  │ LOGGER
+ *  ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
+ *  │ Standard logging mechanism
+ *  ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
+ *  │ But more pretty, simple and powerful
+ *  └────────────────────────────────────────────
+ * 
+ * + *

How to use it

+ * Initialize it first + *

+ *   Logger.addLogAdapter(new AndroidLogAdapter());
+ * 
+ * + * And use the appropriate static Logger methods. + * + *

+ *   Logger.d("debug");
+ *   Logger.e("error");
+ *   Logger.w("warning");
+ *   Logger.v("verbose");
+ *   Logger.i("information");
+ *   Logger.wtf("What a Terrible Failure");
+ * 
+ * + *

String format arguments are supported

+ *

+ *   Logger.d("hello %s", "world");
+ * 
+ * + *

Collections are support ed(only available for debug logs)

+ *

+ *   Logger.d(MAP);
+ *   Logger.d(SET);
+ *   Logger.d(LIST);
+ *   Logger.d(ARRAY);
+ * 
+ * + *

Json and Xml support (output will be in debug level)

+ *

+ *   Logger.json(JSON_CONTENT);
+ *   Logger.xml(XML_CONTENT);
+ * 
+ * + *

Customize Logger

+ * Based on your needs, you can change the following settings: + *
    + *
  • Different {@link LogAdapter}
  • + *
  • Different {@link FormatStrategy}
  • + *
  • Different {@link LogStrategy}
  • + *
+ * + * @see LogAdapter + * @see FormatStrategy + * @see LogStrategy + */ +public final class Logger { + + public static final int VERBOSE = 2; + public static final int DEBUG = 3; + public static final int INFO = 4; + public static final int WARN = 5; + public static final int ERROR = 6; + public static final int ASSERT = 7; + + private static Printer printer = new LoggerPrinter(); + + private Logger() { + //no instance + } + + public static void printer( Printer printer) { + Logger.printer = checkNotNull(printer); + } + + public static void addLogAdapter( LogAdapter adapter) { + printer.addAdapter(checkNotNull(adapter)); + } + + public static void clearLogAdapters() { + printer.clearLogAdapters(); + } + + /** + * Given tag will be used as tag only once for this method call regardless of the tag that's been + * set during initialization. After this invocation, the general tag that's been set will + * be used for the subsequent log calls + */ + public static Printer t(@Nullable String tag) { + return printer.t(tag); + } + + /** + * General log function that accepts all configurations as parameter + */ + public static void log(int priority, @Nullable String tag, @Nullable String message, @Nullable Throwable throwable) { + printer.log(priority, tag, message, throwable); + } + + public static void d(String message, @Nullable Object... args) { + printer.d(message, args); + } + + public static void d(@Nullable Object object) { + printer.d(object); + } + + public static void e(String message, @Nullable Object... args) { + printer.e(null, message, args); + } + + public static void e(@Nullable Throwable throwable, String message, @Nullable Object... args) { + printer.e(throwable, message, args); + } + + public static void i(String message, @Nullable Object... args) { + printer.i(message, args); + } + public static void i(@Nullable Object object) { + printer.i(object); + } + + public static void v(String message, @Nullable Object... args) { + printer.v(message, args); + } + + public static void w(String message, @Nullable Object... args) { + printer.w(message, args); + } + + /** + * Tip: Use this for exceptional situations to log + * ie: Unexpected errors etc + */ + public static void wtf(String message, @Nullable Object... args) { + printer.wtf(message, args); + } + + /** + * Formats the given json content and print it + */ + public static void json(@Nullable String json) { + printer.json(json); + } + + /** + * Formats the given xml content and print it + */ + public static void xml(@Nullable String xml) { + printer.xml(xml); + } + +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LoggerPrinter.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LoggerPrinter.java new file mode 100644 index 0000000000000000000000000000000000000000..2f4b3f33afc6bdb297a20c2703d2e449efe8bedd --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/LoggerPrinter.java @@ -0,0 +1,191 @@ +package com.example.logger_harmony; + + +import org.jetbrains.annotations.Nullable; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import static com.example.logger_harmony.Logger.*; +import static com.example.logger_harmony.Utils.checkNotNull; + +class LoggerPrinter implements Printer { + + /** + * It is used for json pretty print + */ + private static final int JSON_INDENT = 2; + + /** + * Provides one-time used tag for the log message + */ + private final ThreadLocal localTag = new ThreadLocal<>(); + + private final List logAdapters = new ArrayList<>(); + + @Override + public Printer t(String tag) { + if (tag != null) { + localTag.set(tag); + } + return this; + } + + @Override + public void d(String message, @Nullable Object... args) { + log(DEBUG, null, message, args); + } + + @Override + public void d(@Nullable Object object) { + log(DEBUG, null, Utils.toString(object)); + } + + @Override + public void e(String message, @Nullable Object... args) { + e(null, message, args); + } + + @Override + public void e(@Nullable Throwable throwable, String message, @Nullable Object... args) { + log(ERROR, throwable, message, args); + } + + @Override + public void w(String message, @Nullable Object... args) { + log(WARN, null, message, args); + } + + @Override + public void i(String message, @Nullable Object... args) { + log(INFO, null, message, args); + } + + @Override + public void i(@Nullable Object object) { + log(INFO, null, Utils.toString(object)); + + } + + @Override + public void v(String message, @Nullable Object... args) { + log(VERBOSE, null, message, args); + } + + @Override + public void wtf(String message, @Nullable Object... args) { + log(ASSERT, null, message, args); + } + + @Override + public void json(@Nullable String json) { + if (Utils.isEmpty(json)) { + d("Empty/Null json content"); + return; + } + try { + json = json.trim(); + if (json.startsWith("{")) { + JSONObject jsonObject = new JSONObject(json); + String message = jsonObject.toString(JSON_INDENT); + i(message); + return; + } + if (json.startsWith("[")) { + JSONArray jsonArray = new JSONArray(json); + String message = jsonArray.toString(JSON_INDENT); + i(message); + return; + } + e("Invalid Json"); + } catch (Exception e) { + e("Invalid Json"); + } + } + + @Override + public void xml(@Nullable String xml) { + if (Utils.isEmpty(xml)) { + d("Empty/Null xml content"); + return; + } +// try { +// +// Source xmlInput = new StreamSource(new StringReader(xml)); +// StreamResult xmlOutput = new StreamResult(new StringWriter()); +// +// Transformer transformer = TransformerFactory.newInstance().newTransformer(); +// transformer.setOutputProperty(OutputKeys.INDENT, "yes"); +// transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); +// transformer.transform(xmlInput, xmlOutput); +// d(xmlOutput.getWriter().toString().replaceFirst(">", ">\n")); +// } catch (TransformerException e) { +// e("Invalid xml"); +// } + } + + @Override + public synchronized void log(int priority, + @Nullable String tag, + @Nullable String message, + @Nullable Throwable throwable) { + if (throwable != null && message != null) { + message += " : " + Utils.getStackTraceString(throwable); + } + if (throwable != null && message == null) { + message = Utils.getStackTraceString(throwable); + } + if (Utils.isEmpty(message)) { + message = "Empty/NULL log message"; + } + + for (LogAdapter adapter : logAdapters) { + if (adapter.isLoggable(priority, tag)) { + adapter.log(priority, tag, message); + } + } + } + + @Override + public void clearLogAdapters() { + logAdapters.clear(); + } + + @Override + public void addAdapter(LogAdapter adapter) { + logAdapters.add(checkNotNull(adapter)); + } + + /** + * This method is synchronized in order to avoid messy of logs' order. + */ + private synchronized void log(int priority, + @Nullable Throwable throwable, + String msg, + @Nullable Object... args) { + checkNotNull(msg); + + String tag = getTag(); + String message = createMessage(msg, args); + log(priority, tag, message, throwable); + } + + /** + * @return the appropriate tag based on local or global + */ + @Nullable + private String getTag() { + String tag = localTag.get(); + if (tag != null) { + localTag.remove(); + return tag; + } + return null; + } + + private String createMessage(String message, @Nullable Object... args) { + return args == null || args.length == 0 ? message : String.format(message, args); + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/PrettyFormatStrategy.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/PrettyFormatStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..7d952f7a3cde7d1b884fd6181de2ab86bdd711b0 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/PrettyFormatStrategy.java @@ -0,0 +1,258 @@ +package com.example.logger_harmony; + +import org.jetbrains.annotations.Nullable; + +import static com.example.logger_harmony.Utils.checkNotNull; + +/** + * Draws borders around the given log message along with additional information such as : + * + *
    + *
  • Thread information
  • + *
  • Method stack trace
  • + *
+ * + *
+ *  ┌──────────────────────────
+ *  │ Method stack history
+ *  ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
+ *  │ Thread information
+ *  ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
+ *  │ Log message
+ *  └──────────────────────────
+ * 
+ * + *

Customize

+ *

+ *   FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder()
+ *       .showThreadInfo(false)  // (Optional) Whether to show thread info or not. Default true
+ *       .methodCount(0)         // (Optional) How many method line to show. Default 2
+ *       .methodOffset(7)        // (Optional) Hides internal method calls up to offset. Default 5
+ *       .logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat
+ *       .tag("My custom tag")   // (Optional) Global tag for every log. Default PRETTY_LOGGER
+ *       .build();
+ * 
+ */ +public class PrettyFormatStrategy implements FormatStrategy { + + /** + * Android's max limit for a log entry is ~4076 bytes, + * so 4000 bytes is used as chunk size since default charset + * is UTF-8 + */ + private static final int CHUNK_SIZE = 4000; + + /** + * The minimum stack trace index, starts at this class after two native calls. + */ + private static final int MIN_STACK_OFFSET = 5; + + /** + * Drawing toolbox + */ + private static final char TOP_LEFT_CORNER = '┌'; + private static final char BOTTOM_LEFT_CORNER = '└'; + private static final char MIDDLE_CORNER = '├'; + private static final char HORIZONTAL_LINE = '│'; + private static final String DOUBLE_DIVIDER = "────────────────────────────────────────────────────────"; + private static final String SINGLE_DIVIDER = "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄"; + private static final String TOP_BORDER = TOP_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER; + private static final String BOTTOM_BORDER = BOTTOM_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER; + private static final String MIDDLE_BORDER = MIDDLE_CORNER + SINGLE_DIVIDER + SINGLE_DIVIDER; + + private final int methodCount; + private final int methodOffset; + private final boolean showThreadInfo; + private final LogStrategy logStrategy; + @Nullable + private final String tag; + + private PrettyFormatStrategy( Builder builder) { + checkNotNull(builder); + + methodCount = builder.methodCount; + methodOffset = builder.methodOffset; + showThreadInfo = builder.showThreadInfo; + logStrategy = builder.logStrategy; + tag = builder.tag; + } + + public static Builder newBuilder() { + return new Builder(); + } + + @Override + public void log(int priority, @Nullable String onceOnlyTag, String message) { + checkNotNull(message); + + String tag = formatTag(onceOnlyTag); + + logTopBorder(priority, tag); + logHeaderContent(priority, tag, methodCount); + + //get bytes of message with system's default charset (which is UTF-8 for Android) + byte[] bytes = message.getBytes(); + int length = bytes.length; + if (length <= CHUNK_SIZE) { + if (methodCount > 0) { + logDivider(priority, tag); + } + logContent(priority, tag, message); + logBottomBorder(priority, tag); + return; + } + if (methodCount > 0) { + logDivider(priority, tag); + } + for (int i = 0; i < length; i += CHUNK_SIZE) { + int count = Math.min(length - i, CHUNK_SIZE); + //create a new String with system's default charset (which is UTF-8 for Android) + logContent(priority, tag, new String(bytes, i, count)); + } + logBottomBorder(priority, tag); + } + + private void logTopBorder(int logType, @Nullable String tag) { + logChunk(logType, tag, TOP_BORDER); + } + + @SuppressWarnings("StringBufferReplaceableByString") + private void logHeaderContent(int logType, @Nullable String tag, int methodCount) { + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + if (showThreadInfo) { + logChunk(logType, tag, HORIZONTAL_LINE + " Thread: " + Thread.currentThread().getName()); + logDivider(logType, tag); + } + String level = ""; + + int stackOffset = getStackOffset(trace) + methodOffset; + + //corresponding method count with the current stack may exceeds the stack trace. Trims the count + if (methodCount + stackOffset > trace.length) { + methodCount = trace.length - stackOffset - 1; + } + + for (int i = methodCount; i > 0; i--) { + int stackIndex = i + stackOffset; + if (stackIndex >= trace.length) { + continue; + } + StringBuilder builder = new StringBuilder(); + builder.append(HORIZONTAL_LINE) + .append(' ') + .append(level) + .append(getSimpleClassName(trace[stackIndex].getClassName())) + .append(".") + .append(trace[stackIndex].getMethodName()) + .append(" ") + .append(" (") + .append(trace[stackIndex].getFileName()) + .append(":") + .append(trace[stackIndex].getLineNumber()) + .append(")"); + level += " "; + logChunk(logType, tag, builder.toString()); + } + } + + private void logBottomBorder(int logType, @Nullable String tag) { + logChunk(logType, tag, BOTTOM_BORDER); + } + + private void logDivider(int logType, @Nullable String tag) { + logChunk(logType, tag, MIDDLE_BORDER); + } + + private void logContent(int logType, @Nullable String tag, String chunk) { + checkNotNull(chunk); + + String[] lines = chunk.split(System.getProperty("line.separator")); + for (String line : lines) { + logChunk(logType, tag, HORIZONTAL_LINE + " " + line); + } + } + + private void logChunk(int priority, @Nullable String tag, String chunk) { + checkNotNull(chunk); + + logStrategy.log(priority, tag, chunk); + } + + private String getSimpleClassName(String name) { + checkNotNull(name); + + int lastIndex = name.lastIndexOf("."); + return name.substring(lastIndex + 1); + } + + /** + * Determines the starting index of the stack trace, after method calls made by this class. + * + * @param trace the stack trace + * @return the stack offset + */ + private int getStackOffset( StackTraceElement[] trace) { + checkNotNull(trace); + + for (int i = MIN_STACK_OFFSET; i < trace.length; i++) { + StackTraceElement e = trace[i]; + String name = e.getClassName(); + if (!name.equals(LoggerPrinter.class.getName()) && !name.equals(Logger.class.getName())) { + return --i; + } + } + return -1; + } + + @Nullable private String formatTag(@Nullable String tag) { + if (!Utils.isEmpty(tag) && !Utils.equals(this.tag, tag)) { + return this.tag + "-" + tag; + } + return this.tag; + } + + public static class Builder { + int methodCount = 2; + int methodOffset = 0; + boolean showThreadInfo = true; + @Nullable LogStrategy logStrategy; + @Nullable + String tag = "PRETTY_LOGGER"; + + private Builder() { + } + + public Builder methodCount(int val) { + methodCount = val; + return this; + } + + public Builder methodOffset(int val) { + methodOffset = val; + return this; + } + + public Builder showThreadInfo(boolean val) { + showThreadInfo = val; + return this; + } + + public Builder logStrategy(@Nullable LogStrategy val) { + logStrategy = val; + return this; + } + + public Builder tag(@Nullable String tag) { + this.tag = tag; + return this; + } + + public PrettyFormatStrategy build() { + if (logStrategy == null) { + logStrategy = new LogcatLogStrategy(); + } + return new PrettyFormatStrategy(this); + } + } + +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Printer.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Printer.java new file mode 100644 index 0000000000000000000000000000000000000000..c316200cfd30a35bf0940119f611132bc610790b --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Printer.java @@ -0,0 +1,46 @@ +package com.example.logger_harmony; + +import org.jetbrains.annotations.Nullable; + +/** + * A proxy interface to enable additional operations. + * Contains all possible Log message usages. + */ +public interface Printer { + + void addAdapter(LogAdapter adapter); + + Printer t(@Nullable String tag); + + void d(String message, @Nullable Object... args); + + void d(@Nullable Object object); + + void e(String message, @Nullable Object... args); + + void e(@Nullable Throwable throwable, String message, @Nullable Object... args); + + void w(String message, @Nullable Object... args); + + void i(String message, @Nullable Object... args); + + void i(@Nullable Object object); + + void v(String message, @Nullable Object... args); + + void wtf(String message, @Nullable Object... args); + + /** + * Formats the given json content and print it + */ + void json(@Nullable String json); + + /** + * Formats the given xml content and print it + */ + void xml(@Nullable String xml); + + void log(int priority, @Nullable String tag, @Nullable String message, @Nullable Throwable throwable); + + void clearLogAdapters(); +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Utils.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Utils.java new file mode 100644 index 0000000000000000000000000000000000000000..215c20b49b78a5564dfe3191905abf96ed8b65de --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/com/example/logger_harmony/Utils.java @@ -0,0 +1,151 @@ +package com.example.logger_harmony; + +import org.jetbrains.annotations.Nullable; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.UnknownHostException; +import java.util.Arrays; + +import static com.example.logger_harmony.Logger.*; + +/** + * Provides convenient methods to some common operations + */ +final class Utils { + + private Utils() { + // Hidden constructor. + } + + /** + * Returns true if the string is null or 0-length. + * + * @param str the string to be examined + * @return true if str is null or zero length + */ + static boolean isEmpty(CharSequence str) { + return str == null || str.length() == 0; + } + + /** + * Returns true if a and b are equal, including if they are both null. + *

Note: In platform versions 1.1 and earlier, this method only worked well if + * both the arguments were instances of String.

+ * + * @param a first CharSequence to check + * @param b second CharSequence to check + * @return true if a and b are equal + *

+ * NOTE: Logic slightly change due to strict policy on CI - + * "Inner assignments should be avoided" + */ + static boolean equals(CharSequence a, CharSequence b) { + if (a == b) return true; + if (a != null && b != null) { + int length = a.length(); + if (length == b.length()) { + if (a instanceof String && b instanceof String) { + return a.equals(b); + } else { + for (int i = 0; i < length; i++) { + if (a.charAt(i) != b.charAt(i)) return false; + } + return true; + } + } + } + return false; + } + + /** + * Copied from "android.util.Log.getStackTraceString()" in order to avoid usage of Android stack + * in unit tests. + * + * @return Stack trace in form of String + */ + static String getStackTraceString(Throwable tr) { + if (tr == null) { + return ""; + } + + // This is to reduce the amount of log spew that apps do in the non-error + // condition of the network being unavailable. + Throwable t = tr; + while (t != null) { + if (t instanceof UnknownHostException) { + return ""; + } + t = t.getCause(); + } + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + tr.printStackTrace(pw); + pw.flush(); + return sw.toString(); + } + + static String logLevel(int value) { + switch (value) { + case VERBOSE: + return "VERBOSE"; + case DEBUG: + return "DEBUG"; + case INFO: + return "INFO"; + case WARN: + return "WARN"; + case ERROR: + return "ERROR"; + case ASSERT: + return "ASSERT"; + default: + return "UNKNOWN"; + } + } + + public static String toString(Object object) { + if (object == null) { + return "null"; + } + if (!object.getClass().isArray()) { + return object.toString(); + } + if (object instanceof boolean[]) { + return Arrays.toString((boolean[]) object); + } + if (object instanceof byte[]) { + return Arrays.toString((byte[]) object); + } + if (object instanceof char[]) { + return Arrays.toString((char[]) object); + } + if (object instanceof short[]) { + return Arrays.toString((short[]) object); + } + if (object instanceof int[]) { + return Arrays.toString((int[]) object); + } + if (object instanceof long[]) { + return Arrays.toString((long[]) object); + } + if (object instanceof float[]) { + return Arrays.toString((float[]) object); + } + if (object instanceof double[]) { + return Arrays.toString((double[]) object); + } + if (object instanceof Object[]) { + return Arrays.deepToString((Object[]) object); + } + return "Couldn't find a correct type for the object"; + } + + static T checkNotNull(@Nullable final T obj) { + if (obj == null) { + throw new NullPointerException(); + } + return obj; + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSON.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSON.java new file mode 100644 index 0000000000000000000000000000000000000000..ac304a80e902d58f30b3952ff2b0f05a4794e720 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSON.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.json; + +class JSON { + /** + * Returns the input if it is a JSON-permissible value; throws otherwise. + */ + static double checkDouble(double d) throws JSONException { + if (Double.isInfinite(d) || Double.isNaN(d)) { + throw new JSONException("Forbidden numeric value: " + d); + } + return d; + } + + static Boolean toBoolean(Object value) { + if (value instanceof Boolean) { + return (Boolean) value; + } else if (value instanceof String) { + String stringValue = (String) value; + if ("true".equalsIgnoreCase(stringValue)) { + return true; + } else if ("false".equalsIgnoreCase(stringValue)) { + return false; + } + } + return null; + } + + static Double toDouble(Object value) { + if (value instanceof Double) { + return (Double) value; + } else if (value instanceof Number) { + return ((Number) value).doubleValue(); + } else if (value instanceof String) { + try { + return Double.valueOf((String) value); + } catch (NumberFormatException ignored) { + } + } + return null; + } + + static Integer toInteger(Object value) { + if (value instanceof Integer) { + return (Integer) value; + } else if (value instanceof Number) { + return ((Number) value).intValue(); + } else if (value instanceof String) { + try { + return (int) Double.parseDouble((String) value); + } catch (NumberFormatException ignored) { + } + } + return null; + } + + static Long toLong(Object value) { + if (value instanceof Long) { + return (Long) value; + } else if (value instanceof Number) { + return ((Number) value).longValue(); + } else if (value instanceof String) { + try { + return (long) Double.parseDouble((String) value); + } catch (NumberFormatException ignored) { + } + } + return null; + } + + static String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value != null) { + return String.valueOf(value); + } + return null; + } + + public static JSONException typeMismatch(Object indexOrName, Object actual, + String requiredType) throws JSONException { + if (actual == null) { + throw new JSONException("Value at " + indexOrName + " is null."); + } else { + throw new JSONException("Value " + actual + " at " + indexOrName + + " of type " + actual.getClass().getName() + + " cannot be converted to " + requiredType); + } + } + + public static JSONException typeMismatch(Object actual, String requiredType) + throws JSONException { + if (actual == null) { + throw new JSONException("Value is null."); + } else { + throw new JSONException("Value " + actual + + " of type " + actual.getClass().getName() + + " cannot be converted to " + requiredType); + } + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONArray.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONArray.java new file mode 100644 index 0000000000000000000000000000000000000000..63d67ed6b3097f09e4a71d4847719cf0e89e835c --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONArray.java @@ -0,0 +1,630 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.json; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * A dense indexed sequence of values. Values may be any mix of + * {@link JSONObject JSONObjects}, other {@link JSONArray JSONArrays}, Strings, + * Booleans, Integers, Longs, Doubles, {@code null} or {@link JSONObject#NULL}. + * Values may not be {@link Double#isNaN() NaNs}, {@link Double#isInfinite() + * infinities}, or of any type not listed here. + * + *

{@code JSONArray} has the same type coercion behavior and + * optional/mandatory accessors as {@link JSONObject}. See that class' + * documentation for details. + * + *

Warning: this class represents null in two incompatible + * ways: the standard Java {@code null} reference, and the sentinel value {@link + * JSONObject#NULL}. In particular, {@code get} fails if the requested index + * holds the null reference, but succeeds if it holds {@code JSONObject.NULL}. + * + *

Instances of this class are not thread safe. Although this class is + * nonfinal, it was not designed for inheritance and should not be subclassed. + * In particular, self-use by overridable methods is not specified. See + * Effective Java Item 17, "Design and Document or inheritance or else + * prohibit it" for further information. + */ +public class JSONArray { + + private final List values; + + /** + * Creates a {@code JSONArray} with no values. + */ + public JSONArray() { + values = new ArrayList(); + } + + /** + * Creates a new {@code JSONArray} by copying all values from the given + * collection. + * + * @param copyFrom a collection whose values are of supported types. + * Unsupported values are not permitted and will yield an array in an + * inconsistent state. + */ + /* Accept a raw type for API compatibility */ + public JSONArray(Collection copyFrom) { + this(); + if (copyFrom != null) { + for (Iterator it = copyFrom.iterator(); it.hasNext(); ) { + put(JSONObject.wrap(it.next())); + } + } + } + + /** + * Creates a new {@code JSONArray} with values from the next array in the + * tokener. + * + * @param readFrom a tokener whose nextValue() method will yield a + * {@code JSONArray}. + * @throws JSONException if the parse fails or doesn't yield a + * {@code JSONArray}. + */ + public JSONArray(JSONTokener readFrom) throws JSONException { + /* + * Getting the parser to populate this could get tricky. Instead, just + * parse to temporary JSONArray and then steal the data from that. + */ + Object object = readFrom.nextValue(); + if (object instanceof JSONArray) { + values = ((JSONArray) object).values; + } else { + throw JSON.typeMismatch(object, "JSONArray"); + } + } + + /** + * Creates a new {@code JSONArray} with values from the JSON string. + * + * @param json a JSON-encoded string containing an array. + * @throws JSONException if the parse fails or doesn't yield a {@code + * JSONArray}. + */ + public JSONArray(String json) throws JSONException { + this(new JSONTokener(json)); + } + + /** + * Creates a new {@code JSONArray} with values from the given primitive array. + */ + public JSONArray(Object array) throws JSONException { + if (!array.getClass().isArray()) { + throw new JSONException("Not a primitive array: " + array.getClass()); + } + final int length = Array.getLength(array); + values = new ArrayList(length); + for (int i = 0; i < length; ++i) { + put(JSONObject.wrap(Array.get(array, i))); + } + } + + /** + * Returns the number of values in this array. + */ + public int length() { + return values.size(); + } + + /** + * Appends {@code value} to the end of this array. + * + * @return this array. + */ + public JSONArray put(boolean value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this array. + */ + public JSONArray put(double value) throws JSONException { + values.add(JSON.checkDouble(value)); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @return this array. + */ + public JSONArray put(int value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @return this array. + */ + public JSONArray put(long value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May + * not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite() + * infinities}. Unsupported values are not permitted and will cause the + * array to be in an inconsistent state. + * @return this array. + */ + public JSONArray put(Object value) { + values.add(value); + return this; + } + + /** + * Same as {@link #put}, with added validity checks. + */ + void checkedPut(Object value) throws JSONException { + if (value instanceof Number) { + JSON.checkDouble(((Number) value).doubleValue()); + } + + put(value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @return this array. + */ + public JSONArray put(int index, boolean value) throws JSONException { + return put(index, (Boolean) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this array. + */ + public JSONArray put(int index, double value) throws JSONException { + return put(index, (Double) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @return this array. + */ + public JSONArray put(int index, int value) throws JSONException { + return put(index, (Integer) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @return this array. + */ + public JSONArray put(int index, long value) throws JSONException { + return put(index, (Long) value); + } + + /** + * Sets the value at {@code index} to {@code value}, null padding this array + * to the required length if necessary. If a value already exists at {@code + * index}, it will be replaced. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May + * not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite() + * infinities}. + * @return this array. + */ + public JSONArray put(int index, Object value) throws JSONException { + if (value instanceof Number) { + // deviate from the original by checking all Numbers, not just floats & doubles + JSON.checkDouble(((Number) value).doubleValue()); + } + while (values.size() <= index) { + values.add(null); + } + values.set(index, value); + return this; + } + + /** + * Returns true if this array has no value at {@code index}, or if its value + * is the {@code null} reference or {@link JSONObject#NULL}. + */ + public boolean isNull(int index) { + Object value = opt(index); + return value == null || value == JSONObject.NULL; + } + + /** + * Returns the value at {@code index}. + * + * @throws JSONException if this array has no value at {@code index}, or if + * that value is the {@code null} reference. This method returns + * normally if the value is {@code JSONObject#NULL}. + */ + public Object get(int index) throws JSONException { + try { + Object value = values.get(index); + if (value == null) { + throw new JSONException("Value at " + index + " is null."); + } + return value; + } catch (IndexOutOfBoundsException e) { + throw new JSONException("Index " + index + " out of range [0.." + values.size() + ")", e); + } + } + + /** + * Returns the value at {@code index}, or null if the array has no value + * at {@code index}. + */ + public Object opt(int index) { + if (index < 0 || index >= values.size()) { + return null; + } + return values.get(index); + } + + /** + * Removes and returns the value at {@code index}, or null if the array has no value + * at {@code index}. + */ + public Object remove(int index) { + if (index < 0 || index >= values.size()) { + return null; + } + return values.remove(index); + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. + * + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a boolean. + */ + public boolean getBoolean(int index) throws JSONException { + Object object = get(index); + Boolean result = JSON.toBoolean(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "boolean"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. Returns false otherwise. + */ + public boolean optBoolean(int index) { + return optBoolean(index, false); + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. Returns {@code fallback} otherwise. + */ + public boolean optBoolean(int index, boolean fallback) { + Object object = opt(index); + Boolean result = JSON.toBoolean(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is a double or can + * be coerced to a double. + * + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a double. + */ + public double getDouble(int index) throws JSONException { + Object object = get(index); + Double result = JSON.toDouble(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "double"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is a double or can + * be coerced to a double. Returns {@code NaN} otherwise. + */ + public double optDouble(int index) { + return optDouble(index, Double.NaN); + } + + /** + * Returns the value at {@code index} if it exists and is a double or can + * be coerced to a double. Returns {@code fallback} otherwise. + */ + public double optDouble(int index, double fallback) { + Object object = opt(index); + Double result = JSON.toDouble(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is an int or + * can be coerced to an int. + * + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a int. + */ + public int getInt(int index) throws JSONException { + Object object = get(index); + Integer result = JSON.toInteger(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "int"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is an int or + * can be coerced to an int. Returns 0 otherwise. + */ + public int optInt(int index) { + return optInt(index, 0); + } + + /** + * Returns the value at {@code index} if it exists and is an int or + * can be coerced to an int. Returns {@code fallback} otherwise. + */ + public int optInt(int index, int fallback) { + Object object = opt(index); + Integer result = JSON.toInteger(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is a long or + * can be coerced to a long. + * + * @throws JSONException if the value at {@code index} doesn't exist or + * cannot be coerced to a long. + */ + public long getLong(int index) throws JSONException { + Object object = get(index); + Long result = JSON.toLong(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "long"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists and is a long or + * can be coerced to a long. Returns 0 otherwise. + */ + public long optLong(int index) { + return optLong(index, 0L); + } + + /** + * Returns the value at {@code index} if it exists and is a long or + * can be coerced to a long. Returns {@code fallback} otherwise. + */ + public long optLong(int index, long fallback) { + Object object = opt(index); + Long result = JSON.toLong(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. + * + * @throws JSONException if no such value exists. + */ + public String getString(int index) throws JSONException { + Object object = get(index); + String result = JSON.toString(object); + if (result == null) { + throw JSON.typeMismatch(index, object, "String"); + } + return result; + } + + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. Returns the empty string if no such value exists. + */ + public String optString(int index) { + return optString(index, ""); + } + + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. Returns {@code fallback} if no such value exists. + */ + public String optString(int index, String fallback) { + Object object = opt(index); + String result = JSON.toString(object); + return result != null ? result : fallback; + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONArray}. + * + * @throws JSONException if the value doesn't exist or is not a {@code + * JSONArray}. + */ + public JSONArray getJSONArray(int index) throws JSONException { + Object object = get(index); + if (object instanceof JSONArray) { + return (JSONArray) object; + } else { + throw JSON.typeMismatch(index, object, "JSONArray"); + } + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONArray}. Returns null otherwise. + */ + public JSONArray optJSONArray(int index) { + Object object = opt(index); + return object instanceof JSONArray ? (JSONArray) object : null; + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONObject}. + * + * @throws JSONException if the value doesn't exist or is not a {@code + * JSONObject}. + */ + public JSONObject getJSONObject(int index) throws JSONException { + Object object = get(index); + if (object instanceof JSONObject) { + return (JSONObject) object; + } else { + throw JSON.typeMismatch(index, object, "JSONObject"); + } + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONObject}. Returns null otherwise. + */ + public JSONObject optJSONObject(int index) { + Object object = opt(index); + return object instanceof JSONObject ? (JSONObject) object : null; + } + + /** + * Returns a new object whose values are the values in this array, and whose + * names are the values in {@code names}. Names and values are paired up by + * index from 0 through to the shorter array's length. Names that are not + * strings will be coerced to strings. This method returns null if either + * array is empty. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException { + JSONObject result = new JSONObject(); + int length = Math.min(names.length(), values.size()); + if (length == 0) { + return null; + } + for (int i = 0; i < length; i++) { + String name = JSON.toString(names.opt(i)); + result.put(name, opt(i)); + } + return result; + } + + /** + * Returns a new string by alternating this array's values with {@code + * separator}. This array's string values are quoted and have their special + * characters escaped. For example, the array containing the strings '12" + * pizza', 'taco' and 'soda' joined on '+' returns this: + *
"12\" pizza"+"taco"+"soda"
+ */ + public String join(String separator) throws JSONException { + JSONStringer stringer = new JSONStringer(); + stringer.open(JSONStringer.Scope.NULL, ""); + for (int i = 0, size = values.size(); i < size; i++) { + if (i > 0) { + stringer.out.append(separator); + } + stringer.value(values.get(i)); + } + stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); + return stringer.out.toString(); + } + + /** + * Encodes this array as a compact JSON string, such as: + *
[94043,90210]
+ */ + @Override + public String toString() { + try { + JSONStringer stringer = new JSONStringer(); + writeTo(stringer); + return stringer.toString(); + } catch (JSONException e) { + return null; + } + } + + /** + * Encodes this array as a human readable JSON string for debugging, such + * as: + *
+     * [
+     *     94043,
+     *     90210
+     * ]
+ * + * @param indentSpaces the number of spaces to indent for each level of + * nesting. + */ + public String toString(int indentSpaces) throws JSONException { + JSONStringer stringer = new JSONStringer(indentSpaces); + writeTo(stringer); + return stringer.toString(); + } + + + void writeTo(JSONStringer stringer) throws JSONException { + stringer.array(); + for (Object value : values) { + stringer.value(value); + } + stringer.endArray(); + } + + @Override + public boolean equals(Object o) { + return o instanceof JSONArray && ((JSONArray) o).values.equals(values); + } + + @Override + public int hashCode() { + // diverge from the original, which doesn't implement hashCode + return values.hashCode(); + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONException.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONException.java new file mode 100644 index 0000000000000000000000000000000000000000..05e1dddc9aa4666dc89175d144288f9d9aa08ce4 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONException.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.json; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * Thrown to indicate a problem with the JSON API. Such problems include: + *
    + *
  • Attempts to parse or construct malformed documents + *
  • Use of null as a name + *
  • Use of numeric types not available to JSON, such as {@link + * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}. + *
  • Lookups using an out of range index or nonexistent name + *
  • Type mismatches on lookups + *
+ * + *

Although this is a checked exception, it is rarely recoverable. Most + * callers should simply wrap this exception in an unchecked exception and + * rethrow: + *

  public JSONArray toJSONObject() {
+ *     try {
+ *         JSONObject result = new JSONObject();
+ *         ...
+ *     } catch (JSONException e) {
+ *         throw new RuntimeException(e);
+ *     }
+ * }
+ */ +public class JSONException extends Exception { + + public JSONException(String s) { + super(s); + } + + public JSONException(String message, Throwable cause) { + super(message, cause); + } + + public JSONException(Throwable cause) { + super(cause); + } + +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONObject.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONObject.java new file mode 100644 index 0000000000000000000000000000000000000000..587dd4302e92984360ed39646190aabcc645dc5d --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONObject.java @@ -0,0 +1,855 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.json; + +import java.util.*; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * A modifiable set of name/value mappings. Names are unique, non-null strings. + * Values may be any mix of {@link JSONObject JSONObjects}, {@link JSONArray + * JSONArrays}, Strings, Booleans, Integers, Longs, Doubles or {@link #NULL}. + * Values may not be {@code null}, {@link Double#isNaN() NaNs}, {@link + * Double#isInfinite() infinities}, or of any type not listed here. + * + *

This class can coerce values to another type when requested. + *

+ * + *

This class can look up both mandatory and optional values: + *

    + *
  • Use getType() to retrieve a mandatory value. This + * fails with a {@code JSONException} if the requested name has no value + * or if the value cannot be coerced to the requested type. + *
  • Use optType() to retrieve an optional value. This + * returns a system- or user-supplied default if the requested name has no + * value or if the value cannot be coerced to the requested type. + *
+ * + *

Warning: this class represents null in two incompatible + * ways: the standard Java {@code null} reference, and the sentinel value {@link + * JSONObject#NULL}. In particular, calling {@code put(name, null)} removes the + * named entry from the object but {@code put(name, JSONObject.NULL)} stores an + * entry whose value is {@code JSONObject.NULL}. + * + *

Instances of this class are not thread safe. Although this class is + * nonfinal, it was not designed for inheritance and should not be subclassed. + * In particular, self-use by overrideable methods is not specified. See + * Effective Java Item 17, "Design and Document or inheritance or else + * prohibit it" for further information. + */ +public class JSONObject { + + private static final Double NEGATIVE_ZERO = -0d; + + /** + * A sentinel value used to explicitly define a name with no value. Unlike + * {@code null}, names with this value: + *

    + *
  • show up in the {@link #names} array + *
  • show up in the {@link #keys} iterator + *
  • return {@code true} for {@link #has(String)} + *
  • do not throw on {@link #get(String)} + *
  • are included in the encoded JSON string. + *
+ * + *

This value violates the general contract of {@link Object#equals} by + * returning true when compared to {@code null}. Its {@link #toString} + * method returns "null". + */ + public static final Object NULL = new Object() { + @Override + public boolean equals(Object o) { + return o == this || o == null; // API specifies this broken equals implementation + } + + // at least make the broken equals(null) consistent with Objects.hashCode(null). + @Override + public int hashCode() { + return Objects.hashCode(null); + } + + @Override + public String toString() { + return "null"; + } + }; + + + private final LinkedHashMap nameValuePairs; + + /** + * Creates a {@code JSONObject} with no name/value mappings. + */ + public JSONObject() { + nameValuePairs = new LinkedHashMap(); + } + + /** + * Creates a new {@code JSONObject} by copying all name/value mappings from + * the given map. + * + * @param copyFrom a map whose keys are of type {@link String} and whose + * values are of supported types. + * @throws NullPointerException if any of the map's keys are null. + */ + /* (accept a raw type for API compatibility) */ + public JSONObject(Map copyFrom) { + this(); + Map contentsTyped = (Map) copyFrom; + for (Map.Entry entry : contentsTyped.entrySet()) { + /* + * Deviate from the original by checking that keys are non-null and + * of the proper type. (We still defer validating the values). + */ + String key = (String) entry.getKey(); + if (key == null) { + throw new NullPointerException("key == null"); + } + nameValuePairs.put(key, wrap(entry.getValue())); + } + } + + /** + * Creates a new {@code JSONObject} with name/value mappings from the next + * object in the tokener. + * + * @param readFrom a tokener whose nextValue() method will yield a + * {@code JSONObject}. + * @throws JSONException if the parse fails or doesn't yield a + * {@code JSONObject}. + */ + public JSONObject(JSONTokener readFrom) throws JSONException { + /* + * Getting the parser to populate this could get tricky. Instead, just + * parse to temporary JSONObject and then steal the data from that. + */ + Object object = readFrom.nextValue(); + if (object instanceof JSONObject) { + this.nameValuePairs = ((JSONObject) object).nameValuePairs; + } else { + throw JSON.typeMismatch(object, "JSONObject"); + } + } + + /** + * Creates a new {@code JSONObject} with name/value mappings from the JSON + * string. + * + * @param json a JSON-encoded string containing an object. + * @throws JSONException if the parse fails or doesn't yield a {@code + * JSONObject}. + */ + public JSONObject(String json) throws JSONException { + this(new JSONTokener(json)); + } + + /** + * Creates a new {@code JSONObject} by copying mappings for the listed names + * from the given object. Names that aren't present in {@code copyFrom} will + * be skipped. + */ + public JSONObject(JSONObject copyFrom, String[] names) throws JSONException { + this(); + for (String name : names) { + Object value = copyFrom.opt(name); + if (value != null) { + nameValuePairs.put(name, value); + } + } + } + + /** + * Returns the number of name/value mappings in this object. + */ + public int length() { + return nameValuePairs.size(); + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @return this object. + */ + + public JSONObject put(String name, boolean value) throws JSONException { + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this object. + */ + + public JSONObject put(String name, double value) throws JSONException { + nameValuePairs.put(checkName(name), JSON.checkDouble(value)); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @return this object. + */ + + public JSONObject put(String name, int value) throws JSONException { + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. + * + * @return this object. + */ + + public JSONObject put(String name, long value) throws JSONException { + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Maps {@code name} to {@code value}, clobbering any existing name/value + * mapping with the same name. If the value is {@code null}, any existing + * mapping for {@code name} is removed. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link #NULL}, or {@code null}. May not be + * {@link Double#isNaN() NaNs} or {@link Double#isInfinite() + * infinities}. + * @return this object. + */ + + public JSONObject put(String name, Object value) throws JSONException { + if (value == null) { + nameValuePairs.remove(name); + return this; + } + if (value instanceof Number) { + // deviate from the original by checking all Numbers, not just floats & doubles + JSON.checkDouble(((Number) value).doubleValue()); + } + nameValuePairs.put(checkName(name), value); + return this; + } + + /** + * Equivalent to {@code put(name, value)} when both parameters are non-null; + * does nothing otherwise. + */ + + public JSONObject putOpt(String name, Object value) throws JSONException { + if (name == null || value == null) { + return this; + } + return put(name, value); + } + + /** + * Appends {@code value} to the array already mapped to {@code name}. If + * this object has no mapping for {@code name}, this inserts a new mapping. + * If the mapping exists but its value is not an array, the existing + * and new values are inserted in order into a new array which is itself + * mapped to {@code name}. In aggregate, this allows values to be added to a + * mapping one at a time. + * + *

Note that {@code append(String, Object)} provides better semantics. + * In particular, the mapping for {@code name} will always be a + * {@link JSONArray}. Using {@code accumulate} will result in either a + * {@link JSONArray} or a mapping whose type is the type of {@code value} + * depending on the number of calls to it. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double, {@link #NULL} or null. May not be {@link + * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}. + */ + // TODO: Change {@code append) to {@link #append} when append is + // unhidden. + public JSONObject accumulate(String name, Object value) throws JSONException { + Object current = nameValuePairs.get(checkName(name)); + if (current == null) { + return put(name, value); + } + + if (current instanceof JSONArray) { + JSONArray array = (JSONArray) current; + array.checkedPut(value); + } else { + JSONArray array = new JSONArray(); + array.checkedPut(current); + array.checkedPut(value); + nameValuePairs.put(name, array); + } + return this; + } + + /** + * Appends values to the array mapped to {@code name}. A new {@link JSONArray} + * mapping for {@code name} will be inserted if no mapping exists. If the existing + * mapping for {@code name} is not a {@link JSONArray}, a {@link JSONException} + * will be thrown. + * + * @throws JSONException if {@code name} is {@code null} or if the mapping for + * {@code name} is non-null and is not a {@link JSONArray}. + * @hide + */ + + public JSONObject append(String name, Object value) throws JSONException { + Object current = nameValuePairs.get(checkName(name)); + + final JSONArray array; + if (current instanceof JSONArray) { + array = (JSONArray) current; + } else if (current == null) { + JSONArray newArray = new JSONArray(); + nameValuePairs.put(name, newArray); + array = newArray; + } else { + throw new JSONException("Key " + name + " is not a JSONArray"); + } + + array.checkedPut(value); + + return this; + } + + + String checkName(String name) throws JSONException { + if (name == null) { + throw new JSONException("Names must be non-null"); + } + return name; + } + + /** + * Removes the named mapping if it exists; does nothing otherwise. + * + * @return the value previously mapped by {@code name}, or null if there was + * no such mapping. + */ + + public Object remove(String name) { + return nameValuePairs.remove(name); + } + + /** + * Returns true if this object has no mapping for {@code name} or if it has + * a mapping whose value is {@link #NULL}. + */ + public boolean isNull(String name) { + Object value = nameValuePairs.get(name); + return value == null || value == NULL; + } + + /** + * Returns true if this object has a mapping for {@code name}. The mapping + * may be {@link #NULL}. + */ + public boolean has(String name) { + return nameValuePairs.containsKey(name); + } + + /** + * Returns the value mapped by {@code name}, or throws if no such mapping exists. + * + * @throws JSONException if no such mapping exists. + */ + + public Object get(String name) throws JSONException { + Object result = nameValuePairs.get(name); + if (result == null) { + throw new JSONException("No value for " + name); + } + return result; + } + + /** + * Returns the value mapped by {@code name}, or null if no such mapping + * exists. + */ + + public Object opt(String name) { + return nameValuePairs.get(name); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a boolean or + * can be coerced to a boolean, or throws otherwise. + * + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to a boolean. + */ + public boolean getBoolean(String name) throws JSONException { + Object object = get(name); + Boolean result = JSON.toBoolean(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "boolean"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a boolean or + * can be coerced to a boolean, or false otherwise. + */ + public boolean optBoolean(String name) { + return optBoolean(name, false); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a boolean or + * can be coerced to a boolean, or {@code fallback} otherwise. + */ + public boolean optBoolean(String name, boolean fallback) { + Object object = opt(name); + Boolean result = JSON.toBoolean(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a double or + * can be coerced to a double, or throws otherwise. + * + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to a double. + */ + public double getDouble(String name) throws JSONException { + Object object = get(name); + Double result = JSON.toDouble(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "double"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a double or + * can be coerced to a double, or {@code NaN} otherwise. + */ + public double optDouble(String name) { + return optDouble(name, Double.NaN); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a double or + * can be coerced to a double, or {@code fallback} otherwise. + */ + public double optDouble(String name, double fallback) { + Object object = opt(name); + Double result = JSON.toDouble(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is an int or + * can be coerced to an int, or throws otherwise. + * + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to an int. + */ + public int getInt(String name) throws JSONException { + Object object = get(name); + Integer result = JSON.toInteger(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "int"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is an int or + * can be coerced to an int, or 0 otherwise. + */ + public int optInt(String name) { + return optInt(name, 0); + } + + /** + * Returns the value mapped by {@code name} if it exists and is an int or + * can be coerced to an int, or {@code fallback} otherwise. + */ + public int optInt(String name, int fallback) { + Object object = opt(name); + Integer result = JSON.toInteger(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a long or + * can be coerced to a long, or throws otherwise. + * Note that JSON represents numbers as doubles, + * so this is lossy; use strings to transfer numbers via JSON. + * + * @throws JSONException if the mapping doesn't exist or cannot be coerced + * to a long. + */ + public long getLong(String name) throws JSONException { + Object object = get(name); + Long result = JSON.toLong(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "long"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a long or + * can be coerced to a long, or 0 otherwise. Note that JSON represents numbers as doubles, + * so this is lossy; use strings to transfer numbers via JSON. + */ + public long optLong(String name) { + return optLong(name, 0L); + } + + /** + * Returns the value mapped by {@code name} if it exists and is a long or + * can be coerced to a long, or {@code fallback} otherwise. Note that JSON represents + * numbers as doubles, so this is lossy; use strings to transfer + * numbers via JSON. + */ + public long optLong(String name, long fallback) { + Object object = opt(name); + Long result = JSON.toLong(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists, coercing it if + * necessary, or throws if no such mapping exists. + * + * @throws JSONException if no such mapping exists. + */ + + public String getString(String name) throws JSONException { + Object object = get(name); + String result = JSON.toString(object); + if (result == null) { + throw JSON.typeMismatch(name, object, "String"); + } + return result; + } + + /** + * Returns the value mapped by {@code name} if it exists, coercing it if + * necessary, or the empty string if no such mapping exists. + */ + + public String optString(String name) { + return optString(name, ""); + } + + /** + * Returns the value mapped by {@code name} if it exists, coercing it if + * necessary, or {@code fallback} if no such mapping exists. + */ + + public String optString(String name, String fallback) { + Object object = opt(name); + String result = JSON.toString(object); + return result != null ? result : fallback; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONArray}, or throws otherwise. + * + * @throws JSONException if the mapping doesn't exist or is not a {@code + * JSONArray}. + */ + + public JSONArray getJSONArray(String name) throws JSONException { + Object object = get(name); + if (object instanceof JSONArray) { + return (JSONArray) object; + } else { + throw JSON.typeMismatch(name, object, "JSONArray"); + } + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONArray}, or null otherwise. + */ + + public JSONArray optJSONArray(String name) { + Object object = opt(name); + return object instanceof JSONArray ? (JSONArray) object : null; + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONObject}, or throws otherwise. + * + * @throws JSONException if the mapping doesn't exist or is not a {@code + * JSONObject}. + */ + + public JSONObject getJSONObject(String name) throws JSONException { + Object object = get(name); + if (object instanceof JSONObject) { + return (JSONObject) object; + } else { + throw JSON.typeMismatch(name, object, "JSONObject"); + } + } + + /** + * Returns the value mapped by {@code name} if it exists and is a {@code + * JSONObject}, or null otherwise. + */ + + public JSONObject optJSONObject(String name) { + Object object = opt(name); + return object instanceof JSONObject ? (JSONObject) object : null; + } + + /** + * Returns an array with the values corresponding to {@code names}. The + * array contains null for names that aren't mapped. This method returns + * null if {@code names} is either null or empty. + */ + + public JSONArray toJSONArray(JSONArray names) throws JSONException { + JSONArray result = new JSONArray(); + if (names == null) { + return null; + } + int length = names.length(); + if (length == 0) { + return null; + } + for (int i = 0; i < length; i++) { + String name = JSON.toString(names.opt(i)); + result.put(opt(name)); + } + return result; + } + + /** + * Returns an iterator of the {@code String} names in this object. The + * returned iterator supports {@link Iterator#remove() remove}, which will + * remove the corresponding mapping from this object. If this object is + * modified after the iterator is returned, the iterator's behavior is + * undefined. The order of the keys is undefined. + */ + + public Iterator keys() { + return nameValuePairs.keySet().iterator(); + } + + /** + * Returns the set of {@code String} names in this object. The returned set + * is a view of the keys in this object. {@link Set#remove(Object)} will remove + * the corresponding mapping from this object and set iterator behaviour + * is undefined if this object is modified after it is returned. + *

+ * See {@link #keys()}. + * + * @hide. + */ + public Set keySet() { + return nameValuePairs.keySet(); + } + + /** + * Returns an array containing the string names in this object. This method + * returns null if this object contains no mappings. + */ + + public JSONArray names() { + return nameValuePairs.isEmpty() + ? null + : new JSONArray(new ArrayList(nameValuePairs.keySet())); + } + + /** + * Encodes this object as a compact JSON string, such as: + *

{"query":"Pizza","locations":[94043,90210]}
+ */ + @Override + + public String toString() { + try { + JSONStringer stringer = new JSONStringer(); + writeTo(stringer); + return stringer.toString(); + } catch (JSONException e) { + return null; + } + } + + /** + * Encodes this object as a human readable JSON string for debugging, such + * as: + *
+     * {
+     *     "query": "Pizza",
+     *     "locations": [
+     *         94043,
+     *         90210
+     *     ]
+     * }
+ * + * @param indentSpaces the number of spaces to indent for each level of + * nesting. + */ + + public String toString(int indentSpaces) throws JSONException { + JSONStringer stringer = new JSONStringer(indentSpaces); + writeTo(stringer); + return stringer.toString(); + } + + + void writeTo(JSONStringer stringer) throws JSONException { + stringer.object(); + for (Map.Entry entry : nameValuePairs.entrySet()) { + stringer.key(entry.getKey()).value(entry.getValue()); + } + stringer.endObject(); + } + + /** + * Encodes the number as a JSON string. + * + * @param number a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + */ + + public static String numberToString(Number number) throws JSONException { + if (number == null) { + throw new JSONException("Number must be non-null"); + } + + double doubleValue = number.doubleValue(); + JSON.checkDouble(doubleValue); + + // the original returns "-0" instead of "-0.0" for negative zero + if (number.equals(NEGATIVE_ZERO)) { + return "-0"; + } + + long longValue = number.longValue(); + if (doubleValue == (double) longValue) { + return Long.toString(longValue); + } + + return number.toString(); + } + + /** + * Encodes {@code data} as a JSON string. This applies quotes and any + * necessary character escaping. + * + * @param data the string to encode. Null will be interpreted as an empty + * string. + */ + + public static String quote(String data) { + if (data == null) { + return "\"\""; + } + try { + JSONStringer stringer = new JSONStringer(); + stringer.open(JSONStringer.Scope.NULL, ""); + stringer.value(data); + stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); + return stringer.toString(); + } catch (JSONException e) { + throw new AssertionError(); + } + } + + /** + * Wraps the given object if necessary. + * + *

If the object is null or , returns {@link #NULL}. + * If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary. + * If the object is {@code NULL}, no wrapping is necessary. + * If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}. + * If the object is a {@code Map}, returns an equivalent {@code JSONObject}. + * If the object is a primitive wrapper type or {@code String}, returns the object. + * Otherwise if the object is from a {@code java} package, returns the result of {@code toString}. + * If wrapping fails, returns null. + */ + + public static Object wrap(Object o) { + if (o == null) { + return NULL; + } + if (o instanceof JSONArray || o instanceof JSONObject) { + return o; + } + if (o.equals(NULL)) { + return o; + } + try { + if (o instanceof Collection) { + return new JSONArray((Collection) o); + } else if (o.getClass().isArray()) { + return new JSONArray(o); + } + if (o instanceof Map) { + return new JSONObject((Map) o); + } + if (o instanceof Boolean || + o instanceof Byte || + o instanceof Character || + o instanceof Double || + o instanceof Float || + o instanceof Integer || + o instanceof Long || + o instanceof Short || + o instanceof String) { + return o; + } + if (o.getClass().getPackage().getName().startsWith("java.")) { + return o.toString(); + } + } catch (Exception ignored) { + } + return null; + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONStringer.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONStringer.java new file mode 100644 index 0000000000000000000000000000000000000000..668e1c75dfa90ee2bcf2d8f01569bbcb27f9484d --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONStringer.java @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.json; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * Implements {@link JSONObject#toString} and {@link JSONArray#toString}. Most + * application developers should use those methods directly and disregard this + * API. For example:

+ * JSONObject object = ...
+ * String json = object.toString();
+ * + *

Stringers only encode well-formed JSON strings. In particular: + *

    + *
  • The stringer must have exactly one top-level array or object. + *
  • Lexical scopes must be balanced: every call to {@link #array} must + * have a matching call to {@link #endArray} and every call to {@link + * #object} must have a matching call to {@link #endObject}. + *
  • Arrays may not contain keys (property names). + *
  • Objects must alternate keys (property names) and values. + *
  • Values are inserted with either literal {@link #value(Object) value} + * calls, or by nesting arrays or objects. + *
+ * Calls that would result in a malformed JSON string will fail with a + * {@link JSONException}. + * + *

This class provides no facility for pretty-printing (ie. indenting) + * output. To encode indented output, use {@link JSONObject#toString(int)} or + * {@link JSONArray#toString(int)}. + * + *

Some implementations of the API support at most 20 levels of nesting. + * Attempts to create more than 20 levels of nesting may fail with a {@link + * JSONException}. + * + *

Each stringer may be used to encode a single top level value. Instances of + * this class are not thread safe. Although this class is nonfinal, it was not + * designed for inheritance and should not be subclassed. In particular, + * self-use by overrideable methods is not specified. See Effective Java + * Item 17, "Design and Document or inheritance or else prohibit it" for further + * information. + */ +public class JSONStringer { + + /** + * The output data, containing at most one top-level array or object. + */ + final StringBuilder out = new StringBuilder(); + + /** + * Lexical scoping elements within this stringer, necessary to insert the + * appropriate separator characters (ie. commas and colons) and to detect + * nesting errors. + */ + enum Scope { + + /** + * An array with no elements requires no separators or newlines before + * it is closed. + */ + EMPTY_ARRAY, + + /** + * A array with at least one value requires a comma and newline before + * the next element. + */ + NONEMPTY_ARRAY, + + /** + * An object with no keys or values requires no separators or newlines + * before it is closed. + */ + EMPTY_OBJECT, + + /** + * An object whose most recent element is a key. The next element must + * be a value. + */ + DANGLING_KEY, + + /** + * An object with at least one name/value pair requires a comma and + * newline before the next element. + */ + NONEMPTY_OBJECT, + + /** + * A special bracketless array needed by JSONStringer.join() and + * JSONObject.quote() only. Not used for JSON encoding. + */ + NULL, + } + + /** + * Unlike the original implementation, this stack isn't limited to 20 + * levels of nesting. + */ + + private final List stack = new ArrayList(); + + /** + * A string containing a full set of spaces for a single level of + * indentation, or null for no pretty printing. + */ + + private final String indent; + + public JSONStringer() { + indent = null; + } + + + JSONStringer(int indentSpaces) { + char[] indentChars = new char[indentSpaces]; + Arrays.fill(indentChars, ' '); + indent = new String(indentChars); + } + + /** + * Begins encoding a new array. Each call to this method must be paired with + * a call to {@link #endArray}. + * + * @return this stringer. + */ + public JSONStringer array() throws JSONException { + return open(Scope.EMPTY_ARRAY, "["); + } + + /** + * Ends encoding the current array. + * + * @return this stringer. + */ + public JSONStringer endArray() throws JSONException { + return close(Scope.EMPTY_ARRAY, Scope.NONEMPTY_ARRAY, "]"); + } + + /** + * Begins encoding a new object. Each call to this method must be paired + * with a call to {@link #endObject}. + * + * @return this stringer. + */ + public JSONStringer object() throws JSONException { + return open(Scope.EMPTY_OBJECT, "{"); + } + + /** + * Ends encoding the current object. + * + * @return this stringer. + */ + public JSONStringer endObject() throws JSONException { + return close(Scope.EMPTY_OBJECT, Scope.NONEMPTY_OBJECT, "}"); + } + + /** + * Enters a new scope by appending any necessary whitespace and the given + * bracket. + */ + + JSONStringer open(Scope empty, String openBracket) throws JSONException { + if (stack.isEmpty() && out.length() > 0) { + throw new JSONException("Nesting problem: multiple top-level roots"); + } + beforeValue(); + stack.add(empty); + out.append(openBracket); + return this; + } + + /** + * Closes the current scope by appending any necessary whitespace and the + * given bracket. + */ + + JSONStringer close(Scope empty, Scope nonempty, String closeBracket) throws JSONException { + Scope context = peek(); + if (context != nonempty && context != empty) { + throw new JSONException("Nesting problem"); + } + + stack.remove(stack.size() - 1); + if (context == nonempty) { + newline(); + } + out.append(closeBracket); + return this; + } + + /** + * Returns the value on the top of the stack. + */ + + private Scope peek() throws JSONException { + if (stack.isEmpty()) { + throw new JSONException("Nesting problem"); + } + return stack.get(stack.size() - 1); + } + + /** + * Replace the value on the top of the stack with the given value. + */ + + private void replaceTop(Scope topOfStack) { + stack.set(stack.size() - 1, topOfStack); + } + + /** + * Encodes {@code value}. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs} + * or {@link Double#isInfinite() infinities}. + * @return this stringer. + */ + public JSONStringer value(Object value) throws JSONException { + if (stack.isEmpty()) { + throw new JSONException("Nesting problem"); + } + + if (value instanceof JSONArray) { + ((JSONArray) value).writeTo(this); + return this; + + } else if (value instanceof JSONObject) { + ((JSONObject) value).writeTo(this); + return this; + } + + beforeValue(); + + if (value == null + || value instanceof Boolean + || value == JSONObject.NULL) { + out.append(value); + + } else if (value instanceof Number) { + out.append(JSONObject.numberToString((Number) value)); + + } else { + string(value.toString()); + } + + return this; + } + + /** + * Encodes {@code value} to this stringer. + * + * @return this stringer. + */ + public JSONStringer value(boolean value) throws JSONException { + if (stack.isEmpty()) { + throw new JSONException("Nesting problem"); + } + beforeValue(); + out.append(value); + return this; + } + + /** + * Encodes {@code value} to this stringer. + * + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this stringer. + */ + public JSONStringer value(double value) throws JSONException { + if (stack.isEmpty()) { + throw new JSONException("Nesting problem"); + } + beforeValue(); + out.append(JSONObject.numberToString(value)); + return this; + } + + /** + * Encodes {@code value} to this stringer. + * + * @return this stringer. + */ + public JSONStringer value(long value) throws JSONException { + if (stack.isEmpty()) { + throw new JSONException("Nesting problem"); + } + beforeValue(); + out.append(value); + return this; + } + + + private void string(String value) { + out.append("\""); + for (int i = 0, length = value.length(); i < length; i++) { + char c = value.charAt(i); + + /* + * From RFC 4627, "All Unicode characters may be placed within the + * quotation marks except for the characters that must be escaped: + * quotation mark, reverse solidus, and the control characters + * (U+0000 through U+001F)." + */ + switch (c) { + case '"': + case '\\': + case '/': + out.append('\\').append(c); + break; + + case '\t': + out.append("\\t"); + break; + + case '\b': + out.append("\\b"); + break; + + case '\n': + out.append("\\n"); + break; + + case '\r': + out.append("\\r"); + break; + + case '\f': + out.append("\\f"); + break; + + default: + if (c <= 0x1F) { + out.append(String.format("\\u%04x", (int) c)); + } else { + out.append(c); + } + break; + } + + } + out.append("\""); + } + + + private void newline() { + if (indent == null) { + return; + } + + out.append("\n"); + for (int i = 0; i < stack.size(); i++) { + out.append(indent); + } + } + + /** + * Encodes the key (property name) to this stringer. + * + * @param name the name of the forthcoming value. May not be null. + * @return this stringer. + */ + public JSONStringer key(String name) throws JSONException { + if (name == null) { + throw new JSONException("Names must be non-null"); + } + beforeKey(); + string(name); + return this; + } + + /** + * Inserts any necessary separators and whitespace before a name. Also + * adjusts the stack to expect the key's value. + */ + + private void beforeKey() throws JSONException { + Scope context = peek(); + if (context == Scope.NONEMPTY_OBJECT) { // first in object + out.append(','); + } else if (context != Scope.EMPTY_OBJECT) { // not in an object! + throw new JSONException("Nesting problem"); + } + newline(); + replaceTop(Scope.DANGLING_KEY); + } + + /** + * Inserts any necessary separators and whitespace before a literal value, + * inline array, or inline object. Also adjusts the stack to expect either a + * closing bracket or another element. + */ + + private void beforeValue() throws JSONException { + if (stack.isEmpty()) { + return; + } + + Scope context = peek(); + if (context == Scope.EMPTY_ARRAY) { // first in array + replaceTop(Scope.NONEMPTY_ARRAY); + newline(); + } else if (context == Scope.NONEMPTY_ARRAY) { // another in array + out.append(','); + newline(); + } else if (context == Scope.DANGLING_KEY) { // value for key + out.append(indent == null ? ":" : ": "); + replaceTop(Scope.NONEMPTY_OBJECT); + } else if (context != Scope.NULL) { + throw new JSONException("Nesting problem"); + } + } + + /** + * Returns the encoded JSON string. + * + *

If invoked with unterminated arrays or unclosed objects, this method's + * return value is undefined. + * + *

Warning: although it contradicts the general contract + * of {@link Object#toString}, this method returns null if the stringer + * contains no data. + */ + @Override + public String toString() { + return out.length() == 0 ? null : out.toString(); + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONTokener.java b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONTokener.java new file mode 100644 index 0000000000000000000000000000000000000000..026a04f935595a7978c08b5cf980be341e71ba5a --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/java/org/json/JSONTokener.java @@ -0,0 +1,622 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.json; + +// Note: this class was written without inspecting the non-free org.json sourcecode. + +/** + * Parses a JSON (RFC 4627) + * encoded string into the corresponding object. Most clients of + * this class will use only need the {@link #JSONTokener(String) constructor} + * and {@link #nextValue} method. Example usage:

+ * String json = "{"
+ *         + "  \"query\": \"Pizza\", "
+ *         + "  \"locations\": [ 94043, 90210 ] "
+ *         + "}";
+ *
+ * JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
+ * String query = object.getString("query");
+ * JSONArray locations = object.getJSONArray("locations");
+ * + *

For best interoperability and performance use JSON that complies with + * RFC 4627, such as that generated by {@link JSONStringer}. For legacy reasons + * this parser is lenient, so a successful parse does not indicate that the + * input string was valid JSON. All of the following syntax errors will be + * ignored: + *

    + *
  • End of line comments starting with {@code //} or {@code #} and ending + * with a newline character. + *
  • C-style comments starting with {@code /*} and ending with + * {@code *}{@code /}. Such comments may not be nested. + *
  • Strings that are unquoted or {@code 'single quoted'}. + *
  • Hexadecimal integers prefixed with {@code 0x} or {@code 0X}. + *
  • Octal integers prefixed with {@code 0}. + *
  • Array elements separated by {@code ;}. + *
  • Unnecessary array separators. These are interpreted as if null was the + * omitted value. + *
  • Key-value pairs separated by {@code =} or {@code =>}. + *
  • Key-value pairs separated by {@code ;}. + *
+ * + *

Each tokener may be used to parse a single JSON string. Instances of this + * class are not thread safe. Although this class is nonfinal, it was not + * designed for inheritance and should not be subclassed. In particular, + * self-use by overrideable methods is not specified. See Effective Java + * Item 17, "Design and Document or inheritance or else prohibit it" for further + * information. + */ +public class JSONTokener { + + /** + * The input JSON. + */ + + private final String in; + + /** + * The index of the next character to be returned by {@link #next}. When + * the input is exhausted, this equals the input's length. + */ + + private int pos; + + /** + * @param in JSON encoded string. Null is not permitted and will yield a + * tokener that throws {@code NullPointerExceptions} when methods are + * called. + */ + public JSONTokener(String in) { + // consume an optional byte order mark (BOM) if it exists + if (in != null && in.startsWith("\ufeff")) { + in = in.substring(1); + } + this.in = in; + } + + /** + * Returns the next value from the input. + * + * @return a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double or {@link JSONObject#NULL}. + * @throws JSONException if the input is malformed. + */ + public Object nextValue() throws JSONException { + int c = nextCleanInternal(); + switch (c) { + case -1: + throw syntaxError("End of input"); + + case '{': + return readObject(); + + case '[': + return readArray(); + + case '\'': + case '"': + return nextString((char) c); + + default: + pos--; + return readLiteral(); + } + } + + + private int nextCleanInternal() throws JSONException { + while (pos < in.length()) { + int c = in.charAt(pos++); + switch (c) { + case '\t': + case ' ': + case '\n': + case '\r': + continue; + + case '/': + if (pos == in.length()) { + return c; + } + + char peek = in.charAt(pos); + switch (peek) { + case '*': + // skip a /* c-style comment */ + pos++; + int commentEnd = in.indexOf("*/", pos); + if (commentEnd == -1) { + throw syntaxError("Unterminated comment"); + } + pos = commentEnd + 2; + continue; + + case '/': + // skip a // end-of-line comment + pos++; + skipToEndOfLine(); + continue; + + default: + return c; + } + + case '#': + /* + * Skip a # hash end-of-line comment. The JSON RFC doesn't + * specify this behavior, but it's required to parse + * existing documents. See http://b/2571423. + */ + skipToEndOfLine(); + continue; + + default: + return c; + } + } + + return -1; + } + + /** + * Advances the position until after the next newline character. If the line + * is terminated by "\r\n", the '\n' must be consumed as whitespace by the + * caller. + */ + + private void skipToEndOfLine() { + for (; pos < in.length(); pos++) { + char c = in.charAt(pos); + if (c == '\r' || c == '\n') { + pos++; + break; + } + } + } + + /** + * Returns the string up to but not including {@code quote}, unescaping any + * character escape sequences encountered along the way. The opening quote + * should have already been read. This consumes the closing quote, but does + * not include it in the returned string. + * + * @param quote either ' or ". + */ + public String nextString(char quote) throws JSONException { + /* + * For strings that are free of escape sequences, we can just extract + * the result as a substring of the input. But if we encounter an escape + * sequence, we need to use a StringBuilder to compose the result. + */ + StringBuilder builder = null; + + /* the index of the first character not yet appended to the builder. */ + int start = pos; + + while (pos < in.length()) { + int c = in.charAt(pos++); + if (c == quote) { + if (builder == null) { + // a new string avoids leaking memory + return new String(in.substring(start, pos - 1)); + } else { + builder.append(in, start, pos - 1); + return builder.toString(); + } + } + + if (c == '\\') { + if (pos == in.length()) { + throw syntaxError("Unterminated escape sequence"); + } + if (builder == null) { + builder = new StringBuilder(); + } + builder.append(in, start, pos - 1); + builder.append(readEscapeCharacter()); + start = pos; + } + } + + throw syntaxError("Unterminated string"); + } + + /** + * Unescapes the character identified by the character or characters that + * immediately follow a backslash. The backslash '\' should have already + * been read. This supports both unicode escapes "u000A" and two-character + * escapes "\n". + */ + + private char readEscapeCharacter() throws JSONException { + char escaped = in.charAt(pos++); + switch (escaped) { + case 'u': + if (pos + 4 > in.length()) { + throw syntaxError("Unterminated escape sequence"); + } + String hex = in.substring(pos, pos + 4); + pos += 4; + try { + return (char) Integer.parseInt(hex, 16); + } catch (NumberFormatException nfe) { + throw syntaxError("Invalid escape sequence: " + hex); + } + + case 't': + return '\t'; + + case 'b': + return '\b'; + + case 'n': + return '\n'; + + case 'r': + return '\r'; + + case 'f': + return '\f'; + + case '\'': + case '"': + case '\\': + default: + return escaped; + } + } + + /** + * Reads a null, boolean, numeric or unquoted string literal value. Numeric + * values will be returned as an Integer, Long, or Double, in that order of + * preference. + */ + + private Object readLiteral() throws JSONException { + String literal = nextToInternal("{}[]/\\:,=;# \t\f"); + + if (literal.length() == 0) { + throw syntaxError("Expected literal value"); + } else if ("null".equalsIgnoreCase(literal)) { + return JSONObject.NULL; + } else if ("true".equalsIgnoreCase(literal)) { + return Boolean.TRUE; + } else if ("false".equalsIgnoreCase(literal)) { + return Boolean.FALSE; + } + + /* try to parse as an integral type... */ + if (literal.indexOf('.') == -1) { + int base = 10; + String number = literal; + if (number.startsWith("0x") || number.startsWith("0X")) { + number = number.substring(2); + base = 16; + } else if (number.startsWith("0") && number.length() > 1) { + number = number.substring(1); + base = 8; + } + try { + long longValue = Long.parseLong(number, base); + if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) { + return (int) longValue; + } else { + return longValue; + } + } catch (NumberFormatException e) { + /* + * This only happens for integral numbers greater than + * Long.MAX_VALUE, numbers in exponential form (5e-10) and + * unquoted strings. Fall through to try floating point. + */ + } + } + + /* ...next try to parse as a floating point... */ + try { + return Double.valueOf(literal); + } catch (NumberFormatException ignored) { + } + + /* ... finally give up. We have an unquoted string */ + return new String(literal); // a new string avoids leaking memory + } + + /** + * Returns the string up to but not including any of the given characters or + * a newline character. This does not consume the excluded character. + */ + + private String nextToInternal(String excluded) { + int start = pos; + for (; pos < in.length(); pos++) { + char c = in.charAt(pos); + if (c == '\r' || c == '\n' || excluded.indexOf(c) != -1) { + return in.substring(start, pos); + } + } + return in.substring(start); + } + + /** + * Reads a sequence of key/value pairs and the trailing closing brace '}' of + * an object. The opening brace '{' should have already been read. + */ + + private JSONObject readObject() throws JSONException { + JSONObject result = new JSONObject(); + + /* Peek to see if this is the empty object. */ + int first = nextCleanInternal(); + if (first == '}') { + return result; + } else if (first != -1) { + pos--; + } + + while (true) { + Object name = nextValue(); + if (!(name instanceof String)) { + if (name == null) { + throw syntaxError("Names cannot be null"); + } else { + throw syntaxError("Names must be strings, but " + name + + " is of type " + name.getClass().getName()); + } + } + + /* + * Expect the name/value separator to be either a colon ':', an + * equals sign '=', or an arrow "=>". The last two are bogus but we + * include them because that's what the original implementation did. + */ + int separator = nextCleanInternal(); + if (separator != ':' && separator != '=') { + throw syntaxError("Expected ':' after " + name); + } + if (pos < in.length() && in.charAt(pos) == '>') { + pos++; + } + + result.put((String) name, nextValue()); + + switch (nextCleanInternal()) { + case '}': + return result; + case ';': + case ',': + continue; + default: + throw syntaxError("Unterminated object"); + } + } + } + + /** + * Reads a sequence of values and the trailing closing brace ']' of an + * array. The opening brace '[' should have already been read. Note that + * "[]" yields an empty array, but "[,]" returns a two-element array + * equivalent to "[null,null]". + */ + + private JSONArray readArray() throws JSONException { + JSONArray result = new JSONArray(); + + /* to cover input that ends with ",]". */ + boolean hasTrailingSeparator = false; + + while (true) { + switch (nextCleanInternal()) { + case -1: + throw syntaxError("Unterminated array"); + case ']': + if (hasTrailingSeparator) { + result.put(null); + } + return result; + case ',': + case ';': + /* A separator without a value first means "null". */ + result.put(null); + hasTrailingSeparator = true; + continue; + default: + pos--; + } + + result.put(nextValue()); + + switch (nextCleanInternal()) { + case ']': + return result; + case ',': + case ';': + hasTrailingSeparator = true; + continue; + default: + throw syntaxError("Unterminated array"); + } + } + } + + /** + * Returns an exception containing the given message plus the current + * position and the entire input string. + */ + public JSONException syntaxError(String message) { + return new JSONException(message + this); + } + + /** + * Returns the current position and the entire input string. + */ + @Override + public String toString() { + // consistent with the original implementation + return " at character " + pos + " of " + in; + } + + /* + * Legacy APIs. + * + * None of the methods below are on the critical path of parsing JSON + * documents. They exist only because they were exposed by the original + * implementation and may be used by some clients. + */ + + /** + * Returns true until the input has been exhausted. + */ + public boolean more() { + return pos < in.length(); + } + + /** + * Returns the next available character, or the null character '\0' if all + * input has been exhausted. The return value of this method is ambiguous + * for JSON strings that contain the character '\0'. + */ + public char next() { + return pos < in.length() ? in.charAt(pos++) : '\0'; + } + + /** + * Returns the next available character if it equals {@code c}. Otherwise an + * exception is thrown. + */ + public char next(char c) throws JSONException { + char result = next(); + if (result != c) { + throw syntaxError("Expected " + c + " but was " + result); + } + return result; + } + + /** + * Returns the next character that is not whitespace and does not belong to + * a comment. If the input is exhausted before such a character can be + * found, the null character '\0' is returned. The return value of this + * method is ambiguous for JSON strings that contain the character '\0'. + */ + public char nextClean() throws JSONException { + int nextCleanInt = nextCleanInternal(); + return nextCleanInt == -1 ? '\0' : (char) nextCleanInt; + } + + /** + * Returns the next {@code length} characters of the input. + * + *

The returned string shares its backing character array with this + * tokener's input string. If a reference to the returned string may be held + * indefinitely, you should use {@code new String(result)} to copy it first + * to avoid memory leaks. + * + * @throws JSONException if the remaining input is not long enough to + * satisfy this request. + */ + public String next(int length) throws JSONException { + if (pos + length > in.length()) { + throw syntaxError(length + " is out of bounds"); + } + String result = in.substring(pos, pos + length); + pos += length; + return result; + } + + /** + * Returns the {@link String#trim trimmed} string holding the characters up + * to but not including the first of: + *

    + *
  • any character in {@code excluded} + *
  • a newline character '\n' + *
  • a carriage return '\r' + *
+ * + *

The returned string shares its backing character array with this + * tokener's input string. If a reference to the returned string may be held + * indefinitely, you should use {@code new String(result)} to copy it first + * to avoid memory leaks. + * + * @return a possibly-empty string + */ + public String nextTo(String excluded) { + if (excluded == null) { + throw new NullPointerException("excluded == null"); + } + return nextToInternal(excluded).trim(); + } + + /** + * Equivalent to {@code nextTo(String.valueOf(excluded))}. + */ + public String nextTo(char excluded) { + return nextToInternal(String.valueOf(excluded)).trim(); + } + + /** + * Advances past all input up to and including the next occurrence of + * {@code thru}. If the remaining input doesn't contain {@code thru}, the + * input is exhausted. + */ + public void skipPast(String thru) { + int thruStart = in.indexOf(thru, pos); + pos = thruStart == -1 ? in.length() : (thruStart + thru.length()); + } + + /** + * Advances past all input up to but not including the next occurrence of + * {@code to}. If the remaining input doesn't contain {@code to}, the input + * is unchanged. + */ + public char skipTo(char to) { + int index = in.indexOf(to, pos); + if (index != -1) { + pos = index; + return to; + } else { + return '\0'; + } + } + + /** + * Unreads the most recent character of input. If no input characters have + * been read, the input is unchanged. + */ + public void back() { + if (--pos == -1) { + pos = 0; + } + } + + /** + * Returns the integer [0..15] value for the given hex character, or -1 + * for non-hex input. + * + * @param hex a character in the ranges [0-9], [A-F] or [a-f]. Any other + * character will yield a -1 result. + */ + public static int dehexchar(char hex) { + if (hex >= '0' && hex <= '9') { + return hex - '0'; + } else if (hex >= 'A' && hex <= 'F') { + return hex - 'A' + 10; + } else if (hex >= 'a' && hex <= 'f') { + return hex - 'a' + 10; + } else { + return -1; + } + } +} diff --git a/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/resources/base/element/string.json b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..2c8ad3d11f236e131865b498f009f25a742e7c59 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/Logger_harmony/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Logger_harmony" + } + ] +} diff --git a/002.Logger_OpenHarmony-master/code/build.gradle b/002.Logger_OpenHarmony-master/code/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..7f82a87bd3fe9820f6c52998dbd984648a912678 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/build.gradle @@ -0,0 +1,38 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 4 + } +} + +buildscript { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.4.2' + classpath 'com.huawei.ohos:decctest:1.2.4.0' + classpath 'com.huawei.ohos:hap:2.4.0.1' + } +} + +allprojects { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} diff --git a/002.Logger_OpenHarmony-master/code/entry/.gitignore b/002.Logger_OpenHarmony-master/code/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/.gitignore @@ -0,0 +1 @@ +/build diff --git a/002.Logger_OpenHarmony-master/code/entry/build.gradle b/002.Logger_OpenHarmony-master/code/entry/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..4c64d77add9ff66b3b0720d839e01594eb913748 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/build.gradle @@ -0,0 +1,16 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 4 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testCompile'junit:junit:4.12' + implementation project(":Logger_harmony") + implementation 'org.jetbrains:annotations:15.0' + +} diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/config.json b/002.Logger_OpenHarmony-master/code/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..f04813e5a19ddd360cae1d139b05880f1b7eee83 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/config.json @@ -0,0 +1,56 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 4, + "releaseType": "Beta1" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.myapplication", + "name": ".MyApplication", + "deviceType": [ + "phone", + "tv" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "com.example.myapplication.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:label_name", + "type": "page", + "launchType": "standard" + } + ], + "reqPermissions": [ + { + "name": "ohos.permission.READ_USER_STORAGE" + + } + ] + } +} \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MainAbility.java b/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..813ed4e7594dc5d3545f66e7f9ac76aab74be555 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MainAbility.java @@ -0,0 +1,13 @@ +package com.example.myapplication; + +import com.example.myapplication.slice.MainAbilitySlice; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MyApplication.java b/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MyApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..160bab2d67eba94b79d7e5f76b1c0d98208e0c1b --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MyApplication.java @@ -0,0 +1,20 @@ +package com.example.myapplication; + +import com.example.logger_harmony.BuildConfig; +import com.example.logger_harmony.HarmonyOsLogAdapter; +import com.example.logger_harmony.Logger; +import ohos.aafwk.ability.AbilityPackage; + +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + + Logger.addLogAdapter(new HarmonyOsLogAdapter() { + @Override + public boolean isLoggable(int priority, @org.jetbrains.annotations.Nullable String tag) { + return BuildConfig.DEBUG; + } + }); + } +} diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/slice/MainAbilitySlice.java b/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..dd829a0d49c80cba5723050f35358517815e9106 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/slice/MainAbilitySlice.java @@ -0,0 +1,79 @@ +package com.example.myapplication.slice; + +import com.example.logger_harmony.*; +import com.example.myapplication.ResourceTable; +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.components.Text; +import ohos.app.Context; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +public class MainAbilitySlice extends AbilitySlice { + Context context; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_main); + context = this; + Text text = (Text) findComponentById(ResourceTable.Id_text_helloworld); + + text.setClickedListener(new Component.ClickedListener() { + @Override + public void onClick(Component component) { + + try { + Logger.i("需要打印的日志信息"); +// Logger.i("需要打印的日志信息"); +// Logger.t("tag标签").i("需要打印的日志信息"); +// Logger.json("{\"key\": 3, \"value\": something}"); + +// List list = new ArrayList<>(); +// for (int i = 0; i < 5; i++) { +// list.add(i); +// } +// Logger.i(Arrays.asList(list)); + +// FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() +// .showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true +// .methodCount(0) // (Optional) How many method line to show. Default 2 +// .methodOffset(7) // (Optional) Hides internal method calls up to offset. Default 5 +// .logStrategy(new LogcatLogStrategy()) // (Optional) Changes the log strategy to print out. Default LogCat +// .tag("My custom tag") // (Optional) Global tag for every log. Default PRETTY_LOGGER +// .build(); +// +// Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy)); +// Logger.addLogAdapter(new DiskLogAdapter(context)); + + +// Logger.i(Arrays.asList(list)); + +// Map map = new HashMap<>(); +// map.put("key", "value"); +// map.put("key1", "value2"); + +// Logger.d(map); +// HiLog.info(label,"info"); +// HiLog.error(label,"error"); +// HiLog.fatal(label,"fatal"); +// HiLog.warn(label,"warn"); + + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } +} diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..915bc65a5cd104e1a936085e2c66e0a1a1b4a2d6 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + }, + { + "name": "mainability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "label_name", + "value": "MyApplication" + } + ] +} \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0c0a3df480fa387a452b9c40ca191cc918a3fc0 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..264aab6dabe3cedb809d47cfa3b0dfc1a3d5b56a --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/media/icon.png b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/002.Logger_OpenHarmony-master/code/entry/src/main/resources/base/media/icon.png differ diff --git a/002.Logger_OpenHarmony-master/code/entry/src/test/java/com/example/myapplication/ExampleTest.java b/002.Logger_OpenHarmony-master/code/entry/src/test/java/com/example/myapplication/ExampleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..160d520624e9b69a368ef2d9903f914e1be01474 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/entry/src/test/java/com/example/myapplication/ExampleTest.java @@ -0,0 +1,9 @@ +package com.example.myapplication; + +import org.junit.Test; + +public class ExampleTest { + @Test + public void onStart() { + } +} diff --git a/002.Logger_OpenHarmony-master/code/gradle.properties b/002.Logger_OpenHarmony-master/code/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..0daf1830fbdef07e50a44d74210c8c82f1b66278 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/gradle.properties @@ -0,0 +1,10 @@ +# Project-wide Gradle settings. +# IDE (e.g. DevEco Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# If the Chinese output is garbled, please configure the following parameter. +# org.gradle.jvmargs=-Dfile.encoding=GBK diff --git a/002.Logger_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.jar b/002.Logger_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9 Binary files /dev/null and b/002.Logger_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.jar differ diff --git a/002.Logger_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.properties b/002.Logger_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..6623300bebd011bc5f7991f4f9c389e2f67b14ac --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/002.Logger_OpenHarmony-master/code/gradlew b/002.Logger_OpenHarmony-master/code/gradlew new file mode 100644 index 0000000000000000000000000000000000000000..2fe81a7d95e4f9ad2c9b2a046707d36ceb3980b3 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/002.Logger_OpenHarmony-master/code/gradlew.bat b/002.Logger_OpenHarmony-master/code/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..62bd9b9ccefea2b65ae41e5d9a545e2021b90a1d --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/002.Logger_OpenHarmony-master/code/settings.gradle b/002.Logger_OpenHarmony-master/code/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..82c96cd30ac07fc52ca421a9be7b554a02cc44f9 --- /dev/null +++ b/002.Logger_OpenHarmony-master/code/settings.gradle @@ -0,0 +1 @@ +include ':entry', ':Logger_harmony' diff --git "a/002.Logger_OpenHarmony-master/doc/002\345\237\272\344\272\216\351\270\277\350\222\231\347\263\273\347\273\237\347\232\204Logger\345\274\200\345\217\221\346\214\207\345\215\227.docx" "b/002.Logger_OpenHarmony-master/doc/002\345\237\272\344\272\216\351\270\277\350\222\231\347\263\273\347\273\237\347\232\204Logger\345\274\200\345\217\221\346\214\207\345\215\227.docx" new file mode 100644 index 0000000000000000000000000000000000000000..ad8e8651274c15a0717a0548c5f16757214e237f Binary files /dev/null and "b/002.Logger_OpenHarmony-master/doc/002\345\237\272\344\272\216\351\270\277\350\222\231\347\263\273\347\273\237\347\232\204Logger\345\274\200\345\217\221\346\214\207\345\215\227.docx" differ diff --git a/003.Active_OpenHarmony-master/code/.gitignore b/003.Active_OpenHarmony-master/code/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..603b14077394cd2294ac6922fe619669630ef3ab --- /dev/null +++ b/003.Active_OpenHarmony-master/code/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/003.Active_OpenHarmony-master/code/.idea/.gitignore b/003.Active_OpenHarmony-master/code/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/003.Active_OpenHarmony-master/code/.idea/compiler.xml b/003.Active_OpenHarmony-master/code/.idea/compiler.xml new file mode 100644 index 0000000000000000000000000000000000000000..61a9130cd9669c3843e6445dfe1fee2d493869bc --- /dev/null +++ b/003.Active_OpenHarmony-master/code/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/.idea/gradle.xml b/003.Active_OpenHarmony-master/code/.idea/gradle.xml new file mode 100644 index 0000000000000000000000000000000000000000..f0b6549e50dad37933cc5898dc35391764feb555 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/.idea/gradle.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/.idea/jarRepositories.xml b/003.Active_OpenHarmony-master/code/.idea/jarRepositories.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba2e7443424bc5abb3b2c16dd9751cfceb69faed --- /dev/null +++ b/003.Active_OpenHarmony-master/code/.idea/jarRepositories.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/.idea/misc.xml b/003.Active_OpenHarmony-master/code/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..f43837a9d879322d3f3c732d212a3e507d555196 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/build.gradle b/003.Active_OpenHarmony-master/code/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..becc5f7f724a94c358eb4619c7c42c80aadbd2fa --- /dev/null +++ b/003.Active_OpenHarmony-master/code/build.gradle @@ -0,0 +1,36 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } +} + +buildscript { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.2.5' + } +} + +allprojects { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} diff --git a/003.Active_OpenHarmony-master/code/entry/.gitignore b/003.Active_OpenHarmony-master/code/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/.gitignore @@ -0,0 +1 @@ +/build diff --git a/003.Active_OpenHarmony-master/code/entry/build.gradle b/003.Active_OpenHarmony-master/code/entry/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..eb0e5c839fcabef970d330af3644e9012304154f --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } + compileOptions{ + annotationEnabled true + } + +} + +dependencies { + + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testCompile'junit:junit:4.12' + compile files( + "./libs/javapoet_java.jar", + "./libs/orm_annotations_java.jar", + "./libs/orm_annotations_processor_java.jar") + annotationProcessor files( + "./libs/javapoet_java.jar", + "./libs/orm_annotations_java.jar", + "./libs/orm_annotations_processor_java.jar") +} diff --git a/003.Active_OpenHarmony-master/code/entry/libs/javapoet_java.jar b/003.Active_OpenHarmony-master/code/entry/libs/javapoet_java.jar new file mode 100644 index 0000000000000000000000000000000000000000..00c9f224929bc94ae190331df3bead74bc223a62 Binary files /dev/null and b/003.Active_OpenHarmony-master/code/entry/libs/javapoet_java.jar differ diff --git a/003.Active_OpenHarmony-master/code/entry/libs/orm_annotations_java.jar b/003.Active_OpenHarmony-master/code/entry/libs/orm_annotations_java.jar new file mode 100644 index 0000000000000000000000000000000000000000..77f4815a5deba557bf6aa9efe5838bdf8c570800 Binary files /dev/null and b/003.Active_OpenHarmony-master/code/entry/libs/orm_annotations_java.jar differ diff --git a/003.Active_OpenHarmony-master/code/entry/libs/orm_annotations_processor_java.jar b/003.Active_OpenHarmony-master/code/entry/libs/orm_annotations_processor_java.jar new file mode 100644 index 0000000000000000000000000000000000000000..bbfd41bbb81b6f26827a4b88ea9b4b8f929be67a Binary files /dev/null and b/003.Active_OpenHarmony-master/code/entry/libs/orm_annotations_processor_java.jar differ diff --git a/003.Active_OpenHarmony-master/code/entry/libs/sqlitelibrary-debug.har b/003.Active_OpenHarmony-master/code/entry/libs/sqlitelibrary-debug.har new file mode 100644 index 0000000000000000000000000000000000000000..3ee22eb9fdf1718a3451ea1e699e1beba905f210 Binary files /dev/null and b/003.Active_OpenHarmony-master/code/entry/libs/sqlitelibrary-debug.har differ diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/config.json b/003.Active_OpenHarmony-master/code/entry/src/main/config.json new file mode 100644 index 0000000000000000000000000000000000000000..099e70eab45d713710ff06f869eb53da5e892c52 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/config.json @@ -0,0 +1,49 @@ +{ + "app": { + "bundleName": "com.example.myapplication", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 3, + "target": 4, + "releaseType": "Beta1" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.myapplication", + "name": ".MyApplication", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "com.example.myapplication.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:app_name", + "type": "page", + "launchType": "standard" + } + ] + } +} \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/BookStore.java b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/BookStore.java new file mode 100644 index 0000000000000000000000000000000000000000..7cc48315fd4953d884abfc46a4acd54907415df5 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/BookStore.java @@ -0,0 +1,8 @@ +package com.example.myapplication; + +import ohos.data.orm.OrmDatabase; +import ohos.data.orm.annotation.Database; + +@Database(entities = {User.class}, version = 1) +public abstract class BookStore extends OrmDatabase { +} diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MainAbility.java b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..813ed4e7594dc5d3545f66e7f9ac76aab74be555 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MainAbility.java @@ -0,0 +1,13 @@ +package com.example.myapplication; + +import com.example.myapplication.slice.MainAbilitySlice; +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MyApplication.java b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MyApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..33915e2cc691b0fa169fd0a13e2262ac3925bafd --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/MyApplication.java @@ -0,0 +1,10 @@ +package com.example.myapplication; + +import ohos.aafwk.ability.AbilityPackage; + +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/User.java b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/User.java new file mode 100644 index 0000000000000000000000000000000000000000..fe727d20f95931ccac600ddf313f7c499161c600 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/User.java @@ -0,0 +1,79 @@ +package com.example.myapplication; + +import ohos.data.orm.OrmObject; +import ohos.data.orm.annotation.Entity; +import ohos.data.orm.annotation.Index; +import ohos.data.orm.annotation.PrimaryKey; + + +@Entity(tableName = "user", ignoredColumns = {"ignoreColumn1", "ignoreColumn2"}, + indices = {@Index(value = {"firstName", "lastName"}, name = "name_index", unique = true)}) +public class User extends OrmObject { + // 此处将userId设为了自增的主键。注意只有在数据类型为包装类型时,自增主键才能生效。 + @PrimaryKey(autoGenerate = true) + private Integer userId; + private String firstName; + private String lastName; + private int age; + private double balance; + private int ignoreColumn1; + private int ignoreColumn2; + + // 开发者自行添加字段的getter和setter 方法。 + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } + + public int getIgnoreColumn1() { + return ignoreColumn1; + } + + public void setIgnoreColumn1(int ignoreColumn1) { + this.ignoreColumn1 = ignoreColumn1; + } + + public int getIgnoreColumn2() { + return ignoreColumn2; + } + + public void setIgnoreColumn2(int ignoreColumn2) { + this.ignoreColumn2 = ignoreColumn2; + } +} \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/slice/MainAbilitySlice.java b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..c12ce5030e4c65102b35e8525c959fdc12b944dd --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/java/com/example/myapplication/slice/MainAbilitySlice.java @@ -0,0 +1,119 @@ +package com.example.myapplication.slice; + +import com.example.myapplication.BookStore; +import com.example.myapplication.ResourceTable; +import com.example.myapplication.User; +import com.example.sqlitelibrary.DBManage; +import com.example.sqlitelibrary.DBOrmContext; +import com.example.sqlitelibrary.utils.Log; +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Button; +import ohos.agp.components.Component; +import ohos.agp.components.Text; +import ohos.data.DatabaseHelper; +import ohos.data.orm.OrmContext; +import ohos.data.orm.OrmPredicates; +import ohos.data.rdb.RdbStore; +import ohos.data.rdb.ValuesBucket; + +import java.util.ArrayList; +import java.util.List; + +public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener { + + private DatabaseHelper helper; + private RdbStore store; + private OrmContext context; + private Text textResult; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_main); + helper = new DatabaseHelper(this); + DBManage dbManger = new DBManage("user.db","user"); + context = dbManger.getConnectionContext(helper, BookStore.class); +// DBManage dbManger = new DBManage("user.db"); +// store = dbManger.getConnectionStore(helper,"user"); + Button btnInsert = (Button) findComponentById(ResourceTable.Id_btn_insert); + Button btnQuery = (Button) findComponentById(ResourceTable.Id_btn_query); + Button btnDelete = (Button) findComponentById(ResourceTable.Id_btn_delete); + Button btnUpdate = (Button) findComponentById(ResourceTable.Id_btn_update); + textResult = (Text) findComponentById(ResourceTable.Id_text); + btnInsert.setClickedListener(this::onClick); + btnQuery.setClickedListener(this::onClick); + btnDelete.setClickedListener(this::onClick); + btnUpdate.setClickedListener(this::onClick); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } + + @Override + public void onClick(Component component) { +// RdbStoreManage rdbStoreMange = new RdbStoreManage(); +// ValuesBucket values = new ValuesBucket(); +// values.putInteger("id", 1); +// values.putString("name", "zhangsan"); +// values.putInteger("age", 18); +// values.putDouble("salary", 100.5); +// values.putByteArray("blobType", new byte[] {1, 2, 3}); +// rdbStoreMange.setSql(store, "insert into user values(zhangsan, 18, 100.5, byte[1,2,3])"); +// long id = rdbStoreMange.insert(store,"user", values); +// System.out.println(id); + + + DBOrmContext dbOrmContext = new DBOrmContext(); + switch (component.getId()) { + case ResourceTable.Id_btn_insert: //插入数据 + //第一次使用user对应的表的时候,如果有这张表就直接使用,没有就创建表 + User user = new User(); + user.setFirstName("Zhang"); + user.setLastName("San"); + user.setAge(29); + user.setBalance(100.51); + boolean b = dbOrmContext.insert(context, user); + System.out.println("插入成功 "+b); + textResult.setText(user.getFirstName()+" "+user.getLastName()+" "+user.getAge()+" "+user.getBalance()); + break; + case ResourceTable.Id_btn_query: //条件查询 + List users = new ArrayList<>(); + OrmPredicates query = context.where(User.class).equalTo("lastName", "San"); + users = dbOrmContext.query(context, query); + System.out.println("查询 "+users.size()); + for (User user1 : users) { + textResult.setText(user1.getFirstName()+" "+user1.getLastName()+" "+user1.getAge()+" "+user1.getBalance() +"\n"); + } + + break; + case ResourceTable.Id_btn_delete: //条件删除 + OrmPredicates delete = context.where(User.class).equalTo("lastName", "San"); + int delete1 = dbOrmContext.delete(context, delete); + System.out.println("删除成功 "+delete1); + textResult.setText("删除成功"); + break; + case ResourceTable.Id_btn_update: //条件更新 + ValuesBucket valuesBucket = new ValuesBucket(); + valuesBucket.putInteger("age", 31); + valuesBucket.putString("firstName", "Zhang"); + valuesBucket.putString("lastName", "San"); + valuesBucket.putDouble("balance", 300.51); + OrmPredicates update = context.where(User.class).equalTo("userId", 1); + int update1 = dbOrmContext.update(context, valuesBucket, update); + System.out.println("更新成功 "+update1); + textResult.setText(valuesBucket.getString("firstName")+" "+valuesBucket.getString("lastName")+" "+valuesBucket.getInteger("age")+" "+valuesBucket.getDouble("balance")); + break; + } + + dbOrmContext.flush(context); + + } +} diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json b/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..929389e237a263eebc2e130fc06c892bd59404ef --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + }, + { + "name": "mainability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "dataability_description", + "value": "hap sample empty provider" + } + ] +} \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml b/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0c0a3df480fa387a452b9c40ca191cc918a3fc0 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml b/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..cc455eed2c426aa1f01aed388cce957c3a3e9f94 --- /dev/null +++ b/003.Active_OpenHarmony-master/code/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,54 @@ + + + +