├── .gitignore ├── LICENSE.txt ├── README.kor.md ├── README.md ├── build.gradle ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── item_diagram.png ├── settings.gradle └── src ├── main └── java │ └── com │ └── bhyoo │ └── onedrive │ ├── client │ ├── Client.java │ ├── RequestTool.java │ └── auth │ │ ├── AbstractAuthHelper.java │ │ ├── AuthHelper.java │ │ ├── AuthServer.java │ │ └── AuthenticationInfo.java │ ├── container │ ├── AsyncJobMonitor.java │ ├── AsyncJobStatus.java │ ├── DriveType.java │ ├── Identity.java │ ├── IdentitySet.java │ ├── ItemActionSet.java │ ├── ItemActivity.java │ ├── action │ │ ├── CommentAction.java │ │ ├── DeleteAction.java │ │ ├── MentionAction.java │ │ ├── MoveAction.java │ │ ├── RenameAction.java │ │ ├── ShareAction.java │ │ └── VersionAction.java │ ├── facet │ │ ├── AudioFacet.java │ │ ├── DriveState.java │ │ ├── FileFacet.java │ │ ├── FileSystemInfoFacet.java │ │ ├── FolderFacet.java │ │ ├── FolderViewFacet.java │ │ ├── ImageFacet.java │ │ ├── LocationFacet.java │ │ ├── PackageFacet.java │ │ ├── PackageType.java │ │ ├── PhotoFacet.java │ │ ├── RemoteItemFacet.java │ │ ├── SearchResultFacet.java │ │ ├── SharePointIdsFacet.java │ │ ├── ShareScopeType.java │ │ ├── SharedFacet.java │ │ ├── SortOrderType.java │ │ ├── SortType.java │ │ ├── SpecialFolderFacet.java │ │ ├── Thumbnail.java │ │ ├── ThumbnailSet.java │ │ ├── VideoFacet.java │ │ └── ViewType.java │ ├── items │ │ ├── AbstractBaseItem.java │ │ ├── AbstractDriveItem.java │ │ ├── AbstractRemoteItem.java │ │ ├── BaseItem.java │ │ ├── DefaultFileItem.java │ │ ├── DefaultFolderItem.java │ │ ├── DefaultPackageItem.java │ │ ├── Drive.java │ │ ├── DriveItem.java │ │ ├── FileItem.java │ │ ├── FolderItem.java │ │ ├── ItemReference.java │ │ ├── PackageItem.java │ │ ├── RemoteFileItem.java │ │ ├── RemoteFolderItem.java │ │ ├── RemoteItem.java │ │ └── pointer │ │ │ ├── BasePointer.java │ │ │ ├── IdPointer.java │ │ │ ├── Operator.java │ │ │ └── PathPointer.java │ └── pager │ │ ├── AbstractPager.java │ │ ├── DriveItemPager.java │ │ └── DrivePager.java │ ├── exceptions │ ├── ErrorResponseException.java │ ├── InternalException.java │ ├── InvalidJsonException.java │ ├── OneDriveSDKException.java │ └── OneDriveServerException.java │ ├── network │ ├── ErrorResponse.java │ ├── UploadSession.java │ ├── async │ │ ├── AbstractClient.java │ │ ├── AsyncClient.java │ │ ├── AsyncClientHandler.java │ │ ├── AsyncDefaultInitializer.java │ │ ├── AsyncDownloadClient.java │ │ ├── AsyncDownloadHandler.java │ │ ├── AsyncUploadClient.java │ │ ├── AsyncUploadHandler.java │ │ ├── DefaultDownloadPromise.java │ │ ├── DefaultDriveItemPromise.java │ │ ├── DefaultResponsePromise.java │ │ ├── DefaultUploadPromise.java │ │ ├── DownloadFuture.java │ │ ├── DownloadFutureListener.java │ │ ├── DownloadPromise.java │ │ ├── DriveItemFuture.java │ │ ├── DriveItemHandler.java │ │ ├── DriveItemPromise.java │ │ ├── ResponseFuture.java │ │ ├── ResponseFutureListener.java │ │ ├── ResponsePromise.java │ │ ├── UploadFuture.java │ │ └── UploadPromise.java │ └── sync │ │ ├── SyncRequest.java │ │ └── SyncResponse.java │ └── utils │ └── ByteBufStream.java └── test ├── java └── com │ └── bhyoo │ └── onedrive │ ├── ClientTest.java │ ├── RequestToolTest.java │ ├── TestCases.java │ ├── container │ └── items │ │ └── pointer │ │ └── PathPointerTest.java │ ├── network │ └── sync │ │ └── SyncRequestTest.java │ └── utils │ └── ByteBufStreamTest.java └── resources └── SampleAudio_0.7mb.mp3 /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ### Gradle template 3 | .gradle 4 | /build/ 5 | 6 | # Ignore Gradle GUI config 7 | gradle-app.setting 8 | 9 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 10 | !gradle-wrapper.jar 11 | 12 | # Cache of project 13 | .gradletasknamecache 14 | 15 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 16 | # gradle/wrapper/gradle-wrapper.properties 17 | ### Java template 18 | # Compiled class file 19 | *.class 20 | 21 | # Log file 22 | *.log 23 | 24 | # BlueJ files 25 | *.ctxt 26 | 27 | # Mobile Tools for Java (J2ME) 28 | .mtj.tmp/ 29 | 30 | # Package Files # 31 | *.jar 32 | *.war 33 | *.ear 34 | *.zip 35 | *.tar.gz 36 | *.rar 37 | 38 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 39 | hs_err_pid* 40 | ### JetBrains template 41 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 42 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 43 | 44 | # User-specific stuff: 45 | .idea/**/workspace.xml 46 | .idea/**/tasks.xml 47 | .idea/dictionaries 48 | .idea/ 49 | 50 | # Sensitive or high-churn files: 51 | .idea/**/dataSources/ 52 | .idea/**/dataSources.ids 53 | .idea/**/dataSources.xml 54 | .idea/**/dataSources.local.xml 55 | .idea/**/sqlDataSources.xml 56 | .idea/**/dynamic.xml 57 | .idea/**/uiDesigner.xml 58 | 59 | # Gradle: 60 | .idea/**/gradle.xml 61 | .idea/**/libraries 62 | 63 | # CMake 64 | cmake-build-debug/ 65 | 66 | # Mongo Explorer plugin: 67 | .idea/**/mongoSettings.xml 68 | 69 | ## File-based project format: 70 | *.iws 71 | 72 | ## Plugin-specific files: 73 | 74 | # IntelliJ 75 | out/ 76 | 77 | # mpeltonen/sbt-idea plugin 78 | .idea_modules/ 79 | 80 | # JIRA plugin 81 | atlassian-ide-plugin.xml 82 | 83 | # Cursive Clojure plugin 84 | .idea/replstate.xml 85 | 86 | # Crashlytics plugin (for Android Studio and IntelliJ) 87 | com_crashlytics_export_strings.xml 88 | crashlytics.properties 89 | crashlytics-build.properties 90 | fabric.properties 91 | ### Windows template 92 | # Windows thumbnail cache files 93 | Thumbs.db 94 | ehthumbs.db 95 | ehthumbs_vista.db 96 | 97 | # Dump file 98 | *.stackdump 99 | 100 | # Folder config file 101 | [Dd]esktop.ini 102 | 103 | # Recycle Bin used on file shares 104 | $RECYCLE.BIN/ 105 | 106 | # Windows Installer files 107 | *.cab 108 | *.msi 109 | *.msm 110 | *.msp 111 | 112 | # Windows shortcuts 113 | *.lnk 114 | ### Linux template 115 | *~ 116 | 117 | # temporary files which can be created if a process still has a handle open of a deleted file 118 | .fuse_hidden* 119 | 120 | # KDE directory preferences 121 | .directory 122 | 123 | # Linux trash folder which might appear on any partition or disk 124 | .Trash-* 125 | 126 | # .nfs files are created when an open file is removed but is still being accessed 127 | .nfs* 128 | 129 | # lombok config 130 | lombok.config -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Byeonghoon Yoo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-library' 3 | id 'idea' 4 | id 'com.google.osdetector' version '1.6.2' 5 | id 'io.freefair.lombok' version '3.8.4' 6 | id 'maven-publish' 7 | } 8 | 9 | group 'org.onedrive' 10 | version '0.10.2' 11 | 12 | compileJava { 13 | sourceCompatibility = 1.7 14 | targetCompatibility = 1.7 15 | } 16 | 17 | compileTestJava { 18 | sourceCompatibility = 1.8 19 | targetCompatibility = 1.8 20 | } 21 | 22 | repositories { 23 | jcenter() 24 | } 25 | 26 | ext { 27 | nettyVer = '4.1.38.Final' 28 | jacksonVer = '2.10.0.pr1' 29 | } 30 | 31 | dependencies { 32 | implementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVer" 33 | implementation "com.fasterxml.jackson.core:jackson-core:$jacksonVer" 34 | 35 | api "io.netty:netty-buffer:$nettyVer" 36 | api "io.netty:netty-codec:$nettyVer" 37 | api "io.netty:netty-codec-http:$nettyVer" 38 | api "io.netty:netty-common:$nettyVer" 39 | api "io.netty:netty-handler:$nettyVer" 40 | api "io.netty:netty-resolver:$nettyVer" 41 | api "io.netty:netty-transport:$nettyVer" 42 | 43 | 44 | if (osdetector.os == 'linux') { 45 | implementation "io.netty:netty-transport-native-epoll:4.+:${osdetector.classifier}" 46 | } 47 | else if (osdetector.os == 'osx' || osdetector.os.endsWith('bsd')) { 48 | implementation "io.netty:netty-transport-native-kqueue:4.+:${osdetector.classifier}" 49 | } 50 | 51 | api 'org.jetbrains:annotations:+' 52 | 53 | testCompile "com.fasterxml.jackson.core:jackson-databind:$jacksonVer" 54 | testCompile 'org.junit.jupiter:junit-jupiter-api:5.+' 55 | testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.+' 56 | } 57 | 58 | test { 59 | useJUnitPlatform() 60 | } 61 | 62 | javadoc { 63 | if (JavaVersion.current() >= JavaVersion.VERSION_1_9) { 64 | options.addBooleanOption('html5').setValue(true) 65 | } 66 | } 67 | 68 | task sourcesJar(type: Jar) { 69 | archiveClassifier = 'sources' 70 | from sourceSets.main.allJava 71 | } 72 | 73 | task javadocJar(type: Jar) { 74 | archiveClassifier = 'javadoc' 75 | from javadoc.destinationDir 76 | } 77 | 78 | artifacts { 79 | archives jar 80 | archives sourcesJar 81 | archives javadocJar 82 | } 83 | 84 | publishing { 85 | publications { 86 | myLibrary(MavenPublication) { 87 | from components.java 88 | 89 | artifact sourcesJar 90 | artifact javadocJar 91 | } 92 | } 93 | 94 | repositories { 95 | maven { 96 | name = 'myRepo' 97 | url = "file://${buildDir}/repo" 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Aug 05 16:40:14 KST 2019 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /item_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isac322/OneDrive-SDK-java/3d517b4661f88101d4024662747ab44584a75372/item_diagram.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'onedrive-sdk-java' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/client/auth/AbstractAuthHelper.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.client.auth; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public interface AbstractAuthHelper { 7 | @NotNull String refreshLogin(); 8 | 9 | void logout(); 10 | 11 | void login(); 12 | 13 | @JsonIgnore boolean isExpired(); 14 | 15 | @JsonIgnore boolean isLogin(); 16 | 17 | @JsonIgnore @NotNull String getTokenType(); 18 | 19 | @JsonIgnore @NotNull String getAccessToken(); 20 | 21 | @JsonIgnore @NotNull String getRefreshToken(); 22 | 23 | @JsonIgnore @NotNull String getAuthCode(); 24 | 25 | @JsonIgnore @NotNull String[] getScopes(); 26 | 27 | @JsonIgnore @NotNull String getClientId(); 28 | 29 | @JsonIgnore @NotNull String getClientSecret(); 30 | 31 | @JsonIgnore @NotNull String getRedirectURL(); 32 | 33 | @JsonIgnore long getExpirationTime(); 34 | 35 | @JsonIgnore @NotNull String getFullToken(); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/client/auth/AuthServer.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.client.auth; 2 | 3 | import com.bhyoo.onedrive.exceptions.InternalException; 4 | import com.sun.net.httpserver.HttpExchange; 5 | import com.sun.net.httpserver.HttpHandler; 6 | import com.sun.net.httpserver.HttpServer; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.io.OutputStream; 11 | import java.net.InetSocketAddress; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.concurrent.Semaphore; 14 | 15 | // TODO: add javadoc 16 | 17 | /** 18 | * @author isac322 19 | */ 20 | final class AuthServer { 21 | private final Semaphore authLock; 22 | private HttpServer server = null; 23 | private String authCode; 24 | 25 | 26 | // TODO: flexible port and address. 27 | public AuthServer(Semaphore authLock) { 28 | this.authLock = authLock; 29 | 30 | try { 31 | authLock.acquire(); 32 | } 33 | catch (InterruptedException e) { 34 | throw new InternalException("Lock error in AuthServer constructor.", e); 35 | } 36 | 37 | try { 38 | server = HttpServer.create(new InetSocketAddress("localhost", 8080), 0); 39 | server.createContext("/", new AuthHandler()); 40 | server.setExecutor(null); 41 | } 42 | catch (IOException e) { 43 | e.printStackTrace(); 44 | // FIXME: custom exception 45 | } 46 | } 47 | 48 | public void start() { 49 | if (server != null) server.start(); 50 | } 51 | 52 | @Nullable 53 | public String close() { 54 | if (server != null) { 55 | server.stop(0); 56 | return authCode; 57 | } 58 | return null; 59 | } 60 | 61 | private class AuthHandler implements HttpHandler { 62 | @Override 63 | public void handle(HttpExchange httpExchange) throws IOException { 64 | byte[] response = 65 | "".getBytes(StandardCharsets.UTF_8); 66 | httpExchange.sendResponseHeaders(200, response.length); 67 | OutputStream os = httpExchange.getResponseBody(); 68 | os.write(response); 69 | os.close(); 70 | 71 | String[] query = httpExchange.getRequestURI().getQuery().split("="); 72 | 73 | switch (query[0]) { 74 | case "code": 75 | authCode = query[1]; 76 | break; 77 | case "error": 78 | // FIXME: custom exception 79 | throw new IOException("Wrong Login Info"); 80 | default: 81 | // FIXME: custom exception 82 | throw new IOException("Unrecognized OneDrive Server Error"); 83 | } 84 | 85 | authLock.release(); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/client/auth/AuthenticationInfo.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.client.auth; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.util.logging.Logger; 12 | 13 | 14 | /** 15 | * @author isac322 16 | */ 17 | public class AuthenticationInfo { 18 | @Getter @JsonProperty("token_type") protected @NotNull String tokenType; 19 | @Getter @JsonProperty("expires_in") protected long expiresIn; 20 | @Getter @JsonProperty("access_token") protected @NotNull String accessToken; 21 | @Getter @JsonProperty("refresh_token") protected @NotNull String refreshToken; 22 | @Getter protected String scope; 23 | 24 | public AuthenticationInfo(@NotNull String tokenType, long expiresIn, @NotNull String accessToken, 25 | @NotNull String refreshToken, @NotNull String scope) { 26 | this.tokenType = tokenType; 27 | this.expiresIn = expiresIn; 28 | this.accessToken = accessToken; 29 | this.refreshToken = refreshToken; 30 | this.scope = scope; 31 | } 32 | 33 | public static @NotNull AuthenticationInfo deserialize(@NotNull JsonParser parser, boolean autoClose) 34 | throws IOException { 35 | @Nullable String tokenType = null; 36 | @Nullable Long expiresIn = null; 37 | @Nullable String accessToken = null; 38 | @Nullable String refreshToken = null; 39 | @Nullable String scope = null; 40 | 41 | while (parser.nextToken() != JsonToken.END_OBJECT) { 42 | String currentName = parser.getCurrentName(); 43 | parser.nextToken(); 44 | 45 | switch (currentName) { 46 | case "token_type": 47 | tokenType = parser.getText(); 48 | break; 49 | case "expires_in": 50 | expiresIn = parser.getLongValue() * 1000 + System.currentTimeMillis(); 51 | break; 52 | case "access_token": 53 | accessToken = parser.getText(); 54 | break; 55 | case "refresh_token": 56 | refreshToken = parser.getText(); 57 | break; 58 | case "scope": 59 | scope = parser.getText(); 60 | break; 61 | case "ext_expires_in": 62 | // TODO 63 | break; 64 | default: 65 | Logger.getGlobal().info("Unknown attribute detected in AuthenticationInfo : " + currentName); 66 | } 67 | } 68 | 69 | if (autoClose) parser.close(); 70 | 71 | assert tokenType != null : "tokenType is null"; 72 | assert expiresIn != null : "expiresIn is null"; 73 | assert accessToken != null : "accessToken is null"; 74 | assert refreshToken != null : "refreshToken is null"; 75 | assert scope != null : "scope is null"; 76 | 77 | return new AuthenticationInfo(tokenType, expiresIn, accessToken, refreshToken, scope); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/AsyncJobMonitor.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import com.bhyoo.onedrive.network.sync.SyncRequest; 5 | import com.bhyoo.onedrive.network.sync.SyncResponse; 6 | import com.fasterxml.jackson.core.JsonParser; 7 | import com.fasterxml.jackson.core.JsonToken; 8 | import lombok.Getter; 9 | import lombok.SneakyThrows; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | import java.io.IOException; 14 | import java.net.MalformedURLException; 15 | import java.net.URL; 16 | import java.util.logging.Logger; 17 | 18 | import static io.netty.handler.codec.http.HttpHeaderNames.ACCEPT; 19 | import static io.netty.handler.codec.http.HttpHeaderNames.ACCEPT_ENCODING; 20 | import static io.netty.handler.codec.http.HttpHeaderValues.APPLICATION_JSON; 21 | import static io.netty.handler.codec.http.HttpHeaderValues.GZIP; 22 | 23 | /** 24 | * Official doc 25 | */ 26 | public class AsyncJobMonitor { 27 | protected @NotNull String url; 28 | @Getter protected @NotNull String operation; 29 | @Getter protected @Nullable String resourceId; 30 | @Getter protected @NotNull Double percentageComplete; 31 | @Getter protected @NotNull AsyncJobStatus status; 32 | @Getter protected @NotNull String statusDescription; 33 | 34 | 35 | public AsyncJobMonitor(@NotNull String url) { 36 | this.url = url; 37 | 38 | update(); 39 | } 40 | 41 | @SneakyThrows(MalformedURLException.class) 42 | public AsyncJobMonitor update() { 43 | SyncResponse response = new SyncRequest(new URL(this.url)) 44 | .setHeader(ACCEPT, APPLICATION_JSON) 45 | .setHeader(ACCEPT_ENCODING, GZIP) 46 | .doGet(); 47 | 48 | // TODO: error handling 49 | 50 | try { 51 | JsonParser parser = RequestTool.jsonFactory.createParser(response.getContent()); 52 | parser.nextToken(); 53 | 54 | while (parser.nextToken() != JsonToken.END_OBJECT) { 55 | String currentName = parser.getCurrentName(); 56 | parser.nextToken(); 57 | 58 | switch (currentName) { 59 | case "operation": 60 | operation = parser.getText(); 61 | break; 62 | case "resourceId": 63 | resourceId = parser.getText(); 64 | break; 65 | case "percentageComplete": 66 | percentageComplete = parser.getDoubleValue(); 67 | break; 68 | case "status": 69 | status = AsyncJobStatus.deserialize(parser.getText()); 70 | break; 71 | case "statusDescription": 72 | statusDescription = parser.getText(); 73 | break; 74 | case "@odata.context": 75 | // TODO 76 | break; 77 | default: 78 | Logger.getGlobal().info("Unknown attribute detected in AsyncJobMonitor : " + currentName); 79 | } 80 | } 81 | 82 | return this; 83 | } 84 | catch (IOException e) { 85 | // FIXME: custom exception 86 | throw new RuntimeException("DEV: Unrecognizable json response.", e); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/AsyncJobStatus.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum AsyncJobStatus { 6 | NOT_STARTED("notStarted"), 7 | IN_PROGRESS("inProgress"), 8 | COMPLETED("completed"), 9 | UPDATING("updating"), 10 | FAILED("failed"), 11 | DELETE_PENDING("deletePending"), 12 | DELETE_FAILED("deleteFailed"), 13 | WAITING("waiting"); 14 | 15 | private final String type; 16 | 17 | AsyncJobStatus(String type) {this.type = type;} 18 | 19 | public static AsyncJobStatus deserialize(@NotNull String type) { 20 | switch (type) { 21 | case "notStarted": 22 | return NOT_STARTED; 23 | case "inProgress": 24 | return IN_PROGRESS; 25 | case "completed": 26 | return COMPLETED; 27 | case "updating": 28 | return UPDATING; 29 | case "failed": 30 | return FAILED; 31 | case "deletePending": 32 | return DELETE_PENDING; 33 | case "deleteFailed": 34 | return DELETE_FAILED; 35 | case "waiting": 36 | return WAITING; 37 | default: 38 | throw new IllegalStateException("Unknown attribute detected in AsyncJobStatus : " + type); 39 | } 40 | } 41 | 42 | @Override public String toString() {return type;} 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/DriveType.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum DriveType { 6 | PERSONAL("personal"), 7 | BUSINESS("business"), 8 | DOCUMENT_LIBRARY("documentLibrary"); 9 | 10 | private final String type; 11 | 12 | DriveType(String type) {this.type = type;} 13 | 14 | public static DriveType deserialize(@NotNull String type) { 15 | switch (type) { 16 | case "personal": 17 | return PERSONAL; 18 | case "business": 19 | return BUSINESS; 20 | case "documentLibrary": 21 | return DOCUMENT_LIBRARY; 22 | default: 23 | throw new IllegalStateException("Unknown attribute detected in DriveType : " + type); 24 | } 25 | } 26 | 27 | @Override public String toString() {return type;} 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/Identity.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import com.bhyoo.onedrive.container.facet.ThumbnailSet; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.Getter; 8 | import lombok.ToString; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.io.IOException; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | import java.util.logging.Logger; 15 | 16 | /** 17 | * https://dev.onedrive.com/resources/identitySet.htm 18 | * 19 | * @author isac322 20 | */ 21 | @EqualsAndHashCode(of = "id") 22 | @ToString(exclude = "thumbnails", doNotUseGetters = true) 23 | public class Identity { 24 | private static final ConcurrentHashMap identitySet = new ConcurrentHashMap<>(); 25 | 26 | @Getter protected final @Nullable String displayName; 27 | @Getter protected final @Nullable String email; 28 | @Getter protected final @Nullable String id; 29 | @Getter protected final @Nullable ThumbnailSet thumbnails; 30 | 31 | 32 | protected Identity(@Nullable String displayName, @Nullable String email, 33 | @Nullable String id, @Nullable ThumbnailSet thumbnails) { 34 | this.displayName = displayName; 35 | this.email = email; 36 | this.id = id; 37 | this.thumbnails = thumbnails; 38 | } 39 | 40 | static Identity deserialize(@NotNull JsonParser parser) throws IOException { 41 | @Nullable String displayName = null; 42 | @Nullable String email = null; 43 | @Nullable String id = null; 44 | @Nullable ThumbnailSet thumbnails = null; 45 | 46 | while (parser.nextToken() != JsonToken.END_OBJECT) { 47 | String currentName = parser.getCurrentName(); 48 | parser.nextToken(); 49 | 50 | switch (currentName) { 51 | case "displayName": 52 | displayName = parser.getText(); 53 | break; 54 | case "email": 55 | email = parser.getText(); 56 | break; 57 | case "id": 58 | id = parser.getText(); 59 | break; 60 | case "thumbnails": 61 | thumbnails = ThumbnailSet.deserialize(parser); 62 | break; 63 | default: 64 | Logger.getGlobal().info("Unknown attribute detected in Identity : " + currentName); 65 | } 66 | } 67 | 68 | if (id != null) { 69 | Identity identity = identitySet.get(id); 70 | 71 | Identity value = new Identity(displayName, email, id, thumbnails); 72 | 73 | // FIXME: merge two objects into a bigger object if possible 74 | if (identity != null && identity.countNull() <= value.countNull()) return identity; 75 | 76 | return identitySet.put(id, value); 77 | } 78 | else { 79 | return new Identity(displayName, email, null, thumbnails); 80 | } 81 | } 82 | 83 | private int countNull() { 84 | return (displayName == null ? 1 : 0) + (email == null ? 1 : 0) + 85 | (id == null ? 1 : 0) + (thumbnails == null ? 1 : 0); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/IdentitySet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.io.IOException; 12 | import java.util.ArrayList; 13 | 14 | /** 15 | * https://dev.onedrive.com/resources/identitySet.htm 16 | * 17 | * @author isac322 18 | */ 19 | @ToString(doNotUseGetters = true) 20 | @EqualsAndHashCode 21 | public class IdentitySet { 22 | @Getter protected @Nullable Identity user; 23 | @Getter protected @Nullable Identity application; 24 | @Getter protected @Nullable Identity device; 25 | @Getter protected @Nullable Identity organization; 26 | @Getter protected @NotNull Identity[] extraIdentity; 27 | 28 | protected IdentitySet(@Nullable Identity user, @Nullable Identity application, 29 | @Nullable Identity device, @Nullable Identity organization, 30 | @NotNull Identity[] extraIdentity) { 31 | this.user = user; 32 | this.application = application; 33 | this.device = device; 34 | this.organization = organization; 35 | this.extraIdentity = extraIdentity; 36 | } 37 | 38 | public static IdentitySet deserialize(@NotNull JsonParser parser) throws IOException { 39 | @Nullable Identity user = null; 40 | @Nullable Identity application = null; 41 | @Nullable Identity device = null; 42 | @Nullable Identity organization = null; 43 | ArrayList extraIdentities = new ArrayList<>(); 44 | 45 | while (parser.nextToken() != JsonToken.END_OBJECT) { 46 | String currentName = parser.getCurrentName(); 47 | parser.nextToken(); 48 | 49 | switch (currentName) { 50 | case "user": 51 | user = Identity.deserialize(parser); 52 | break; 53 | case "application": 54 | application = Identity.deserialize(parser); 55 | break; 56 | case "device": 57 | device = Identity.deserialize(parser); 58 | break; 59 | case "organization": 60 | organization = Identity.deserialize(parser); 61 | break; 62 | default: 63 | try { 64 | Identity extra = Identity.deserialize(parser); 65 | extraIdentities.add(extra); 66 | break; 67 | } 68 | catch (IOException e) { 69 | throw new IllegalStateException("Unknown attribute detected in IdentitySet : " + currentName); 70 | } 71 | } 72 | } 73 | 74 | return new IdentitySet(user, application, device, organization, extraIdentities.toArray(new Identity[0])); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/ItemActionSet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import com.bhyoo.onedrive.container.action.*; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.util.logging.Logger; 12 | 13 | public class ItemActionSet { 14 | @Getter protected final @Nullable CommentAction comment; 15 | @Getter protected final boolean create; 16 | @Getter protected final @Nullable DeleteAction delete; 17 | @Getter protected final boolean edit; 18 | @Getter protected final @Nullable MentionAction mention; 19 | @Getter protected final @Nullable MoveAction move; 20 | @Getter protected final @Nullable RenameAction rename; 21 | @Getter protected final boolean restore; 22 | @Getter protected final @Nullable ShareAction share; 23 | @Getter protected final @Nullable VersionAction version; 24 | 25 | protected ItemActionSet(@Nullable CommentAction comment, boolean create, @Nullable DeleteAction delete, 26 | boolean edit, @Nullable MentionAction mention, @Nullable MoveAction move, 27 | @Nullable RenameAction rename, boolean restore, @Nullable ShareAction share, 28 | @Nullable VersionAction version) { 29 | this.comment = comment; 30 | this.create = create; 31 | this.delete = delete; 32 | this.edit = edit; 33 | this.mention = mention; 34 | this.move = move; 35 | this.rename = rename; 36 | this.restore = restore; 37 | this.share = share; 38 | this.version = version; 39 | } 40 | 41 | 42 | public static ItemActionSet deserialize(@NotNull JsonParser parser) throws IOException { 43 | @Nullable CommentAction comment = null; 44 | boolean create = false; 45 | @Nullable DeleteAction delete = null; 46 | boolean edit = false; 47 | @Nullable MentionAction mention = null; 48 | @Nullable MoveAction move = null; 49 | @Nullable RenameAction rename = null; 50 | boolean restore = false; 51 | @Nullable ShareAction share = null; 52 | @Nullable VersionAction version = null; 53 | 54 | while (parser.nextToken() != JsonToken.END_OBJECT) { 55 | String currentName = parser.getCurrentName(); 56 | parser.nextToken(); 57 | 58 | switch (currentName) { 59 | case "comment": 60 | comment = CommentAction.deserialize(parser); 61 | break; 62 | case "create": 63 | create = true; 64 | while (parser.nextToken() != JsonToken.END_OBJECT) { 65 | // TODO 66 | } 67 | break; 68 | case "delete": 69 | delete = DeleteAction.deserialize(parser); 70 | break; 71 | case "edit": 72 | edit = true; 73 | while (parser.nextToken() != JsonToken.END_OBJECT) { 74 | // TODO 75 | } 76 | break; 77 | case "mention": 78 | mention = MentionAction.deserialize(parser); 79 | break; 80 | case "move": 81 | move = MoveAction.deserialize(parser); 82 | break; 83 | case "rename": 84 | rename = RenameAction.deserialize(parser); 85 | break; 86 | case "restore": 87 | restore = true; 88 | while (parser.nextToken() != JsonToken.END_OBJECT) { 89 | // TODO 90 | } 91 | break; 92 | case "share": 93 | share = ShareAction.deserialize(parser); 94 | break; 95 | case "version": 96 | version = VersionAction.deserialize(parser); 97 | break; 98 | default: 99 | Logger.getGlobal().info("Unknown attribute detected in ItemActionSet : " + currentName); 100 | } 101 | } 102 | 103 | return new ItemActionSet(comment, create, delete, edit, mention, move, rename, restore, share, version); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/ItemActivity.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.items.AbstractDriveItem; 5 | import com.fasterxml.jackson.core.JsonParser; 6 | import com.fasterxml.jackson.core.JsonToken; 7 | import lombok.Getter; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.io.IOException; 11 | import java.util.logging.Logger; 12 | 13 | public class ItemActivity { 14 | @Getter protected final @NotNull String id; 15 | @Getter protected final @NotNull ItemActionSet action; 16 | @Getter protected final @NotNull IdentitySet actor; 17 | @Getter protected final @NotNull AbstractDriveItem driveItem; 18 | // TODO: @Getter @Setter(PRIVATE) protected @NotNull ListItem listItem; 19 | @Getter protected final @NotNull ItemActivityTimeSet times; 20 | 21 | protected ItemActivity(@NotNull String id, @NotNull ItemActionSet action, @NotNull IdentitySet actor, 22 | @NotNull AbstractDriveItem driveItem, @NotNull ItemActivityTimeSet times) { 23 | this.id = id; 24 | this.action = action; 25 | this.actor = actor; 26 | this.driveItem = driveItem; 27 | this.times = times; 28 | } 29 | 30 | 31 | @SuppressWarnings("ConstantConditions") 32 | public static ItemActivity deserialize(@NotNull Client client, @NotNull JsonParser parser) throws IOException { 33 | @NotNull String id = null; 34 | @NotNull ItemActionSet action = null; 35 | @NotNull IdentitySet actor = null; 36 | @NotNull AbstractDriveItem driveItem = null; 37 | @NotNull ItemActivityTimeSet times = null; 38 | 39 | while (parser.nextToken() != JsonToken.END_OBJECT) { 40 | String currentName = parser.getCurrentName(); 41 | parser.nextToken(); 42 | 43 | switch (currentName) { 44 | case "id": 45 | id = parser.getText(); 46 | break; 47 | case "action": 48 | action = ItemActionSet.deserialize(parser); 49 | break; 50 | case "actor": 51 | actor = IdentitySet.deserialize(parser); 52 | break; 53 | case "driveItem": 54 | driveItem = AbstractDriveItem.deserialize(client, parser, false); 55 | break; 56 | case "times": 57 | times = ItemActivityTimeSet.deserialize(parser); 58 | break; 59 | default: 60 | Logger.getGlobal().info("Unknown attribute detected in ItemActivity : " + currentName); 61 | } 62 | } 63 | 64 | return new ItemActivity(id, action, actor, driveItem, times); 65 | } 66 | 67 | protected static class ItemActivityTimeSet { 68 | public final @NotNull String observedDateTime, recordedDateTime; 69 | 70 | protected ItemActivityTimeSet(@NotNull String observedDateTime, @NotNull String recordedDateTime) { 71 | this.observedDateTime = observedDateTime; 72 | this.recordedDateTime = recordedDateTime; 73 | } 74 | 75 | @SuppressWarnings("ConstantConditions") 76 | public static ItemActivityTimeSet deserialize(@NotNull JsonParser parser) throws IOException { 77 | @NotNull String observedDateTime = null; 78 | @NotNull String recordedDateTime = null; 79 | 80 | while (parser.nextToken() != JsonToken.END_OBJECT) { 81 | String currentName = parser.getCurrentName(); 82 | parser.nextToken(); 83 | 84 | switch (currentName) { 85 | case "observedDateTime": 86 | observedDateTime = parser.getText(); 87 | break; 88 | case "recordedDateTime": 89 | recordedDateTime = parser.getText(); 90 | break; 91 | default: 92 | Logger.getGlobal().info( 93 | "Unknown attribute detected in ItemActivityTimeSet : " + currentName 94 | ); 95 | } 96 | } 97 | 98 | return new ItemActivityTimeSet(observedDateTime, recordedDateTime); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/CommentAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.bhyoo.onedrive.container.IdentitySet; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | public class CommentAction { 13 | @Getter protected final boolean isReply; 14 | @Getter protected final @NotNull IdentitySet parentAuthor; 15 | @Getter protected final @NotNull IdentitySet participants; 16 | 17 | protected CommentAction(boolean isReply, @NotNull IdentitySet parentAuthor, @NotNull IdentitySet participants) { 18 | this.isReply = isReply; 19 | this.parentAuthor = parentAuthor; 20 | this.participants = participants; 21 | } 22 | 23 | 24 | @SuppressWarnings("ConstantConditions") 25 | public static @NotNull CommentAction deserialize(@NotNull JsonParser parser) throws IOException { 26 | @NotNull Boolean isReply = null; 27 | @NotNull IdentitySet parentAuthor = null; 28 | @NotNull IdentitySet participants = null; 29 | 30 | while (parser.nextToken() != JsonToken.END_OBJECT) { 31 | String currentName = parser.getCurrentName(); 32 | parser.nextToken(); 33 | 34 | switch (currentName) { 35 | case "isReply": 36 | isReply = parser.getBooleanValue(); 37 | break; 38 | case "parentAuthor": 39 | parentAuthor = IdentitySet.deserialize(parser); 40 | break; 41 | case "participants": 42 | participants = IdentitySet.deserialize(parser); 43 | break; 44 | default: 45 | Logger.getGlobal().info("Unknown attribute detected in CommentAction : " + currentName); 46 | } 47 | } 48 | 49 | return new CommentAction(isReply, parentAuthor, participants); 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/DeleteAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.io.IOException; 9 | import java.util.logging.Logger; 10 | 11 | public class DeleteAction { 12 | @Getter protected final @NotNull String name; 13 | 14 | protected DeleteAction(@NotNull String name) {this.name = name;} 15 | 16 | @SuppressWarnings("ConstantConditions") 17 | public static @NotNull DeleteAction deserialize(@NotNull JsonParser parser) throws IOException { 18 | @NotNull String name = null; 19 | 20 | while (parser.nextToken() != JsonToken.END_OBJECT) { 21 | String currentName = parser.getCurrentName(); 22 | parser.nextToken(); 23 | 24 | switch (currentName) { 25 | case "name": 26 | name = parser.getText(); 27 | break; 28 | default: 29 | Logger.getGlobal().info("Unknown attribute detected in DeleteAction : " + currentName); 30 | } 31 | } 32 | 33 | return new DeleteAction(name); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/MentionAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.bhyoo.onedrive.container.IdentitySet; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | public class MentionAction { 13 | @Getter protected final @NotNull IdentitySet mentionees; 14 | 15 | protected MentionAction(@NotNull IdentitySet mentionees) {this.mentionees = mentionees;} 16 | 17 | @SuppressWarnings("ConstantConditions") 18 | public static @NotNull MentionAction deserialize(@NotNull JsonParser parser) throws IOException { 19 | @NotNull IdentitySet mentionees = null; 20 | 21 | while (parser.nextToken() != JsonToken.END_OBJECT) { 22 | String currentName = parser.getCurrentName(); 23 | parser.nextToken(); 24 | 25 | switch (currentName) { 26 | case "mentionees": 27 | mentionees = IdentitySet.deserialize(parser); 28 | break; 29 | default: 30 | Logger.getGlobal().info("Unknown attribute detected in MentionAction : " + currentName); 31 | } 32 | } 33 | 34 | return new MentionAction(mentionees); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/MoveAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | // TODO: add pointer (PathPointer) 13 | public class MoveAction { 14 | @Getter protected final @NotNull String from; 15 | @Getter protected final @NotNull String to; 16 | 17 | protected MoveAction(@NotNull String from, @NotNull String to) { 18 | this.from = from; 19 | this.to = to; 20 | } 21 | 22 | public static @NotNull MoveAction deserialize(@NotNull JsonParser parser) throws IOException { 23 | @Nullable String from = null; 24 | @Nullable String to = null; 25 | 26 | while (parser.nextToken() != JsonToken.END_OBJECT) { 27 | String currentName = parser.getCurrentName(); 28 | parser.nextToken(); 29 | 30 | switch (currentName) { 31 | case "from": 32 | from = parser.getText(); 33 | break; 34 | case "to": 35 | to = parser.getText(); 36 | break; 37 | default: 38 | Logger.getGlobal().info("Unknown attribute detected in MoveAction : " + currentName); 39 | } 40 | } 41 | 42 | assert from != null : "from is null"; 43 | assert to != null : "to is null"; 44 | 45 | return new MoveAction(from, to); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/RenameAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.io.IOException; 9 | import java.util.logging.Logger; 10 | 11 | public class RenameAction { 12 | @Getter protected final @NotNull String oldName; 13 | 14 | protected RenameAction(@NotNull String oldName) {this.oldName = oldName;} 15 | 16 | @SuppressWarnings("ConstantConditions") 17 | public static @NotNull RenameAction deserialize(@NotNull JsonParser parser) throws IOException { 18 | @NotNull String oldName = null; 19 | 20 | while (parser.nextToken() != JsonToken.END_OBJECT) { 21 | String currentName = parser.getCurrentName(); 22 | parser.nextToken(); 23 | 24 | switch (currentName) { 25 | case "oldName": 26 | oldName = parser.getText(); 27 | break; 28 | default: 29 | Logger.getGlobal().info("Unknown attribute detected in RenameAction : " + currentName); 30 | } 31 | } 32 | 33 | return new RenameAction(oldName); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/ShareAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.bhyoo.onedrive.container.IdentitySet; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | public class ShareAction { 13 | @Getter protected final @NotNull IdentitySet recipients; 14 | 15 | protected ShareAction(@NotNull IdentitySet recipients) {this.recipients = recipients;} 16 | 17 | @SuppressWarnings("ConstantConditions") 18 | public static @NotNull ShareAction deserialize(@NotNull JsonParser parser) throws IOException { 19 | @NotNull IdentitySet recipients = null; 20 | 21 | while (parser.nextToken() != JsonToken.END_OBJECT) { 22 | String currentName = parser.getCurrentName(); 23 | parser.nextToken(); 24 | 25 | switch (currentName) { 26 | case "recipients": 27 | recipients = IdentitySet.deserialize(parser); 28 | break; 29 | default: 30 | Logger.getGlobal().info("Unknown attribute detected in ShareAction : " + currentName); 31 | } 32 | } 33 | 34 | return new ShareAction(recipients); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/action/VersionAction.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.action; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.io.IOException; 9 | import java.util.logging.Logger; 10 | 11 | public class VersionAction { 12 | @Getter protected final @NotNull String newVersion; 13 | 14 | protected VersionAction(@NotNull String newVersion) {this.newVersion = newVersion;} 15 | 16 | @SuppressWarnings("ConstantConditions") 17 | public static @NotNull VersionAction deserialize(@NotNull JsonParser parser) throws IOException { 18 | @NotNull String newVersion = null; 19 | 20 | while (parser.nextToken() != JsonToken.END_OBJECT) { 21 | String currentName = parser.getCurrentName(); 22 | parser.nextToken(); 23 | 24 | switch (currentName) { 25 | case "newVersion": 26 | newVersion = parser.getText(); 27 | break; 28 | default: 29 | Logger.getGlobal().info("Unknown attribute detected in VersionAction : " + currentName); 30 | } 31 | } 32 | 33 | return new VersionAction(newVersion); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/AudioFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/audio_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class AudioFacet { 18 | @Getter protected final @Nullable String album; 19 | @Getter protected final @Nullable String albumArtist; 20 | @Getter protected final @Nullable String artist; 21 | @Getter protected final @Nullable Integer bitrate; 22 | @Getter protected final @Nullable String composers; 23 | @Getter protected final @Nullable String copyright; 24 | @Getter protected final @Nullable Integer disc; 25 | @Getter protected final @Nullable Integer discCount; 26 | @Getter protected final @Nullable Long duration; 27 | @Getter protected final @Nullable String genre; 28 | @Getter protected final @Nullable Boolean hasDrm; 29 | @Getter protected final @Nullable Boolean isVariableBitrate; 30 | @Getter protected final @Nullable String title; 31 | @Getter protected final @Nullable Integer track; 32 | @Getter protected final @Nullable Integer trackCount; 33 | @Getter protected final @Nullable Integer year; 34 | 35 | 36 | protected AudioFacet(@Nullable String album, @Nullable String albumArtist, @Nullable String artist, 37 | @Nullable Integer bitrate, @Nullable String composers, @Nullable String copyright, 38 | @Nullable Integer disc, @Nullable Integer discCount, @Nullable Long duration, 39 | @Nullable String genre, @Nullable Boolean hasDrm, @Nullable Boolean isVariableBitrate, 40 | @Nullable String title, @Nullable Integer track, @Nullable Integer trackCount, 41 | @Nullable Integer year) { 42 | this.album = album; 43 | this.albumArtist = albumArtist; 44 | this.artist = artist; 45 | this.bitrate = bitrate; 46 | this.composers = composers; 47 | this.copyright = copyright; 48 | this.disc = disc; 49 | this.discCount = discCount; 50 | this.duration = duration; 51 | this.genre = genre; 52 | this.hasDrm = hasDrm; 53 | this.isVariableBitrate = isVariableBitrate; 54 | this.title = title; 55 | this.track = track; 56 | this.trackCount = trackCount; 57 | this.year = year; 58 | } 59 | 60 | public static AudioFacet deserialize(@NotNull JsonParser parser) throws IOException { 61 | @Nullable String album = null; 62 | @Nullable String albumArtist = null; 63 | @Nullable String artist = null; 64 | @Nullable Integer bitrate = null; 65 | @Nullable String composers = null; 66 | @Nullable String copyright = null; 67 | @Nullable Integer disc = null; 68 | @Nullable Integer discCount = null; 69 | @Nullable Long duration = null; 70 | @Nullable String genre = null; 71 | @Nullable Boolean hasDrm = null; 72 | @Nullable Boolean isVariableBitrate = null; 73 | @Nullable String title = null; 74 | @Nullable Integer track = null; 75 | @Nullable Integer trackCount = null; 76 | @Nullable Integer year = null; 77 | 78 | while (parser.nextToken() != JsonToken.END_OBJECT) { 79 | String currentName = parser.getCurrentName(); 80 | parser.nextToken(); 81 | 82 | switch (currentName) { 83 | case "album": 84 | album = parser.getText(); 85 | break; 86 | case "albumArtist": 87 | albumArtist = parser.getText(); 88 | break; 89 | case "artist": 90 | artist = parser.getText(); 91 | break; 92 | case "bitrate": 93 | bitrate = parser.getIntValue(); 94 | break; 95 | case "composers": 96 | composers = parser.getText(); 97 | break; 98 | case "copyright": 99 | copyright = parser.getText(); 100 | break; 101 | case "disc": 102 | disc = parser.getIntValue(); 103 | break; 104 | case "discCount": 105 | discCount = parser.getIntValue(); 106 | break; 107 | case "duration": 108 | duration = parser.getLongValue(); 109 | break; 110 | case "genre": 111 | genre = parser.getText(); 112 | break; 113 | case "hasDrm": 114 | hasDrm = parser.getBooleanValue(); 115 | break; 116 | case "isVariableBitrate": 117 | isVariableBitrate = parser.getBooleanValue(); 118 | break; 119 | case "title": 120 | title = parser.getText(); 121 | break; 122 | case "track": 123 | track = parser.getIntValue(); 124 | break; 125 | case "trackCount": 126 | trackCount = parser.getIntValue(); 127 | break; 128 | case "year": 129 | year = parser.getIntValue(); 130 | break; 131 | default: 132 | Logger.getGlobal().info("Unknown attribute detected in AudioFacet : " + currentName); 133 | } 134 | } 135 | 136 | return new AudioFacet(album, albumArtist, artist, bitrate, composers, copyright, disc, discCount, duration, 137 | genre, hasDrm, isVariableBitrate, title, track, trackCount, year); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/DriveState.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum DriveState { 6 | NORMAL("normal"), 7 | NEARING("nearing"), 8 | CRITICAL("critical"), 9 | EXCEEDED("exceeded"); 10 | 11 | private final String type; 12 | 13 | DriveState(String type) {this.type = type;} 14 | 15 | public static DriveState deserialize(@NotNull String type) { 16 | switch (type) { 17 | case "normal": 18 | return NORMAL; 19 | case "nearing": 20 | return NEARING; 21 | case "critical": 22 | return CRITICAL; 23 | case "exceeded": 24 | return EXCEEDED; 25 | default: 26 | throw new IllegalStateException("Unknown attribute detected in ViewType : " + type); 27 | } 28 | } 29 | 30 | @Override public String toString() {return type;} 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/FileFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * https://dev.onedrive.com/facets/file_facet.htm 15 | * 16 | * @author isac322 17 | */ 18 | public class FileFacet { 19 | @Getter protected final @Nullable String mimeType; 20 | protected final @Nullable Hashes hashes; 21 | @Getter protected final @Nullable Boolean processingMetadata; 22 | 23 | protected FileFacet(@Nullable String mimeType, @Nullable Hashes hashes, @Nullable Boolean processingMetadata) { 24 | this.mimeType = mimeType; 25 | this.hashes = hashes; 26 | this.processingMetadata = processingMetadata; 27 | } 28 | 29 | public static FileFacet deserialize(@NotNull JsonParser parser) throws IOException { 30 | @Nullable String mimeType = null; 31 | @Nullable Hashes hashes = null; 32 | @Nullable Boolean processingMetadata = null; 33 | 34 | while (parser.nextToken() != JsonToken.END_OBJECT) { 35 | String currentName = parser.getCurrentName(); 36 | parser.nextToken(); 37 | 38 | switch (currentName) { 39 | case "mimeType": 40 | mimeType = parser.getText(); 41 | break; 42 | case "hashes": 43 | hashes = Hashes.deserialize(parser); 44 | break; 45 | case "processingMetadata": 46 | processingMetadata = parser.getBooleanValue(); 47 | break; 48 | default: 49 | Logger.getGlobal().info("Unknown attribute detected in FileFacet : " + currentName); 50 | } 51 | } 52 | 53 | return new FileFacet(mimeType, hashes, processingMetadata); 54 | } 55 | 56 | @JsonIgnore public @Nullable String getSha1Hash() {return hashes == null ? null : hashes.sha1Hash;} 57 | 58 | @JsonIgnore public @Nullable String getCrc32Hash() {return hashes == null ? null : hashes.crc32Hash;} 59 | 60 | @JsonIgnore public @Nullable String getQuickXorHash() {return hashes == null ? null : hashes.quickXorHash;} 61 | 62 | 63 | private static class Hashes { 64 | public String sha1Hash, crc32Hash, quickXorHash; 65 | 66 | static Hashes deserialize(@NotNull JsonParser parser) throws IOException { 67 | Hashes ret = new Hashes(); 68 | 69 | while (parser.nextToken() != JsonToken.END_OBJECT) { 70 | String currentName = parser.getCurrentName(); 71 | parser.nextToken(); 72 | 73 | switch (currentName) { 74 | case "sha1Hash": 75 | ret.sha1Hash = parser.getText(); 76 | break; 77 | case "crc32Hash": 78 | ret.crc32Hash = parser.getText(); 79 | break; 80 | case "quickXorHash": 81 | ret.quickXorHash = parser.getText(); 82 | break; 83 | default: 84 | Logger.getGlobal().info("Unknown attribute detected in Hashes : " + currentName); 85 | } 86 | } 87 | 88 | return ret; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/FileSystemInfoFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive 14 | * .com/facets/filesysteminfo_facet.htm 15 | * 16 | * @author isac322 17 | */ 18 | public class FileSystemInfoFacet { 19 | @Getter protected final @NotNull String createdDateTime; 20 | @Getter protected final @NotNull String lastModifiedDateTime; 21 | 22 | protected FileSystemInfoFacet(@NotNull String createdDateTime, @NotNull String lastModifiedDateTime) { 23 | this.createdDateTime = createdDateTime; 24 | this.lastModifiedDateTime = lastModifiedDateTime; 25 | } 26 | 27 | public static FileSystemInfoFacet deserialize(@NotNull JsonParser parser) throws IOException { 28 | @Nullable String createdDateTime = null; 29 | @Nullable String lastModifiedDateTime = null; 30 | 31 | while (parser.nextToken() != JsonToken.END_OBJECT) { 32 | String currentName = parser.getCurrentName(); 33 | parser.nextToken(); 34 | 35 | switch (currentName) { 36 | case "createdDateTime": 37 | createdDateTime = parser.getText(); 38 | break; 39 | case "lastModifiedDateTime": 40 | lastModifiedDateTime = parser.getText(); 41 | break; 42 | default: 43 | Logger.getGlobal().info("Unknown attribute detected in FileSystemInfoFacet : " + currentName); 44 | } 45 | } 46 | 47 | assert createdDateTime != null : "createdDateTime is null"; 48 | assert lastModifiedDateTime != null : "lastModifiedDateTime is null"; 49 | 50 | return new FileSystemInfoFacet(createdDateTime, lastModifiedDateTime); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/FolderFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * 14 | * https://docs.microsoft.com/ko-kr/onedrive/developer/rest-api/resources/folderview 15 | * 16 | * 17 | * @author isac322 18 | */ 19 | public class FolderFacet { 20 | @Getter protected final long childCount; 21 | // Nullable on onedrive for business 22 | @Getter protected final @Nullable FolderViewFacet view; 23 | 24 | protected FolderFacet(@NotNull Long childCount, @Nullable FolderViewFacet view) { 25 | this.childCount = childCount; 26 | this.view = view; 27 | } 28 | 29 | public static FolderFacet deserialize(@NotNull JsonParser parser) throws IOException { 30 | @Nullable Long childCount = null; 31 | @Nullable FolderViewFacet view = null; 32 | 33 | while (parser.nextToken() != JsonToken.END_OBJECT) { 34 | String currentName = parser.getCurrentName(); 35 | parser.nextToken(); 36 | 37 | switch (currentName) { 38 | case "childCount": 39 | childCount = parser.getLongValue(); 40 | break; 41 | case "view": 42 | view = FolderViewFacet.deserialize(parser); 43 | break; 44 | default: 45 | Logger.getGlobal().info("Unknown attribute detected in FolderFacet : " + currentName); 46 | } 47 | } 48 | 49 | assert childCount != null : "childCount is null"; 50 | 51 | return new FolderFacet(childCount, view); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/FolderViewFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/folder_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class FolderViewFacet { 18 | @Getter protected final @NotNull SortType sortBy; 19 | @Getter protected final @NotNull SortOrderType sortOrder; 20 | @Getter protected final @NotNull ViewType viewType; 21 | 22 | protected FolderViewFacet(@NotNull SortType sortBy, @NotNull SortOrderType sortOrder, @NotNull ViewType viewType) { 23 | this.sortBy = sortBy; 24 | this.sortOrder = sortOrder; 25 | this.viewType = viewType; 26 | } 27 | 28 | public static FolderViewFacet deserialize(@NotNull JsonParser parser) throws IOException { 29 | @Nullable SortType sortBy = null; 30 | @Nullable SortOrderType sortOrder = null; 31 | @Nullable ViewType viewType = null; 32 | 33 | while (parser.nextToken() != JsonToken.END_OBJECT) { 34 | String currentName = parser.getCurrentName(); 35 | parser.nextToken(); 36 | 37 | switch (currentName) { 38 | case "sortBy": 39 | sortBy = SortType.deserialize(parser.getText()); 40 | break; 41 | case "sortOrder": 42 | sortOrder = SortOrderType.deserialize(parser.getText()); 43 | break; 44 | case "viewType": 45 | viewType = ViewType.deserialize(parser.getText()); 46 | break; 47 | default: 48 | Logger.getGlobal().info("Unknown attribute detected in FolderViewFacet : " + currentName); 49 | } 50 | } 51 | 52 | assert sortBy != null : "sortBy is null"; 53 | assert sortOrder != null : "sortOrder is null"; 54 | assert viewType != null : "viewType is null"; 55 | 56 | return new FolderViewFacet(sortBy, sortOrder, viewType); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/ImageFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/image_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class ImageFacet { 18 | @Getter protected final int width; 19 | @Getter protected final int height; 20 | 21 | protected ImageFacet(@NotNull Integer width, @NotNull Integer height) { 22 | this.width = width; 23 | this.height = height; 24 | } 25 | 26 | public static ImageFacet deserialize(@NotNull JsonParser parser) throws IOException { 27 | @Nullable Integer width = null, height = null; 28 | 29 | while (parser.nextToken() != JsonToken.END_OBJECT) { 30 | String currentName = parser.getCurrentName(); 31 | parser.nextToken(); 32 | 33 | switch (currentName) { 34 | case "width": 35 | width = parser.getIntValue(); 36 | break; 37 | case "height": 38 | height = parser.getIntValue(); 39 | break; 40 | default: 41 | Logger.getGlobal().info("Unknown attribute detected in ImageFacet : " + currentName); 42 | } 43 | } 44 | 45 | assert width != null : "width is null"; 46 | assert height != null : "height is null"; 47 | 48 | return new ImageFacet(width, height); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/LocationFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/location_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class LocationFacet { 18 | @Getter protected final @Nullable Double altitude; 19 | @Getter protected final @Nullable Double latitude; 20 | @Getter protected final @Nullable Double longitude; 21 | 22 | protected LocationFacet(@Nullable Double altitude, @Nullable Double latitude, @Nullable Double longitude) { 23 | this.altitude = altitude; 24 | this.latitude = latitude; 25 | this.longitude = longitude; 26 | } 27 | 28 | public static LocationFacet deserialize(@NotNull JsonParser parser) throws IOException { 29 | @Nullable Double altitude = null; 30 | @Nullable Double latitude = null; 31 | @Nullable Double longitude = null; 32 | 33 | while (parser.nextToken() != JsonToken.END_OBJECT) { 34 | String currentName = parser.getCurrentName(); 35 | parser.nextToken(); 36 | 37 | switch (currentName) { 38 | case "altitude": 39 | altitude = parser.getDoubleValue(); 40 | break; 41 | case "latitude": 42 | latitude = parser.getDoubleValue(); 43 | break; 44 | case "longitude": 45 | longitude = parser.getDoubleValue(); 46 | break; 47 | default: 48 | Logger.getGlobal().info("Unknown attribute detected in LocationFacet : " + currentName); 49 | } 50 | } 51 | 52 | return new LocationFacet(altitude, latitude, longitude); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/PackageFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/package_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class PackageFacet { 18 | @Getter protected final @NotNull PackageType type; 19 | 20 | protected PackageFacet(@NotNull PackageType type) {this.type = type;} 21 | 22 | public static PackageFacet deserialize(@NotNull JsonParser parser) throws IOException { 23 | @Nullable PackageType type = null; 24 | 25 | while (parser.nextToken() != JsonToken.END_OBJECT) { 26 | String currentName = parser.getCurrentName(); 27 | parser.nextToken(); 28 | 29 | switch (currentName) { 30 | case "type": 31 | type = PackageType.deserialize(parser.getText()); 32 | break; 33 | default: 34 | Logger.getGlobal().info("Unknown attribute detected in PackageFacet : " + currentName); 35 | } 36 | } 37 | 38 | assert type != null : "type is null"; 39 | 40 | return new PackageFacet(type); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/PackageType.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | @SuppressWarnings("SameParameterValue") 6 | public enum PackageType { 7 | ONENOTE("oneNote"); 8 | 9 | private final String type; 10 | 11 | PackageType(String type) {this.type = type;} 12 | 13 | public static PackageType deserialize(@NotNull String type) { 14 | switch (type) { 15 | case "oneNote": 16 | return ONENOTE; 17 | default: 18 | throw new IllegalStateException("Unknown attribute detected in PackageType : " + type); 19 | } 20 | } 21 | 22 | @Override public String toString() {return type;} 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/PhotoFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/photo_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class PhotoFacet { 18 | @Getter protected final @Nullable String cameraMake; 19 | @Getter protected final @Nullable String cameraModel; 20 | @Getter protected final @Nullable Double exposureDenominator; 21 | @Getter protected final @Nullable Double exposureNumerator; 22 | @Getter protected final @Nullable Double fNumber; 23 | @Getter protected final @Nullable Double focalLength; 24 | @Getter protected final @Nullable Long iso; 25 | @Getter protected final @Nullable String takenDateTime; 26 | 27 | protected PhotoFacet(@Nullable String cameraMake, @Nullable String cameraModel, 28 | @Nullable Double exposureDenominator, @Nullable Double exposureNumerator, 29 | @Nullable Double fNumber, @Nullable Double focalLength, @Nullable Long iso, 30 | @Nullable String takenDateTime) { 31 | this.cameraMake = cameraMake; 32 | this.cameraModel = cameraModel; 33 | this.exposureDenominator = exposureDenominator; 34 | this.exposureNumerator = exposureNumerator; 35 | this.fNumber = fNumber; 36 | this.focalLength = focalLength; 37 | this.iso = iso; 38 | this.takenDateTime = takenDateTime; 39 | } 40 | 41 | public static PhotoFacet deserialize(@NotNull JsonParser parser) throws IOException { 42 | @Nullable String cameraMake = null; 43 | @Nullable String cameraModel = null; 44 | @Nullable Double exposureDenominator = null; 45 | @Nullable Double exposureNumerator = null; 46 | @Nullable Double fNumber = null; 47 | @Nullable Double focalLength = null; 48 | @Nullable Long iso = null; 49 | @Nullable String takenDateTime = null; 50 | 51 | while (parser.nextToken() != JsonToken.END_OBJECT) { 52 | String currentName = parser.getCurrentName(); 53 | parser.nextToken(); 54 | 55 | switch (currentName) { 56 | case "cameraMake": 57 | cameraMake = parser.getText(); 58 | break; 59 | case "cameraModel": 60 | cameraModel = parser.getText(); 61 | break; 62 | case "exposureDenominator": 63 | exposureDenominator = parser.getDoubleValue(); 64 | break; 65 | case "exposureNumerator": 66 | exposureNumerator = parser.getDoubleValue(); 67 | break; 68 | case "fNumber": 69 | fNumber = parser.getDoubleValue(); 70 | break; 71 | case "focalLength": 72 | focalLength = parser.getDoubleValue(); 73 | break; 74 | case "iso": 75 | iso = parser.getLongValue(); 76 | break; 77 | case "takenDateTime": 78 | takenDateTime = parser.getText(); 79 | break; 80 | default: 81 | Logger.getGlobal().info("Unknown attribute detected in PhotoFacet : " + currentName); 82 | } 83 | } 84 | 85 | return new PhotoFacet(cameraMake, cameraModel, exposureDenominator, 86 | exposureNumerator, fNumber, focalLength, iso, takenDateTime); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/SearchResultFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import lombok.SneakyThrows; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.net.URI; 12 | import java.net.URISyntaxException; 13 | import java.util.logging.Logger; 14 | 15 | /** 16 | * 17 | * https://dev.onedrive.com/facets/searchresult_facet.htm 18 | * 19 | * @author isac322 20 | */ 21 | public class SearchResultFacet { 22 | @Getter protected final @NotNull URI onClickTelemetryUrl; 23 | 24 | protected SearchResultFacet(@NotNull URI onClickTelemetryUrl) { 25 | this.onClickTelemetryUrl = onClickTelemetryUrl; 26 | } 27 | 28 | @SneakyThrows(URISyntaxException.class) 29 | public static SearchResultFacet deserialize(@NotNull JsonParser parser) throws IOException { 30 | @Nullable URI onClickTelemetryUrl = null; 31 | 32 | while (parser.nextToken() != JsonToken.END_OBJECT) { 33 | String currentName = parser.getCurrentName(); 34 | parser.nextToken(); 35 | 36 | if (currentName.equals("onClickTelemetryUrl")) { 37 | onClickTelemetryUrl = new URI(parser.getText()); 38 | } 39 | else { 40 | Logger.getGlobal().info("Unknown attribute detected in SearchResultFacet : " + currentName); 41 | } 42 | } 43 | 44 | assert onClickTelemetryUrl != null : "onClickTelemetryUrl is null"; 45 | 46 | return new SearchResultFacet(onClickTelemetryUrl); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/SharePointIdsFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import lombok.SneakyThrows; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.net.URI; 12 | import java.net.URISyntaxException; 13 | import java.util.logging.Logger; 14 | 15 | /** 16 | * https://dev.onedrive 17 | * .com/facets/sharepointIds_facet.htm 18 | * 19 | * @author isac322 20 | */ 21 | public class SharePointIdsFacet { 22 | @Getter protected final @Nullable String listId; 23 | @Getter protected final @Nullable String listItemId; 24 | @Getter protected final @Nullable String listItemUniqueId; 25 | @Getter protected final @Nullable String siteId; 26 | @Getter protected final @Nullable URI siteUrl; 27 | @Getter protected final @Nullable String webId; 28 | 29 | protected SharePointIdsFacet(@Nullable String listId, @Nullable String listItemId, 30 | @Nullable String listItemUniqueId, @Nullable String siteId, @Nullable URI siteUrl, 31 | @Nullable String webId) { 32 | this.listId = listId; 33 | this.listItemId = listItemId; 34 | this.listItemUniqueId = listItemUniqueId; 35 | this.siteId = siteId; 36 | this.siteUrl = siteUrl; 37 | this.webId = webId; 38 | } 39 | 40 | @SneakyThrows(URISyntaxException.class) 41 | public static SharePointIdsFacet deserialize(@NotNull JsonParser parser) throws IOException { 42 | @Nullable String listId = null; 43 | @Nullable String listItemId = null; 44 | @Nullable String listItemUniqueId = null; 45 | @Nullable String siteId = null; 46 | @Nullable URI siteUrl = null; 47 | @Nullable String webId = null; 48 | 49 | while (parser.nextToken() != JsonToken.END_OBJECT) { 50 | String currentName = parser.getCurrentName(); 51 | parser.nextToken(); 52 | 53 | switch (currentName) { 54 | case "listId": 55 | listId = parser.getText(); 56 | break; 57 | case "listItemId": 58 | listItemId = parser.getText(); 59 | break; 60 | case "listItemUniqueId": 61 | listItemUniqueId = parser.getText(); 62 | break; 63 | case "siteId": 64 | siteId = parser.getText(); 65 | break; 66 | case "siteUrl": 67 | siteUrl = new URI(parser.getText()); 68 | break; 69 | case "webId": 70 | webId = parser.getText(); 71 | break; 72 | default: 73 | Logger.getGlobal().info( 74 | "Unknown attribute detected in SharePointIdsFacet : " + currentName 75 | ); 76 | } 77 | } 78 | 79 | return new SharePointIdsFacet(listId, listItemId, listItemUniqueId, siteId, siteUrl, webId); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/ShareScopeType.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum ShareScopeType { 6 | ANONYMOUS("anonymous"), 7 | ORGANIZATION("organization"), 8 | USERS("users"); 9 | 10 | private final String type; 11 | 12 | ShareScopeType(String type) {this.type = type;} 13 | 14 | public static ShareScopeType deserialize(@NotNull String type) { 15 | switch (type) { 16 | case "anonymous": 17 | return ANONYMOUS; 18 | case "organization": 19 | return ORGANIZATION; 20 | case "users": 21 | return USERS; 22 | default: 23 | throw new IllegalStateException("Unknown attribute detected in ShareScopeType : " + type); 24 | } 25 | } 26 | 27 | @Override public String toString() {return type;} 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/SharedFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.bhyoo.onedrive.container.IdentitySet; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * https://dev.onedrive.com/facets/shared_facet.htm 15 | * 16 | * @author isac322 17 | */ 18 | public class SharedFacet { 19 | @Getter protected final @Nullable IdentitySet owner; 20 | @Getter protected final @Nullable ShareScopeType scope; 21 | @Getter protected final @Nullable IdentitySet sharedBy; 22 | @Getter protected final @Nullable String sharedDateTime; 23 | 24 | protected SharedFacet(@Nullable IdentitySet owner, @Nullable ShareScopeType scope, 25 | @Nullable IdentitySet sharedBy, @Nullable String sharedDateTime) { 26 | this.owner = owner; 27 | this.scope = scope; 28 | this.sharedBy = sharedBy; 29 | this.sharedDateTime = sharedDateTime; 30 | } 31 | 32 | public static SharedFacet deserialize(@NotNull JsonParser parser) throws IOException { 33 | @Nullable IdentitySet owner = null; 34 | @Nullable ShareScopeType scope = null; 35 | @Nullable IdentitySet sharedBy = null; 36 | @Nullable String sharedDateTime = null; 37 | 38 | while (parser.nextToken() != JsonToken.END_OBJECT) { 39 | String currentName = parser.getCurrentName(); 40 | parser.nextToken(); 41 | 42 | switch (currentName) { 43 | case "owner": 44 | owner = IdentitySet.deserialize(parser); 45 | break; 46 | case "scope": 47 | scope = ShareScopeType.deserialize(parser.getText()); 48 | break; 49 | case "sharedBy": 50 | sharedBy = IdentitySet.deserialize(parser); 51 | break; 52 | case "sharedDateTime": 53 | sharedDateTime = parser.getText(); 54 | break; 55 | default: 56 | Logger.getGlobal().info("Unknown attribute detected in SharedFacet : " + currentName); 57 | } 58 | } 59 | 60 | return new SharedFacet(owner, scope, sharedBy, sharedDateTime); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/SortOrderType.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum SortOrderType { 6 | ASCENDING("ascending"), 7 | DESCENDING("descending"); 8 | 9 | private final String type; 10 | 11 | SortOrderType(String type) {this.type = type;} 12 | 13 | public static SortOrderType deserialize(@NotNull String type) { 14 | switch (type) { 15 | case "ascending": 16 | return ASCENDING; 17 | case "descending": 18 | return DESCENDING; 19 | default: 20 | throw new IllegalStateException("Unknown attribute detected in SortOrderType : " + type); 21 | } 22 | } 23 | 24 | @Override public String toString() {return type;} 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/SortType.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum SortType { 6 | DEFAULT("default"), 7 | NAME("name"), 8 | TYPE("type"), 9 | SIZE("size"), 10 | TAKEN_OR_CREATED_DATETIME("takenOrCreatedDateTime"), 11 | LAST_MODIFIED_DATETIME("lastModifiedDateTime"), 12 | SEQUENCE("sequence"); 13 | 14 | private final String type; 15 | 16 | SortType(String type) {this.type = type;} 17 | 18 | public static SortType deserialize(@NotNull String type) { 19 | switch (type) { 20 | case "default": 21 | return DEFAULT; 22 | case "name": 23 | return NAME; 24 | case "type": 25 | return TYPE; 26 | case "size": 27 | return SIZE; 28 | case "takenOrCreatedDateTime": 29 | return TAKEN_OR_CREATED_DATETIME; 30 | case "lastModifiedDateTime": 31 | return LAST_MODIFIED_DATETIME; 32 | case "sequence": 33 | return SEQUENCE; 34 | default: 35 | throw new IllegalStateException("Unknown attribute detected in SortType : " + type); 36 | } 37 | } 38 | 39 | @Override public String toString() {return type;} 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/SpecialFolderFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | // TODO: merge with AbstractDriveItem if possible 13 | 14 | /** 15 | * https://dev.onedrive.com/facets/jumpinfo_facet.htm 16 | * 17 | * @author isac322 18 | */ 19 | public class SpecialFolderFacet { 20 | @Getter protected final @Nullable String name; 21 | 22 | protected SpecialFolderFacet(@Nullable String name) {this.name = name;} 23 | 24 | public static SpecialFolderFacet deserialize(@NotNull JsonParser parser) throws IOException { 25 | @Nullable String name = null; 26 | 27 | while (parser.nextToken() != JsonToken.END_OBJECT) { 28 | String currentName = parser.getCurrentName(); 29 | parser.nextToken(); 30 | 31 | switch (currentName) { 32 | case "name": 33 | name = parser.getText(); 34 | break; 35 | default: 36 | Logger.getGlobal().info( 37 | "Unknown attribute detected in SpecialFolderFacet : " + currentName 38 | ); 39 | } 40 | } 41 | 42 | return new SpecialFolderFacet(name); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/Thumbnail.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | public class Thumbnail { 13 | @Getter protected final int height; 14 | @Getter protected final @NotNull String url; 15 | @Getter protected final @Nullable String sourceItemId; 16 | @Getter protected final int width; 17 | 18 | Thumbnail(int height, @NotNull String url, @Nullable String sourceItemId, int width) { 19 | this.height = height; 20 | this.url = url; 21 | this.sourceItemId = sourceItemId; 22 | this.width = width; 23 | } 24 | 25 | public static @NotNull Thumbnail deserialize(@NotNull JsonParser parser) throws IOException { 26 | @Nullable Integer height = null; 27 | @Nullable String url = null; 28 | @Nullable String sourceItemId = null; 29 | @Nullable Integer width = null; 30 | 31 | while (parser.nextToken() != JsonToken.END_OBJECT) { 32 | String currentName = parser.getCurrentName(); 33 | parser.nextToken(); 34 | 35 | switch (currentName) { 36 | case "height": 37 | height = parser.getIntValue(); 38 | break; 39 | case "url": 40 | url = parser.getText(); 41 | break; 42 | case "sourceItemId": 43 | sourceItemId = parser.getText(); 44 | break; 45 | case "width": 46 | width = parser.getIntValue(); 47 | break; 48 | default: 49 | Logger.getGlobal().info("Unknown attribute detected in Thumbnail : " + currentName); 50 | } 51 | } 52 | 53 | assert height != null : "height is null"; 54 | assert url != null : "url is null"; 55 | assert width != null : "width is null"; 56 | 57 | return new Thumbnail(height, url, sourceItemId, width); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/ThumbnailSet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | public class ThumbnailSet { 13 | @Getter protected final @NotNull String id; 14 | @Getter protected final @Nullable Thumbnail large; 15 | @Getter protected final @Nullable Thumbnail medium; 16 | @Getter protected final @Nullable Thumbnail source; 17 | @Getter protected final @Nullable Thumbnail small; 18 | 19 | ThumbnailSet(@NotNull String id, @Nullable Thumbnail large, @Nullable Thumbnail medium, 20 | @Nullable Thumbnail source, @Nullable Thumbnail small) { 21 | this.id = id; 22 | this.large = large; 23 | this.medium = medium; 24 | this.source = source; 25 | this.small = small; 26 | } 27 | 28 | public static @NotNull ThumbnailSet deserialize(@NotNull JsonParser parser) throws IOException { 29 | @Nullable String id = null; 30 | @Nullable Thumbnail large = null; 31 | @Nullable Thumbnail medium = null; 32 | @Nullable Thumbnail source = null; 33 | @Nullable Thumbnail small = null; 34 | 35 | while (parser.nextToken() != JsonToken.END_OBJECT) { 36 | String currentName = parser.getCurrentName(); 37 | parser.nextToken(); 38 | 39 | switch (currentName) { 40 | case "id": 41 | id = parser.getText(); 42 | break; 43 | case "large": 44 | large = Thumbnail.deserialize(parser); 45 | break; 46 | case "medium": 47 | medium = Thumbnail.deserialize(parser); 48 | break; 49 | case "source": 50 | source = Thumbnail.deserialize(parser); 51 | break; 52 | case "small": 53 | small = Thumbnail.deserialize(parser); 54 | break; 55 | default: 56 | Logger.getGlobal().info("Unknown attribute detected in ThumbnailSet : " + currentName); 57 | } 58 | } 59 | 60 | assert id != null : "height is null"; 61 | 62 | return new ThumbnailSet(id, large, medium, source, small); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/VideoFacet.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * https://dev.onedrive.com/facets/video_facet.htm 14 | * 15 | * @author isac322 16 | */ 17 | public class VideoFacet { 18 | @Getter protected final int audioBitsPerSample; 19 | @Getter protected final int audioChannels; 20 | @Getter protected final @Nullable String audioFormat; 21 | @Getter protected final int audioSamplesPerSecond; 22 | @Getter protected final int bitrate; 23 | @Getter protected final long duration; 24 | @Getter protected final @Nullable String fourCC; 25 | @Getter protected final double frameRate; 26 | @Getter protected final long height; 27 | @Getter protected final long width; 28 | 29 | protected VideoFacet(@NotNull Integer audioBitsPerSample, @NotNull Integer audioChannels, 30 | @Nullable String audioFormat, @NotNull Integer audioSamplesPerSecond, 31 | @NotNull Integer bitrate, @NotNull Long duration, @Nullable String fourCC, 32 | @NotNull Double frameRate, @NotNull Long height, @NotNull Long width) { 33 | this.audioBitsPerSample = audioBitsPerSample; 34 | this.audioChannels = audioChannels; 35 | this.audioFormat = audioFormat; 36 | this.audioSamplesPerSecond = audioSamplesPerSecond; 37 | this.bitrate = bitrate; 38 | this.duration = duration; 39 | this.fourCC = fourCC; 40 | this.frameRate = frameRate; 41 | this.height = height; 42 | this.width = width; 43 | } 44 | 45 | public static VideoFacet deserialize(@NotNull JsonParser parser) throws IOException { 46 | @Nullable Integer audioBitsPerSample = null; 47 | @Nullable Integer audioChannels = null; 48 | @Nullable String audioFormat = null; 49 | @Nullable Integer audioSamplesPerSecond = null; 50 | @Nullable Integer bitrate = null; 51 | @Nullable Long duration = null; 52 | @Nullable String fourCC = null; 53 | @Nullable Double frameRate = null; 54 | @Nullable Long height = null; 55 | @Nullable Long width = null; 56 | 57 | while (parser.nextToken() != JsonToken.END_OBJECT) { 58 | String currentName = parser.getCurrentName(); 59 | parser.nextToken(); 60 | 61 | switch (currentName) { 62 | case "audioBitsPerSample": 63 | audioBitsPerSample = parser.getIntValue(); 64 | break; 65 | case "audioChannels": 66 | audioChannels = parser.getIntValue(); 67 | break; 68 | case "audioFormat": 69 | audioFormat = parser.getText(); 70 | break; 71 | case "audioSamplesPerSecond": 72 | audioSamplesPerSecond = parser.getIntValue(); 73 | break; 74 | case "bitrate": 75 | bitrate = parser.getIntValue(); 76 | break; 77 | case "duration": 78 | duration = parser.getLongValue(); 79 | break; 80 | case "fourCC": 81 | fourCC = parser.getText(); 82 | break; 83 | case "frameRate": 84 | frameRate = parser.getDoubleValue(); 85 | break; 86 | case "height": 87 | height = parser.getLongValue(); 88 | break; 89 | case "width": 90 | width = parser.getLongValue(); 91 | break; 92 | default: 93 | Logger.getGlobal().info("Unknown attribute detected in VideoFacet : " + currentName); 94 | } 95 | } 96 | 97 | assert audioBitsPerSample != null : "audioBitsPerSample is null"; 98 | assert audioChannels != null : "audioChannels is null"; 99 | assert audioSamplesPerSecond != null : "audioSamplesPerSecond is null"; 100 | assert bitrate != null : "bitrate is null"; 101 | assert duration != null : "duration is null"; 102 | assert frameRate != null : "frameRate is null"; 103 | assert height != null : "height is null"; 104 | assert width != null : "width is null"; 105 | 106 | return new VideoFacet(audioBitsPerSample, audioChannels, audioFormat, audioSamplesPerSecond, bitrate, duration, 107 | fourCC, frameRate, height, width); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/facet/ViewType.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.facet; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | public enum ViewType { 6 | DEFAULT("default"), 7 | ICONS("icons"), 8 | DETAILS("details"), 9 | THUMBNAILS("thumbnails"); 10 | 11 | private final String type; 12 | 13 | ViewType(String type) {this.type = type;} 14 | 15 | public static ViewType deserialize(@NotNull String type) { 16 | switch (type) { 17 | case "default": 18 | return DEFAULT; 19 | case "icons": 20 | return ICONS; 21 | case "details": 22 | return DETAILS; 23 | case "thumbnails": 24 | return THUMBNAILS; 25 | default: 26 | throw new IllegalStateException("Unknown attribute detected in ViewType : " + type); 27 | } 28 | } 29 | 30 | @Override public String toString() {return type;} 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/AbstractBaseItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.IdentitySet; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.net.URI; 11 | 12 | /** 13 | * @author isac322 14 | */ 15 | @EqualsAndHashCode(of = "id") 16 | @ToString(doNotUseGetters = true) 17 | abstract public class AbstractBaseItem implements BaseItem { 18 | @Getter(onMethod = @__(@Override)) protected @NotNull String id; 19 | 20 | // createdBy 21 | @Getter(onMethod = @__(@Override)) protected @Nullable IdentitySet creator; 22 | 23 | // TODO: convert datetime to some appreciate object 24 | @Getter(onMethod = @__(@Override)) protected @Nullable String createdDateTime; 25 | @Getter(onMethod = @__(@Override)) protected @Nullable String description; 26 | 27 | // eTag 28 | @Getter(onMethod = @__(@Override)) protected @Nullable String eTag; 29 | 30 | // lastModifiedBy 31 | @Getter(onMethod = @__(@Override)) protected @Nullable IdentitySet lastModifier; 32 | 33 | // TODO: convert datetime to some appreciate object 34 | @Getter(onMethod = @__(@Override)) protected @Nullable String lastModifiedDateTime; 35 | @Getter(onMethod = @__(@Override)) protected @Nullable String name; 36 | @Getter(onMethod = @__(@Override)) protected @Nullable URI webUrl; 37 | 38 | AbstractBaseItem(@NotNull String id, @Nullable IdentitySet creator, @Nullable String createdDateTime, 39 | @Nullable String description, @Nullable String eTag, @Nullable IdentitySet lastModifier, 40 | @Nullable String lastModifiedDateTime, @Nullable String name, @Nullable URI webUrl) { 41 | this.id = id; 42 | this.creator = creator; 43 | this.createdDateTime = createdDateTime; 44 | this.description = description; 45 | this.eTag = eTag; 46 | this.lastModifier = lastModifier; 47 | this.lastModifiedDateTime = lastModifiedDateTime; 48 | this.name = name; 49 | this.webUrl = webUrl; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/AbstractRemoteItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.facet.RemoteItemFacet; 5 | import com.bhyoo.onedrive.container.facet.SearchResultFacet; 6 | import com.bhyoo.onedrive.container.facet.SharePointIdsFacet; 7 | import com.bhyoo.onedrive.container.facet.SharedFacet; 8 | import com.bhyoo.onedrive.container.items.pointer.IdPointer; 9 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 10 | import lombok.Getter; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.net.URI; 15 | 16 | public abstract class AbstractRemoteItem extends AbstractDriveItem implements RemoteItem { 17 | @Getter(onMethod = @__(@Override)) protected @NotNull RemoteItemFacet remoteItem; 18 | @Getter(onMethod = @__(@Override)) protected @NotNull IdPointer remotePointer; 19 | 20 | AbstractRemoteItem(@NotNull String id, @NotNull String createdDateTime, @Nullable String description, 21 | @NotNull String eTag, @NotNull String lastModifiedDateTime, @NotNull String name, 22 | @NotNull URI webUrl, @NotNull Client client, @NotNull String cTag, @Nullable String deleted, 23 | @NotNull ItemReference parentReference, @Nullable SearchResultFacet searchResult, 24 | @Nullable SharedFacet shared, @Nullable SharePointIdsFacet sharePointIds, URI webDavUrl, 25 | @NotNull RemoteItemFacet remoteItem) { 26 | super(id, remoteItem.getCreator(), createdDateTime, description, eTag, remoteItem.getLastModifier(), 27 | lastModifiedDateTime, name, webUrl, client, cTag, deleted, remoteItem.getFileSystemInfo(), 28 | parentReference, searchResult, shared, sharePointIds, remoteItem.getSize(), webDavUrl); 29 | this.remoteItem = remoteItem; 30 | 31 | createPointers(); 32 | } 33 | 34 | @Override 35 | protected void createPointers() { 36 | if (parentReference.pathPointer != null) { 37 | assert name != null : "name is null"; 38 | this.pathPointer = parentReference.pathPointer.resolve(name); 39 | } 40 | this.idPointer = new IdPointer(id, parentReference.driveId); 41 | this.remotePointer = new IdPointer(remoteItem.getId(), remoteItem.getParentReference().driveId); 42 | } 43 | 44 | public @NotNull String getRemoteDriveID() {return remoteItem.getParentReference().driveId;} 45 | 46 | public @NotNull String getRemoteID() {return remoteItem.getId();} 47 | 48 | 49 | @Override public @NotNull DriveItem fetchRemoteItem() throws ErrorResponseException { 50 | return client.getItem(remotePointer); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/BaseItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.IdentitySet; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.net.URI; 7 | 8 | public interface BaseItem { 9 | @NotNull String getId(); 10 | 11 | @NotNull IdentitySet getCreator(); 12 | 13 | @NotNull String getCreatedDateTime(); 14 | 15 | @NotNull String getDescription(); 16 | 17 | @NotNull String getETag(); 18 | 19 | @NotNull IdentitySet getLastModifier(); 20 | 21 | @NotNull String getLastModifiedDateTime(); 22 | 23 | @NotNull String getName(); 24 | 25 | @NotNull URI getWebUrl(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/DefaultFileItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.IdentitySet; 5 | import com.bhyoo.onedrive.container.facet.*; 6 | import com.bhyoo.onedrive.network.async.DownloadFuture; 7 | import lombok.Getter; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.io.IOException; 12 | import java.net.URI; 13 | import java.nio.file.Path; 14 | import java.nio.file.Paths; 15 | 16 | /** 17 | * @author isac322 18 | */ 19 | public class DefaultFileItem extends AbstractDriveItem implements FileItem { 20 | @Getter(onMethod = @__(@Override)) protected @Nullable AudioFacet audio; 21 | protected @NotNull FileFacet file; 22 | @Getter(onMethod = @__(@Override)) protected @Nullable ImageFacet image; 23 | @Getter(onMethod = @__(@Override)) protected @Nullable LocationFacet location; 24 | @Getter(onMethod = @__(@Override)) protected @Nullable PhotoFacet photo; 25 | @Getter(onMethod = @__(@Override)) protected @Nullable VideoFacet video; 26 | 27 | 28 | DefaultFileItem(@NotNull String id, @NotNull IdentitySet creator, @NotNull String createdDateTime, 29 | @Nullable String description, @NotNull String eTag, @NotNull IdentitySet lastModifier, 30 | @NotNull String lastModifiedDateTime, @NotNull String name, @NotNull URI webUrl, 31 | @NotNull Client client, @NotNull String cTag, @Nullable String deleted, 32 | FileSystemInfoFacet fileSystemInfo, @NotNull ItemReference parentReference, 33 | @Nullable SearchResultFacet searchResult, @Nullable SharedFacet shared, 34 | @Nullable SharePointIdsFacet sharePointIds, @NotNull Long size, URI webDavUrl, 35 | @Nullable AudioFacet audio, @NotNull FileFacet file, @Nullable ImageFacet image, 36 | @Nullable LocationFacet location, @Nullable PhotoFacet photo, @Nullable VideoFacet video) { 37 | super(id, creator, createdDateTime, description, eTag, lastModifier, lastModifiedDateTime, name, webUrl, 38 | client, cTag, deleted, fileSystemInfo, parentReference, searchResult, shared, sharePointIds, size, 39 | webDavUrl); 40 | this.audio = audio; 41 | this.file = file; 42 | this.image = image; 43 | this.location = location; 44 | this.photo = photo; 45 | this.video = video; 46 | 47 | createPointers(); 48 | } 49 | 50 | @Override 51 | public void download(@NotNull String path) throws IOException { 52 | assert this.name != null : "this.name is null"; 53 | client.download(idPointer, Paths.get(path), this.name); 54 | } 55 | 56 | @Override 57 | public void download(@NotNull String path, @NotNull String newName) throws IOException { 58 | client.download(idPointer, Paths.get(path), newName); 59 | } 60 | 61 | @Override 62 | public void download(@NotNull Path folderPath) throws IOException { 63 | assert this.name != null : "this.name is null"; 64 | client.download(idPointer, folderPath, this.name); 65 | } 66 | 67 | // TODO: handling overwriting file 68 | 69 | @Override 70 | public void download(@NotNull Path folderPath, String newName) throws IOException { 71 | client.download(idPointer, folderPath, newName); 72 | } 73 | 74 | 75 | @Override 76 | public @NotNull DownloadFuture downloadAsync(@NotNull Path folderPath) throws IOException { 77 | return client.downloadAsync(idPointer, folderPath, this.name); 78 | } 79 | 80 | @Override 81 | public @NotNull DownloadFuture downloadAsync(@NotNull Path folderPath, String newName) throws IOException { 82 | return client.downloadAsync(idPointer, folderPath, newName); 83 | } 84 | 85 | 86 | @Override 87 | protected void refreshBy(@NotNull AbstractDriveItem newItem) { 88 | super.refreshBy(newItem); 89 | 90 | DefaultFileItem item = (DefaultFileItem) newItem; 91 | 92 | this.audio = item.audio; 93 | this.file = item.file; 94 | this.image = item.image; 95 | this.location = item.location; 96 | this.photo = item.photo; 97 | this.video = item.video; 98 | } 99 | 100 | 101 | 102 | /* 103 | ************************************************************* 104 | * 105 | * Custom Getter 106 | * 107 | ************************************************************* 108 | */ 109 | 110 | 111 | @Override 112 | public @Nullable String getMimeType() {return this.file.getMimeType();} 113 | 114 | @Override 115 | public @Nullable String getCRC32() {return this.file.getCrc32Hash();} 116 | 117 | @Override 118 | public @Nullable String getSHA1() {return this.file.getSha1Hash();} 119 | 120 | @Override 121 | public @Nullable String getQuickXorHash() {return this.file.getQuickXorHash();} 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/DefaultPackageItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.IdentitySet; 5 | import com.bhyoo.onedrive.container.facet.*; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.net.URI; 10 | 11 | /** 12 | * https://dev.onedrive.com/facets/package_facet.htm 13 | *

14 | * Because there is only one package type item in OneDrive now, this class inherits {@link DefaultFileItem}. 15 | *

16 | * 17 | * @author isac322 18 | */ 19 | public class DefaultPackageItem extends AbstractDriveItem implements PackageItem { 20 | @NotNull private final PackageFacet packages; 21 | 22 | DefaultPackageItem(@NotNull String id, @NotNull IdentitySet creator, @NotNull String createdDateTime, 23 | @Nullable String description, @NotNull String eTag, @NotNull IdentitySet lastModifier, 24 | @NotNull String lastModifiedDateTime, @NotNull String name, @NotNull URI webUrl, 25 | @NotNull Client client, @NotNull String cTag, @Nullable String deleted, 26 | FileSystemInfoFacet fileSystemInfo, @NotNull ItemReference parentReference, 27 | @Nullable SearchResultFacet searchResult, @Nullable SharedFacet shared, 28 | @Nullable SharePointIdsFacet sharePointIds, @NotNull Long size, URI webDavUrl, 29 | @NotNull PackageFacet packages) { 30 | super(id, creator, createdDateTime, description, eTag, lastModifier, lastModifiedDateTime, name, webUrl, 31 | client, cTag, deleted, fileSystemInfo, parentReference, searchResult, shared, sharePointIds, size, 32 | webDavUrl); 33 | this.packages = packages; 34 | 35 | createPointers(); 36 | } 37 | 38 | @Override public PackageType getType() { 39 | return packages.getType(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/DriveItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.AsyncJobMonitor; 4 | import com.bhyoo.onedrive.container.facet.FileSystemInfoFacet; 5 | import com.bhyoo.onedrive.container.facet.SearchResultFacet; 6 | import com.bhyoo.onedrive.container.facet.SharePointIdsFacet; 7 | import com.bhyoo.onedrive.container.facet.SharedFacet; 8 | import com.bhyoo.onedrive.container.items.pointer.BasePointer; 9 | import com.bhyoo.onedrive.container.items.pointer.IdPointer; 10 | import com.bhyoo.onedrive.container.items.pointer.PathPointer; 11 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | import java.net.URI; 16 | 17 | public interface DriveItem extends BaseItem { 18 | @Override String toString(); 19 | 20 | 21 | /** 22 | * This method refresh content even if you doesn't have changes.
23 | *
24 | * Note that when refresh content, it can contains difference that you didn't modify. because other side 25 | * (it could be other App, other process, etc.) can modify content after you fetched. 26 | * 27 | * @throws ErrorResponseException if error happens while requesting copying operation. such as invalid login info 28 | */ 29 | void refresh() throws ErrorResponseException; 30 | 31 | 32 | 33 | 34 | /* 35 | ************************************************************* 36 | * 37 | * Deleting 38 | * 39 | * ************************************************************* 40 | */ 41 | 42 | 43 | void delete() throws ErrorResponseException; 44 | 45 | 46 | 47 | 48 | /* 49 | ************************************************************* 50 | * 51 | * Coping 52 | * 53 | * ************************************************************* 54 | */ 55 | 56 | 57 | @NotNull AsyncJobMonitor copyTo(@NotNull FolderItem folder) throws ErrorResponseException; 58 | 59 | @NotNull AsyncJobMonitor copyTo(@NotNull FolderItem folder, @NotNull String newName) throws ErrorResponseException; 60 | 61 | @NotNull AsyncJobMonitor copyTo(@NotNull ItemReference folder) throws ErrorResponseException; 62 | 63 | @NotNull AsyncJobMonitor copyTo(@NotNull ItemReference folder, @NotNull String newName) throws ErrorResponseException; 64 | 65 | @NotNull AsyncJobMonitor copyTo(@NotNull BasePointer dest) throws ErrorResponseException; 66 | 67 | @NotNull AsyncJobMonitor copyTo(@NotNull BasePointer dest, @NotNull String newName) throws ErrorResponseException; 68 | 69 | @NotNull AsyncJobMonitor copyTo(@NotNull String destId) throws ErrorResponseException; 70 | 71 | @NotNull AsyncJobMonitor copyTo(@NotNull String destId, @NotNull String newName) throws ErrorResponseException; 72 | 73 | 74 | 75 | 76 | /* 77 | ************************************************************* 78 | * 79 | * Moving 80 | * 81 | ************************************************************* 82 | */ 83 | 84 | 85 | void moveTo(@NotNull FolderItem folder) throws ErrorResponseException; 86 | 87 | void moveTo(@NotNull ItemReference reference) throws ErrorResponseException; 88 | 89 | void moveTo(@NotNull String id) throws ErrorResponseException; 90 | 91 | void moveTo(@NotNull BasePointer pointer) throws ErrorResponseException; 92 | 93 | 94 | @NotNull ItemReference newReference(); 95 | 96 | 97 | 98 | 99 | /* 100 | ************************************************************* 101 | * 102 | * Custom Getter 103 | * 104 | ************************************************************* 105 | */ 106 | 107 | 108 | @NotNull String getDriveId(); 109 | 110 | @NotNull String getCTag(); 111 | 112 | @Nullable FileSystemInfoFacet getFileSystemInfo(); 113 | 114 | @NotNull ItemReference getParentReference(); 115 | 116 | @Nullable SearchResultFacet getSearchResult(); 117 | 118 | @Nullable SharedFacet getShared(); 119 | 120 | @Nullable SharePointIdsFacet getSharePointIds(); 121 | 122 | @Nullable Long getSize(); 123 | 124 | @Nullable URI getWebDavUrl(); 125 | 126 | @Nullable PathPointer getPathPointer(); 127 | 128 | @NotNull IdPointer getIdPointer(); 129 | 130 | 131 | 132 | 133 | /* 134 | ************************************************************* 135 | * 136 | * Custom Setter 137 | * 138 | ************************************************************* 139 | */ 140 | 141 | 142 | void updateDescription(String description) throws ErrorResponseException; 143 | 144 | void rename(@NotNull String name) throws ErrorResponseException; 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/FileItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.facet.*; 4 | import com.bhyoo.onedrive.exceptions.InvalidJsonException; 5 | import com.bhyoo.onedrive.network.async.DownloadFuture; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.nio.file.Path; 11 | 12 | public interface FileItem extends DriveItem { 13 | /** 14 | * Works just like {@link FileItem#download(Path, String)}} except new name of item will automatically set with 15 | * {@link FileItem#getName()}. 16 | * 17 | * @param path Folder path. It could be relative path (like . or ..). Note that this parameter isn't 18 | * path of item that will be downloaded. It must point parent directory of the item. 19 | * 20 | * @see FileItem#download(Path, String) 21 | */ 22 | void download(@NotNull String path) throws IOException; 23 | 24 | /** 25 | * Works just like {@link FileItem#download(Path, String)}}. 26 | * 27 | * @param path Folder path. It could be relative path (like . or ..). Note that this parameter isn't 28 | * path of item that will be downloaded. It must point parent directory of the item. 29 | * @param newName new file name. 30 | * 31 | * @see FileItem#download(Path, String) 32 | */ 33 | void download(@NotNull String path, @NotNull String newName) throws IOException; 34 | 35 | /** 36 | * Works just like {@link FileItem#download(Path, String)}} except new name of item will automatically set with 37 | * {@link FileItem#getName()}. 38 | * 39 | * @param folderPath Folder path. It could be relative path (like . or ..). Note that this parameter isn't 40 | * path of item that will be downloaded. It must point parent directory of the item. 41 | * 42 | * @see FileItem#download(Path, String) 43 | */ 44 | void download(@NotNull Path folderPath) throws IOException; 45 | 46 | /** 47 | * Download file from OneDrive to {@code folderPath} with {@code newName}. 48 | * It could be relative path (like . or ..).
49 | * If {@code newName} is already exists in {@code folderPath} or {@code folderPath} is not folder, 50 | * it will throw {@link IllegalArgumentException}. 51 | * 52 | * @param folderPath Folder path. It could be relative path (like . or ..). Note that this parameter isn't 53 | * path of item that will be downloaded. It must point parent directory of the item. 54 | * @param newName new file name. 55 | * 56 | * @throws SecurityException If a required system property value cannot be accessed, or if a security 57 | * manager exists and its SecurityManager.checkRead method denies read access to 58 | * the file 59 | * @throws IllegalArgumentException If {@code folderPath} is exists and is not directory. 60 | * @throws InvalidJsonException if fail to parse response of copying request into json. it caused by server 61 | * side not by SDK. 62 | * @throws IOException if an I/O error occurs 63 | */ 64 | void download(@NotNull Path folderPath, String newName) throws IOException; 65 | 66 | 67 | @NotNull DownloadFuture downloadAsync(@NotNull Path folderPath) throws IOException; 68 | 69 | @NotNull DownloadFuture downloadAsync(@NotNull Path folderPath, String newName) throws IOException; 70 | 71 | 72 | /* 73 | ************************************************************* 74 | * 75 | * Custom Getter 76 | * 77 | ************************************************************* 78 | */ 79 | 80 | 81 | @Nullable String getMimeType(); 82 | 83 | @Nullable String getCRC32(); 84 | 85 | @Nullable String getSHA1(); 86 | 87 | @Nullable String getQuickXorHash(); 88 | 89 | 90 | @Nullable AudioFacet getAudio(); 91 | 92 | @Nullable ImageFacet getImage(); 93 | 94 | @Nullable LocationFacet getLocation(); 95 | 96 | @Nullable PhotoFacet getPhoto(); 97 | 98 | @Nullable VideoFacet getVideo(); 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/FolderItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 4 | import com.bhyoo.onedrive.network.async.DriveItemFuture; 5 | import com.bhyoo.onedrive.network.async.UploadFuture; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.nio.file.Path; 11 | 12 | public interface FolderItem extends DriveItem, Iterable { 13 | // TODO: Implement '@name.conflictBehavior' 14 | 15 | // TODO: add more @throws 16 | 17 | /** 18 | * Implementation of detail. 19 | *

20 | * 21 | * @param name New folder name. 22 | * 23 | * @return New folder's object. 24 | * 25 | * @throws RuntimeException If creating folder or converting response is fails. 26 | */ 27 | @NotNull FolderItem createFolder(@NotNull String name) throws ErrorResponseException; 28 | 29 | @NotNull UploadFuture uploadFile(@NotNull Path filePath); 30 | 31 | @NotNull FileItem simpleUploadFile(@NotNull Path filePath) throws IOException, ErrorResponseException; 32 | 33 | @NotNull DriveItemFuture simpleUploadFileAsync(@NotNull Path filePath); 34 | 35 | 36 | 37 | /* 38 | ************************************************************* 39 | * 40 | * Custom Getter 41 | * 42 | ************************************************************* 43 | */ 44 | 45 | boolean isDeleted(); 46 | 47 | @Nullable String deletedState(); 48 | 49 | boolean isRoot(); 50 | 51 | boolean isChildrenFetched(); 52 | 53 | void fetchChildren() throws ErrorResponseException; 54 | 55 | boolean isSpecial(); 56 | 57 | long childCount(); 58 | 59 | @NotNull DriveItem[] allChildren() throws ErrorResponseException; 60 | 61 | @NotNull FolderItem[] folderChildren() throws ErrorResponseException; 62 | 63 | @NotNull FileItem[] fileChildren() throws ErrorResponseException; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/ItemReference.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.DriveType; 4 | import com.bhyoo.onedrive.container.facet.SharePointIdsFacet; 5 | import com.bhyoo.onedrive.container.items.pointer.PathPointer; 6 | import com.fasterxml.jackson.core.JsonParser; 7 | import com.fasterxml.jackson.core.JsonToken; 8 | import lombok.EqualsAndHashCode; 9 | import lombok.Getter; 10 | import lombok.ToString; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.io.IOException; 15 | import java.util.logging.Logger; 16 | 17 | // TODO: is there any way to merge with {@link BasePointer}? cause it's conflict in behavior 18 | 19 | /** 20 | * https://dev.onedrive.com/resources/itemReference 21 | * .htm 22 | * 23 | * @author isac322 24 | */ 25 | @ToString 26 | @EqualsAndHashCode(of = {"id", "driveId"}) 27 | public class ItemReference { 28 | @Getter protected @NotNull String driveId; 29 | @Getter protected @NotNull DriveType driveType; 30 | /** 31 | * only null when root directory 32 | */ 33 | @Getter protected @Nullable String id; 34 | /** 35 | * only null on Business version 36 | */ 37 | @Getter protected @Nullable String name; 38 | /** 39 | * only null when root directory 40 | */ 41 | @Getter protected @Nullable PathPointer pathPointer; 42 | /** 43 | * only null when root directory 44 | */ 45 | @Getter protected @Nullable String rawPath; 46 | @Getter protected @Nullable String shareId; 47 | @Getter protected @Nullable SharePointIdsFacet sharepointIds; 48 | 49 | protected ItemReference(@NotNull String driveId, @NotNull DriveType driveType, @Nullable String id, 50 | @Nullable String name, @Nullable String rawPath, @Nullable String shareId, 51 | @Nullable SharePointIdsFacet sharepointIds) { 52 | this.driveId = driveId; 53 | this.driveType = driveType; 54 | this.id = id; 55 | this.name = name; 56 | this.rawPath = rawPath; 57 | this.shareId = shareId; 58 | this.sharepointIds = sharepointIds; 59 | 60 | if (rawPath != null) { 61 | this.pathPointer = new PathPointer(rawPath, driveId); 62 | } 63 | } 64 | 65 | ItemReference(@NotNull String driveId, @NotNull DriveType driveType, 66 | @Nullable String id, @Nullable PathPointer pathPointer) { 67 | this.driveId = driveId; 68 | this.driveType = driveType; 69 | this.id = id; 70 | this.pathPointer = pathPointer; 71 | 72 | if (pathPointer != null) 73 | this.rawPath = pathPointer.toASCIIApi(); 74 | else 75 | this.rawPath = null; 76 | } 77 | 78 | public static ItemReference deserialize(@NotNull JsonParser parser) throws IOException { 79 | @Nullable String driveId = null; 80 | @Nullable DriveType driveType = null; 81 | @Nullable String id = null; 82 | @Nullable String name = null; 83 | @Nullable String rawPath = null; 84 | @Nullable String shareId = null; 85 | @Nullable SharePointIdsFacet sharepointIds = null; 86 | 87 | while (parser.nextToken() != JsonToken.END_OBJECT) { 88 | String currentName = parser.getCurrentName(); 89 | parser.nextToken(); 90 | 91 | switch (currentName) { 92 | case "driveId": 93 | driveId = parser.getText(); 94 | break; 95 | case "driveType": 96 | driveType = DriveType.deserialize(parser.getText()); 97 | break; 98 | case "id": 99 | id = parser.getText(); 100 | break; 101 | case "name": 102 | name = parser.getText(); 103 | break; 104 | case "path": 105 | rawPath = parser.getText(); 106 | break; 107 | case "shareId": 108 | shareId = parser.getText(); 109 | break; 110 | case "sharepointIds": 111 | sharepointIds = SharePointIdsFacet.deserialize(parser); 112 | break; 113 | default: 114 | Logger.getGlobal().info("Unknown attribute detected in ItemReference : " + currentName); 115 | } 116 | } 117 | 118 | assert driveId != null : "driveId is null"; 119 | assert driveType != null : "driveType is null"; 120 | 121 | return new ItemReference(driveId, driveType, id, name, rawPath, shareId, sharepointIds); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/PackageItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.facet.PackageType; 4 | 5 | public interface PackageItem extends DriveItem { 6 | PackageType getType(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/RemoteFileItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.facet.*; 5 | import com.bhyoo.onedrive.network.async.DownloadFuture; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.net.URI; 11 | import java.nio.file.Path; 12 | import java.nio.file.Paths; 13 | 14 | /** 15 | * @author isac322 16 | */ 17 | public class RemoteFileItem extends AbstractRemoteItem implements FileItem { 18 | RemoteFileItem(@NotNull String id, @NotNull String createdDateTime, @Nullable String description, 19 | @NotNull String eTag, @NotNull String lastModifiedDateTime, @NotNull String name, 20 | @NotNull URI webUrl, @NotNull Client client, @NotNull String cTag, @Nullable String deleted, 21 | @NotNull ItemReference parentReference, @Nullable SearchResultFacet searchResult, 22 | @Nullable SharedFacet shared, @Nullable SharePointIdsFacet sharePointIds, URI webDavUrl, 23 | @NotNull RemoteItemFacet remoteItem) { 24 | super(id, createdDateTime, description, eTag, lastModifiedDateTime, name, webUrl, client, cTag, deleted, 25 | parentReference, searchResult, shared, sharePointIds, webDavUrl, remoteItem); 26 | } 27 | 28 | @Override 29 | public void download(@NotNull String path) throws IOException { 30 | assert this.name != null : "this.name is null"; 31 | client.download(idPointer, Paths.get(path), this.name); 32 | } 33 | 34 | @Override 35 | public void download(@NotNull String path, @NotNull String newName) throws IOException { 36 | client.download(idPointer, Paths.get(path), newName); 37 | } 38 | 39 | @Override 40 | public void download(@NotNull Path folderPath) throws IOException { 41 | assert this.name != null : "this.name is null"; 42 | client.download(idPointer, folderPath, this.name); 43 | } 44 | 45 | // TODO: handling overwriting file 46 | 47 | @Override 48 | public void download(@NotNull Path folderPath, String newName) throws IOException { 49 | client.download(idPointer, folderPath, newName); 50 | } 51 | 52 | 53 | @Override 54 | public @NotNull DownloadFuture downloadAsync(@NotNull Path folderPath) throws IOException { 55 | return client.downloadAsync(idPointer, folderPath, this.name); 56 | } 57 | 58 | @Override 59 | public @NotNull DownloadFuture downloadAsync(@NotNull Path folderPath, String newName) throws IOException { 60 | return client.downloadAsync(idPointer, folderPath, newName); 61 | } 62 | 63 | 64 | @Override public @Nullable String getMimeType() { 65 | assert remoteItem.getFile() != null : "remoteItem.getFile() is null"; 66 | return remoteItem.getFile().getMimeType(); 67 | } 68 | 69 | @Override public @Nullable String getCRC32() { 70 | assert remoteItem.getFile() != null : "remoteItem.getFile() is null"; 71 | return remoteItem.getFile().getCrc32Hash(); 72 | } 73 | 74 | @Override public @Nullable String getSHA1() { 75 | assert remoteItem.getFile() != null : "remoteItem.getFile() is null"; 76 | return remoteItem.getFile().getSha1Hash(); 77 | } 78 | 79 | @Override public @Nullable String getQuickXorHash() { 80 | assert remoteItem.getFile() != null : "remoteItem.getFile() is null"; 81 | return remoteItem.getFile().getQuickXorHash(); 82 | } 83 | 84 | @Override public @Nullable AudioFacet getAudio() {return null;} 85 | 86 | @Override public @Nullable ImageFacet getImage() {return null;} 87 | 88 | @Override public @Nullable LocationFacet getLocation() {return null;} 89 | 90 | @Override public @Nullable PhotoFacet getPhoto() {return null;} 91 | 92 | @Override public @Nullable VideoFacet getVideo() {return null;} 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/RemoteFolderItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.facet.RemoteItemFacet; 5 | import com.bhyoo.onedrive.container.facet.SearchResultFacet; 6 | import com.bhyoo.onedrive.container.facet.SharePointIdsFacet; 7 | import com.bhyoo.onedrive.container.facet.SharedFacet; 8 | import com.bhyoo.onedrive.container.items.pointer.Operator; 9 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 10 | import com.bhyoo.onedrive.network.async.DriveItemFuture; 11 | import com.bhyoo.onedrive.network.async.ResponseFuture; 12 | import com.bhyoo.onedrive.network.async.UploadFuture; 13 | import io.netty.handler.codec.http.HttpMethod; 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | import java.io.IOException; 18 | import java.net.URI; 19 | import java.nio.file.Path; 20 | import java.util.ArrayList; 21 | import java.util.Iterator; 22 | import java.util.List; 23 | 24 | import static java.net.HttpURLConnection.HTTP_OK; 25 | 26 | 27 | public class RemoteFolderItem extends AbstractRemoteItem implements FolderItem { 28 | protected List folderChildren; 29 | protected List fileChildren; 30 | protected List allChildren; 31 | 32 | RemoteFolderItem(@NotNull String id, @NotNull String createdDateTime, @Nullable String description, 33 | @NotNull String eTag, @NotNull String lastModifiedDateTime, @NotNull String name, 34 | @NotNull URI webUrl, @NotNull Client client, @NotNull String cTag, @Nullable String deleted, 35 | @NotNull ItemReference parentReference, @Nullable SearchResultFacet searchResult, 36 | @Nullable SharedFacet shared, @Nullable SharePointIdsFacet sharePointIds, URI webDavUrl, 37 | @NotNull RemoteItemFacet remoteItem) { 38 | super(id, createdDateTime, description, eTag, lastModifiedDateTime, name, webUrl, client, cTag, deleted, 39 | parentReference, searchResult, shared, sharePointIds, webDavUrl, remoteItem); 40 | } 41 | 42 | @Override 43 | public @NotNull FolderItem createFolder(@NotNull String name) throws ErrorResponseException { 44 | return client.createFolder(remotePointer, name); 45 | } 46 | 47 | @Override public @NotNull UploadFuture uploadFile(@NotNull Path filePath) { 48 | return client.uploadFile(this.remoteItem.getId(), filePath); 49 | } 50 | 51 | @Override 52 | public @NotNull FileItem simpleUploadFile(@NotNull Path filePath) throws IOException, ErrorResponseException { 53 | return client.simpleUploadFile(this.remoteItem.getId(), filePath); 54 | } 55 | 56 | @Override public @NotNull DriveItemFuture simpleUploadFileAsync(@NotNull Path filePath) { 57 | return client.simpleUploadFileAsync(this.remoteItem.getId(), filePath); 58 | } 59 | 60 | @Override public boolean isDeleted() {return deleted != null;} 61 | 62 | @Override public @Nullable String deletedState() {return deleted;} 63 | 64 | @Override public boolean isRoot() {return false;} 65 | 66 | @Override public boolean isChildrenFetched() { 67 | assert remoteItem.getFolder() != null : "remoteItem.getFolder() is null"; 68 | return remoteItem.getFolder().getChildCount() == 0 69 | || allChildren != null && folderChildren != null && fileChildren != null; 70 | } 71 | 72 | protected void addChildren(@NotNull DriveItem[] array) { 73 | for (DriveItem item : array) { 74 | if (item instanceof FolderItem) { 75 | folderChildren.add((FolderItem) item); 76 | } 77 | else if (item instanceof FileItem) { 78 | fileChildren.add((FileItem) item); 79 | } 80 | else { 81 | // if child is neither FolderItem nor FileItem nor PackageItem. 82 | assert item instanceof PackageItem : "Wrong item type"; 83 | } 84 | allChildren.add(item); 85 | } 86 | } 87 | 88 | @Override public void fetchChildren() throws ErrorResponseException { 89 | allChildren = new ArrayList<>(); 90 | folderChildren = new ArrayList<>(); 91 | fileChildren = new ArrayList<>(); 92 | 93 | ResponseFuture responseFuture = client.requestTool() 94 | .doAsync(HttpMethod.GET, remotePointer.resolveOperator(Operator.CHILDREN)) 95 | .syncUninterruptibly(); 96 | 97 | addChildren(client.requestTool() 98 | .parseDriveItemRecursiveAndHandle(responseFuture.response(), responseFuture.getNow(), HTTP_OK)); 99 | } 100 | 101 | @Override public boolean isSpecial() {return false;} 102 | 103 | @Override public long childCount() { 104 | assert remoteItem.getFolder() != null : "remoteItem.getFolder() is null"; 105 | return remoteItem.getFolder().getChildCount(); 106 | } 107 | 108 | @Override public @NotNull DriveItem[] allChildren() throws ErrorResponseException { 109 | if (!isChildrenFetched()) fetchChildren(); 110 | return allChildren.toArray(new DriveItem[0]); 111 | } 112 | 113 | @Override public @NotNull FolderItem[] folderChildren() throws ErrorResponseException { 114 | if (!isChildrenFetched()) fetchChildren(); 115 | return folderChildren.toArray(new FolderItem[0]); 116 | } 117 | 118 | @Override public @NotNull FileItem[] fileChildren() throws ErrorResponseException { 119 | if (!isChildrenFetched()) fetchChildren(); 120 | return fileChildren.toArray(new FileItem[0]); 121 | } 122 | 123 | @Override public @NotNull Iterator iterator() { 124 | try { 125 | if (!isChildrenFetched()) fetchChildren(); 126 | return allChildren.iterator(); 127 | } 128 | catch (ErrorResponseException e) { 129 | // FIXME: custom exception 130 | throw new RuntimeException(e); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/RemoteItem.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items; 2 | 3 | import com.bhyoo.onedrive.container.facet.RemoteItemFacet; 4 | import com.bhyoo.onedrive.container.items.pointer.IdPointer; 5 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public interface RemoteItem extends DriveItem { 9 | @NotNull String getRemoteDriveID(); 10 | 11 | @NotNull String getRemoteID(); 12 | 13 | @NotNull IdPointer getRemotePointer(); 14 | 15 | @NotNull DriveItem fetchRemoteItem() throws ErrorResponseException; 16 | 17 | @NotNull RemoteItemFacet getRemoteItem(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/pointer/BasePointer.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items.pointer; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | import java.net.URI; 7 | import java.net.URISyntaxException; 8 | 9 | /** 10 | * @author isac322 11 | */ 12 | abstract public class BasePointer { 13 | abstract public @Nullable String getDriveId(); 14 | 15 | abstract public @NotNull URI toURI() throws URISyntaxException; 16 | 17 | abstract public @NotNull String toApi(); 18 | 19 | abstract public @NotNull String toASCIIApi(); 20 | 21 | @Override public @NotNull String toString() { 22 | return toApi(); 23 | } 24 | 25 | abstract public @NotNull String toJson(); 26 | 27 | /** 28 | * DO NOT USE
29 | * Internal use only 30 | * 31 | * @param op operator object 32 | * 33 | * @return resolved API 34 | */ 35 | abstract public @NotNull String resolveOperator(@NotNull Operator op); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/pointer/IdPointer.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items.pointer; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import lombok.Getter; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | import java.net.URI; 9 | import java.net.URISyntaxException; 10 | import java.util.regex.Pattern; 11 | 12 | import static com.bhyoo.onedrive.client.Client.ITEM_ID_PREFIX; 13 | 14 | /** 15 | * @author isac322 16 | */ 17 | public class IdPointer extends BasePointer { 18 | private static final @NotNull Pattern idPattern = Pattern.compile("[a-zA-Z0-9!]+"); 19 | 20 | @Getter protected final @Nullable String driveId; 21 | @Getter protected final @NotNull String id; 22 | private final @NotNull String path; 23 | 24 | 25 | public IdPointer(@NotNull String id) { 26 | if (!idPattern.matcher(id).matches()) 27 | throw new IllegalArgumentException("`id` isn't match with regex \"[a-zA-Z0-9!]+\""); 28 | 29 | this.id = id; 30 | this.driveId = null; 31 | this.path = ITEM_ID_PREFIX + id; 32 | } 33 | 34 | public IdPointer(@NotNull String id, @Nullable String driveId) { 35 | if (!idPattern.matcher(id).matches()) 36 | throw new IllegalArgumentException("`id` isn't match with regex \"[a-zA-Z0-9!]+\""); 37 | 38 | this.id = id; 39 | this.driveId = driveId; 40 | this.path = "/drives/" + driveId + "/items/" + id; 41 | } 42 | 43 | @Override 44 | public @NotNull String toJson() { 45 | return "{\"id\":\"" + path + "\"}"; 46 | } 47 | 48 | @Override 49 | public @NotNull String resolveOperator(@NotNull Operator op) { 50 | return path + '/' + op; 51 | } 52 | 53 | @Override 54 | public @NotNull URI toURI() throws URISyntaxException { 55 | return new URI(RequestTool.SCHEME, RequestTool.HOST, path, null); 56 | } 57 | 58 | @Override 59 | public @NotNull String toApi() { 60 | return path; 61 | } 62 | 63 | @Override 64 | public @NotNull String toASCIIApi() { 65 | return path; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/items/pointer/Operator.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items.pointer; 2 | 3 | /** 4 | * @author isac322 5 | */ 6 | public enum Operator { 7 | COPY("copy"), 8 | ACTION_CREATE_LINK("action.createLink"), 9 | CHILDREN("children"), 10 | CONTENT("content"), 11 | SEARCH("search"), 12 | DELTA("delta"), 13 | THUMBNAILS("thumbnails"), 14 | CREATE_UPLOAD_SESSION("createUploadSession"); 15 | 16 | private final String operator; 17 | 18 | Operator(String operator) {this.operator = operator;} 19 | 20 | @Override public String toString() {return operator;} 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/pager/AbstractPager.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.pager; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 5 | import com.bhyoo.onedrive.network.async.ResponseFuture; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.net.URI; 11 | import java.util.Iterator; 12 | import java.util.NoSuchElementException; 13 | 14 | import static io.netty.handler.codec.http.HttpMethod.GET; 15 | 16 | abstract public class AbstractPager implements Iterable { 17 | protected final @NotNull RequestTool requestTool; 18 | protected @NotNull Page page; 19 | 20 | protected AbstractPager(@NotNull RequestTool requestTool, @NotNull Page page) { 21 | this.requestTool = requestTool; 22 | this.page = page; 23 | } 24 | 25 | 26 | abstract static class Page { 27 | @Getter protected final @Nullable URI nextLink; 28 | @Getter protected final @Nullable URI deltaLink; 29 | @Getter protected final @NotNull T value; 30 | 31 | Page(@Nullable URI nextLink, @Nullable URI deltaLink, @NotNull T value) { 32 | this.nextLink = nextLink; 33 | this.deltaLink = deltaLink; 34 | this.value = value; 35 | } 36 | } 37 | 38 | 39 | abstract static class PageIterator implements Iterator { 40 | protected final @NotNull RequestTool requestTool; 41 | protected @Nullable Page currentPage; 42 | protected boolean isFirst = true; 43 | 44 | PageIterator(@NotNull RequestTool requestTool, @NotNull Page currentPage) { 45 | this.requestTool = requestTool; 46 | this.currentPage = currentPage; 47 | } 48 | 49 | @Override public T next() { 50 | if (isFirst) { 51 | isFirst = false; 52 | assert currentPage != null : "currentPage is null"; 53 | return currentPage.value; 54 | } 55 | else if (currentPage == null || currentPage.nextLink == null) throw new NoSuchElementException(); 56 | else { 57 | ResponseFuture responseFuture = requestTool.doAsync(GET, currentPage.nextLink).syncUninterruptibly(); 58 | try { 59 | currentPage = parse(responseFuture); 60 | return currentPage.value; 61 | } 62 | catch (ErrorResponseException e) { 63 | throw new IllegalStateException(e); 64 | } 65 | } 66 | } 67 | 68 | @Override public boolean hasNext() {return currentPage != null && currentPage.nextLink != null;} 69 | 70 | @Override public void remove() {throw new UnsupportedOperationException();} 71 | 72 | protected abstract Page parse(@NotNull ResponseFuture responseFuture) throws ErrorResponseException; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/pager/DriveItemPager.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.pager; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.client.RequestTool; 5 | import com.bhyoo.onedrive.container.items.AbstractDriveItem; 6 | import com.bhyoo.onedrive.container.items.DriveItem; 7 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 8 | import com.bhyoo.onedrive.network.async.ResponseFuture; 9 | import com.fasterxml.jackson.core.JsonParser; 10 | import com.fasterxml.jackson.core.JsonToken; 11 | import lombok.SneakyThrows; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | import java.io.IOException; 16 | import java.net.URI; 17 | import java.net.URISyntaxException; 18 | import java.util.ArrayList; 19 | import java.util.Iterator; 20 | import java.util.logging.Logger; 21 | 22 | import static io.netty.handler.codec.http.HttpMethod.GET; 23 | import static java.net.HttpURLConnection.HTTP_OK; 24 | 25 | public class DriveItemPager extends AbstractPager { 26 | protected DriveItemPager(@NotNull RequestTool requestTool, @NotNull DriveItemPage page) { 27 | super(requestTool, page); 28 | } 29 | 30 | public static DriveItemPager deserialize(@NotNull Client client, @NotNull JsonParser parser, boolean autoClose) 31 | throws IOException { 32 | DriveItemPage itemPage = DriveItemPage.deserialize(client, parser, autoClose); 33 | return new DriveItemPager(client.requestTool(), itemPage); 34 | } 35 | 36 | @SneakyThrows(URISyntaxException.class) 37 | public static @NotNull DriveItem[] deserializeRecursive(final @NotNull Client client, @NotNull JsonParser parser, 38 | boolean autoClose) throws IOException { 39 | @Nullable URI nextLink; 40 | @NotNull ArrayList items = new ArrayList<>(); 41 | @Nullable JsonParser currentParser = parser; 42 | 43 | do { 44 | @Nullable ResponseFuture responseFuture = null; 45 | nextLink = null; 46 | 47 | while (currentParser.nextToken() != JsonToken.END_OBJECT) { 48 | String currentName = currentParser.getCurrentName(); 49 | currentParser.nextToken(); 50 | 51 | switch (currentName) { 52 | case "@odata.nextLink": 53 | nextLink = new URI(currentParser.getText()); 54 | responseFuture = client.requestTool().doAsync(GET, nextLink); 55 | break; 56 | case "@odata.deltaLink": 57 | break; 58 | case "value": 59 | while (currentParser.nextToken() != JsonToken.END_ARRAY) { 60 | items.add(AbstractDriveItem.deserialize(client, currentParser, false)); 61 | } 62 | break; 63 | case "@odata.context": 64 | // TODO 65 | break; 66 | default: 67 | Logger.getGlobal().info("Unknown attribute detected in DriveItemPager : " + currentName); 68 | } 69 | } 70 | 71 | if (responseFuture != null) { 72 | responseFuture.syncUninterruptibly(); 73 | if (parser != currentParser) currentParser.close(); 74 | currentParser = RequestTool.jsonFactory.createParser(responseFuture.getNow()); 75 | currentParser.nextToken(); 76 | } 77 | } while (nextLink != null); 78 | 79 | if (currentParser != parser) currentParser.close(); 80 | if (autoClose) parser.close(); 81 | 82 | return items.toArray(new DriveItem[0]); 83 | } 84 | 85 | @Override public @NotNull Iterator iterator() {return new ItemPageIterator(requestTool, page);} 86 | 87 | 88 | public static class DriveItemPage extends Page { 89 | DriveItemPage(@Nullable URI nextLink, @Nullable URI deltaLink, @NotNull DriveItem[] value) { 90 | super(nextLink, deltaLink, value); 91 | } 92 | 93 | @SneakyThrows(URISyntaxException.class) 94 | public static DriveItemPage deserialize(@NotNull Client client, @NotNull JsonParser parser, boolean autoClose) 95 | throws IOException { 96 | @Nullable URI nextLink = null; 97 | @Nullable URI deltaLink = null; 98 | @NotNull ArrayList values = new ArrayList<>(); 99 | 100 | while (parser.nextToken() != JsonToken.END_OBJECT) { 101 | String currentName = parser.getCurrentName(); 102 | parser.nextToken(); 103 | 104 | switch (currentName) { 105 | case "@odata.nextLink": 106 | nextLink = new URI(parser.getText()); 107 | break; 108 | case "@odata.deltaLink": 109 | deltaLink = new URI(parser.getText()); 110 | break; 111 | case "value": 112 | while (parser.nextToken() != JsonToken.END_ARRAY) { 113 | values.add(AbstractDriveItem.deserialize(client, parser, false)); 114 | } 115 | break; 116 | default: 117 | Logger.getGlobal().info("Unknown attribute detected in DriveItemPager : " + currentName); 118 | } 119 | } 120 | 121 | if (autoClose) parser.close(); 122 | return new DriveItemPage(nextLink, deltaLink, values.toArray(new DriveItem[0])); 123 | } 124 | } 125 | 126 | 127 | class ItemPageIterator extends PageIterator { 128 | ItemPageIterator(@NotNull RequestTool requestTool, @NotNull Page currentPage) { 129 | super(requestTool, currentPage); 130 | } 131 | 132 | @Override 133 | protected DriveItemPage parse(@NotNull ResponseFuture responseFuture) throws ErrorResponseException { 134 | return requestTool.parseDriveItemPageAndHandle( 135 | responseFuture.response(), responseFuture.getNow(), HTTP_OK); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/container/pager/DrivePager.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.pager; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.client.RequestTool; 5 | import com.bhyoo.onedrive.container.items.Drive; 6 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 7 | import com.bhyoo.onedrive.network.async.ResponseFuture; 8 | import com.fasterxml.jackson.core.JsonParser; 9 | import com.fasterxml.jackson.core.JsonToken; 10 | import lombok.SneakyThrows; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.io.IOException; 15 | import java.net.URI; 16 | import java.net.URISyntaxException; 17 | import java.util.ArrayList; 18 | import java.util.Iterator; 19 | import java.util.logging.Logger; 20 | 21 | import static java.net.HttpURLConnection.HTTP_OK; 22 | 23 | public class DrivePager extends AbstractPager { 24 | protected DrivePager(@NotNull RequestTool requestTool, @NotNull DrivePage page) { 25 | super(requestTool, page); 26 | } 27 | 28 | public static DrivePager deserialize(@NotNull Client client, @NotNull JsonParser parser) throws IOException { 29 | DrivePage itemPage = DrivePage.deserialize(client, parser); 30 | return new DrivePager(client.requestTool(), itemPage); 31 | } 32 | 33 | @NotNull @Override public Iterator iterator() { 34 | return new DrivePageIterator(requestTool, page); 35 | } 36 | 37 | public static class DrivePage extends Page { 38 | DrivePage(@Nullable URI nextLink, @Nullable URI deltaLink, @NotNull Drive[] value) { 39 | super(nextLink, deltaLink, value); 40 | } 41 | 42 | @SneakyThrows(URISyntaxException.class) 43 | public static DrivePage deserialize(@NotNull Client client, @NotNull JsonParser parser) throws IOException { 44 | @Nullable URI nextLink = null; 45 | @Nullable URI deltaLink = null; 46 | @NotNull ArrayList values = new ArrayList<>(); 47 | 48 | while (parser.nextToken() != JsonToken.END_OBJECT) { 49 | String currentName = parser.getCurrentName(); 50 | parser.nextToken(); 51 | 52 | switch (currentName) { 53 | case "@odata.nextLink": 54 | nextLink = new URI(parser.getText()); 55 | break; 56 | case "@odata.deltaLink": 57 | deltaLink = new URI(parser.getText()); 58 | break; 59 | case "value": 60 | while (parser.nextToken() != JsonToken.END_ARRAY) { 61 | values.add(Drive.deserialize(client, parser)); 62 | } 63 | break; 64 | case "@odata.context": 65 | // TODO 66 | break; 67 | default: 68 | Logger.getGlobal().info("Unknown attribute detected in DriveItemPager : " + currentName); 69 | } 70 | } 71 | 72 | return new DrivePage(nextLink, deltaLink, values.toArray(new Drive[0])); 73 | } 74 | } 75 | 76 | 77 | class DrivePageIterator extends PageIterator { 78 | DrivePageIterator(@NotNull RequestTool requestTool, @NotNull Page currentPage) { 79 | super(requestTool, currentPage); 80 | } 81 | 82 | @Override 83 | protected DrivePage parse(@NotNull ResponseFuture responseFuture) throws ErrorResponseException { 84 | return requestTool.parseDrivePageAndHandle(responseFuture.response(), responseFuture.getNow(), HTTP_OK); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/exceptions/ErrorResponseException.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.exceptions; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Exception that server rejects to response.
7 | * Mostly because of invalid request, such as requesting deleting item that already deleted.
8 | * More details of error type can be found here. 9 | * 10 | * @author isac322 11 | */ 12 | public class ErrorResponseException extends Exception implements OneDriveSDKException { 13 | private static final long serialVersionUID = -1799958534485231334L; 14 | @Getter private final int expectedResponse, givenResponse; 15 | @Getter private final String errorCode, errorMessage; 16 | 17 | public ErrorResponseException(int expectedResponse, int givenResponse, String errorCode, String errorMessage) { 18 | super(String.format("Expected %d response code, but received %d. It means %s (%s).", 19 | expectedResponse, givenResponse, errorCode, errorMessage)); 20 | this.expectedResponse = expectedResponse; 21 | this.givenResponse = givenResponse; 22 | this.errorCode = errorCode; 23 | this.errorMessage = errorMessage; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/exceptions/InternalException.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.exceptions; 2 | 3 | /** 4 | * Exception that happens when SDK fails itself, in short BUG. So if you encounter with this kind of 5 | * exception, contact to author with stack trace. 6 | * 7 | * @author isac322 8 | */ 9 | public class InternalException extends RuntimeException implements OneDriveSDKException { 10 | private static final long serialVersionUID = 3298001219331142089L; 11 | 12 | public InternalException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public InternalException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/exceptions/InvalidJsonException.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.exceptions; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import lombok.Getter; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | /** 9 | * Exception type for when SDK encounters invalid JSON from server. That means client's request was valid but 10 | * OneDrive's server responses with invalid JSON. So if you encounter with this exception, firstly retry. but if it 11 | * happens continuously contact author with {@code content}. 12 | * 13 | * @author isac322 14 | */ 15 | public class InvalidJsonException extends RuntimeException implements OneDriveServerException { 16 | private static final long serialVersionUID = -5643456357629703015L; 17 | @Getter private byte[] content; 18 | @Getter private int responseCode; 19 | 20 | public InvalidJsonException(@Nullable Throwable cause, int responseCode) { 21 | super("Invalid JSON response from server with " + responseCode + " response code.", cause); 22 | this.responseCode = responseCode; 23 | } 24 | 25 | public InvalidJsonException(@Nullable Throwable cause, int responseCode, @Nullable byte[] content) { 26 | super("Invalid JSON response from server with " + responseCode + " response code.", cause); 27 | this.responseCode = responseCode; 28 | this.content = content; 29 | } 30 | 31 | public InvalidJsonException(@Nullable Throwable cause, int responseCode, @NotNull ByteBuf content) { 32 | super("Invalid JSON response from server with " + responseCode + " response code.", cause); 33 | this.responseCode = responseCode; 34 | this.content = new byte[content.readableBytes()]; 35 | content.readBytes(this.content); 36 | } 37 | 38 | public InvalidJsonException(@Nullable String message, int responseCode, @Nullable byte[] content) { 39 | super(message); 40 | this.responseCode = responseCode; 41 | this.content = content; 42 | } 43 | 44 | public InvalidJsonException(@NotNull String message) { 45 | super(message); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/exceptions/OneDriveSDKException.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.exceptions; 2 | 3 | /** 4 | * Exception that happens in this SDK, such as requesting item with invalid item-id. 5 | * 6 | * @author isac322 7 | */ 8 | public interface OneDriveSDKException { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/exceptions/OneDriveServerException.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.exceptions; 2 | 3 | /** 4 | * Exception that happens in OneDrive server, such as invalid json.
5 | * Most of this exception can be resolved by retrying. but if same exception happens continuously, 6 | * it's probably SDK error, so contact author. 7 | * 8 | * @author isac322 9 | */ 10 | public interface OneDriveServerException { 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network; 2 | 3 | 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import lombok.Getter; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.io.IOException; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * explain of error types 15 | * 16 | * @author isac322 17 | */ 18 | public class ErrorResponse { 19 | @Getter protected final @NotNull String code; 20 | @Getter protected final @NotNull String message; 21 | @Getter protected final @NotNull String requestId; 22 | @Getter protected final @NotNull String date; 23 | 24 | protected ErrorResponse(@NotNull String code, @NotNull String message, 25 | @NotNull String requestId, @NotNull String date) { 26 | this.code = code; 27 | this.message = message; 28 | this.requestId = requestId; 29 | this.date = date; 30 | } 31 | 32 | public static @NotNull ErrorResponse deserialize(@NotNull JsonParser parser, boolean autoClose) 33 | throws IOException { 34 | @Nullable String code = null; 35 | @Nullable String message = null; 36 | @Nullable String requestId = null; 37 | @Nullable String date = null; 38 | 39 | while (parser.nextToken() != JsonToken.END_OBJECT) { 40 | String currentName = parser.getCurrentName(); 41 | parser.nextToken(); 42 | 43 | switch (currentName) { 44 | case "error": 45 | while (parser.nextToken() != JsonToken.END_OBJECT) { 46 | String fieldName = parser.currentName(); 47 | parser.nextToken(); 48 | 49 | switch (fieldName) { 50 | case "code": 51 | code = parser.getText(); 52 | break; 53 | case "message": 54 | message = parser.getText(); 55 | break; 56 | case "innerError": 57 | // TODO 58 | break; 59 | case "request-id": 60 | requestId = parser.getText(); 61 | break; 62 | case "date": 63 | date = parser.getText(); 64 | break; 65 | default: 66 | Logger.getGlobal().info(String.format( 67 | "Unknown attribute detected in inner ErrorResponse : %s(%s)", 68 | fieldName, parser.getText())); 69 | } 70 | } 71 | break; 72 | default: 73 | Logger.getGlobal().info(String.format( 74 | "Unknown attribute detected in ErrorResponse : %s(%s)", 75 | currentName, parser.getText())); 76 | } 77 | } 78 | 79 | if (autoClose) parser.close(); 80 | 81 | assert code != null : "code is null"; 82 | assert message != null : "message is null"; 83 | assert requestId != null : "requestId is null"; 84 | assert date != null : "date is null"; 85 | 86 | return new ErrorResponse(code, message, requestId, date); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/UploadSession.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonToken; 5 | import lombok.Getter; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * implements of detail 15 | * 16 | * @author isac322 17 | */ 18 | public class UploadSession { 19 | @Getter protected @Nullable String uploadUrl; 20 | @Getter protected @NotNull String expirationDateTime; 21 | @Getter protected @NotNull String[] nextExpectedRanges; 22 | 23 | 24 | UploadSession(@Nullable String uploadUrl, @NotNull String expirationDateTime, 25 | @NotNull String[] nextExpectedRanges) { 26 | this.uploadUrl = uploadUrl; 27 | this.expirationDateTime = expirationDateTime; 28 | this.nextExpectedRanges = nextExpectedRanges; 29 | } 30 | 31 | public static @NotNull UploadSession deserialize(@NotNull JsonParser parser, boolean autoClose) 32 | throws IOException { 33 | @Nullable String uploadUrl = null; 34 | @Nullable String expirationDateTime = null; 35 | @Nullable String[] nextExpectedRanges = null; 36 | 37 | while (parser.nextToken() != JsonToken.END_OBJECT) { 38 | String currentName = parser.getCurrentName(); 39 | parser.nextToken(); 40 | 41 | switch (currentName) { 42 | case "uploadUrl": 43 | uploadUrl = parser.getText(); 44 | break; 45 | case "expirationDateTime": 46 | expirationDateTime = parser.getText(); 47 | break; 48 | case "nextExpectedRanges": 49 | ArrayList ranges = new ArrayList<>(); 50 | while (parser.nextToken() != JsonToken.END_ARRAY) { 51 | ranges.add(parser.getText()); 52 | } 53 | nextExpectedRanges = ranges.toArray(new String[0]); 54 | break; 55 | 56 | default: 57 | Logger.getGlobal().info("Unknown attribute detected in UploadSession : " + currentName); 58 | } 59 | } 60 | 61 | if (autoClose) parser.close(); 62 | 63 | assert uploadUrl != null : "uploadUrl is null"; 64 | assert expirationDateTime != null : "expirationDateTime is null"; 65 | assert nextExpectedRanges != null : "nextExpectedRanges is null"; 66 | 67 | return new UploadSession(uploadUrl, expirationDateTime, nextExpectedRanges); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AbstractClient.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.handler.codec.http.DefaultFullHttpRequest; 6 | import io.netty.handler.codec.http.HttpMethod; 7 | import io.netty.util.AsciiString; 8 | import io.netty.util.concurrent.Future; 9 | import lombok.Getter; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | import java.net.URI; 14 | 15 | import static io.netty.handler.codec.http.HttpHeaderNames.ACCEPT_ENCODING; 16 | import static io.netty.handler.codec.http.HttpHeaderNames.HOST; 17 | import static io.netty.handler.codec.http.HttpHeaderValues.GZIP; 18 | import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; 19 | 20 | /** 21 | * @author isac322 22 | */ 23 | public abstract class AbstractClient { 24 | @NotNull @Getter protected final URI uri; 25 | @NotNull @Getter protected final HttpMethod method; 26 | @Nullable @Getter protected final byte[] content; 27 | @NotNull protected final DefaultFullHttpRequest request; 28 | 29 | 30 | public AbstractClient(@NotNull HttpMethod method, @NotNull URI uri, @Nullable byte[] content) { 31 | this.uri = uri; 32 | this.method = method; 33 | this.content = content; 34 | 35 | if (!RequestTool.SCHEME.equalsIgnoreCase(uri.getScheme())) { 36 | throw new IllegalArgumentException("Wrong network scheme : \"" + uri.getScheme() + "\"."); 37 | } 38 | 39 | if (content != null) { 40 | this.request = new DefaultFullHttpRequest( 41 | HTTP_1_1, 42 | method, 43 | uri.toASCIIString(), 44 | Unpooled.wrappedBuffer(content)); 45 | } 46 | else { 47 | this.request = new DefaultFullHttpRequest(HTTP_1_1, method, uri.toASCIIString()); 48 | } 49 | 50 | this.request.headers() 51 | .set(HOST, uri.getHost()) 52 | .set(ACCEPT_ENCODING, GZIP); 53 | } 54 | 55 | @NotNull public AbstractClient setHeader(AsciiString header, CharSequence value) { 56 | request.headers().set(header, value); 57 | return this; 58 | } 59 | 60 | @NotNull public AbstractClient setHeader(String header, String value) { 61 | request.headers().set(header, value); 62 | return this; 63 | } 64 | 65 | public abstract Future execute(); 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AsyncClient.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import io.netty.bootstrap.Bootstrap; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelFutureListener; 7 | import io.netty.channel.EventLoopGroup; 8 | import io.netty.handler.codec.http.HttpMethod; 9 | import io.netty.util.AsciiString; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | import java.net.URI; 14 | 15 | /** 16 | * @author isac322 17 | */ 18 | public class AsyncClient extends AbstractClient { 19 | @NotNull private final EventLoopGroup group; 20 | 21 | 22 | public AsyncClient(@NotNull EventLoopGroup group, @NotNull HttpMethod method, @NotNull URI uri) { 23 | super(method, uri, null); 24 | this.group = group; 25 | } 26 | 27 | public AsyncClient(@NotNull EventLoopGroup group, @NotNull HttpMethod method, @NotNull URI uri, 28 | @Nullable byte[] content) { 29 | super(method, uri, content); 30 | this.group = group; 31 | } 32 | 33 | 34 | @Override public @NotNull AsyncClient setHeader(AsciiString header, CharSequence value) { 35 | request.headers().set(header, value); 36 | return this; 37 | } 38 | 39 | @Override public @NotNull AsyncClient setHeader(String header, String value) { 40 | request.headers().set(header, value); 41 | return this; 42 | } 43 | 44 | 45 | @Override 46 | public ResponseFuture execute() { 47 | String host = uri.getHost(); 48 | int port = 443; 49 | 50 | ResponsePromise promise = new DefaultResponsePromise(group.next()); 51 | 52 | // Configure the client. 53 | Bootstrap bootstrap = new Bootstrap() 54 | .group(group) 55 | .channel(RequestTool.socketChannelClass()) 56 | .handler(new AsyncDefaultInitializer(new AsyncClientHandler(promise))); 57 | 58 | 59 | bootstrap.connect(host, port).addListener(new ChannelFutureListener() { 60 | @Override public void operationComplete(ChannelFuture future) { 61 | future.channel().writeAndFlush(request); 62 | } 63 | }); 64 | 65 | return promise; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AsyncClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.utils.ByteBufStream; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.SimpleChannelInboundHandler; 6 | import io.netty.handler.codec.http.HttpContent; 7 | import io.netty.handler.codec.http.HttpObject; 8 | import io.netty.handler.codec.http.HttpResponse; 9 | import io.netty.handler.codec.http.LastHttpContent; 10 | 11 | public class AsyncClientHandler extends SimpleChannelInboundHandler { 12 | private final ByteBufStream resultStream = new ByteBufStream(); 13 | private final ResponsePromise responsePromise; 14 | 15 | 16 | public AsyncClientHandler(ResponsePromise responsePromise) { 17 | this.responsePromise = responsePromise; 18 | } 19 | 20 | @Override 21 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 22 | super.channelActive(ctx); 23 | responsePromise.setChannel(ctx.channel()); 24 | } 25 | 26 | @Override 27 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 28 | super.exceptionCaught(ctx, cause); 29 | responsePromise.setFailure(cause); 30 | ctx.close(); 31 | } 32 | 33 | @Override 34 | protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) { 35 | if (msg instanceof HttpResponse) { 36 | responsePromise.setResponse((HttpResponse) msg); 37 | } 38 | 39 | if (msg instanceof HttpContent) { 40 | HttpContent content = (HttpContent) msg; 41 | 42 | resultStream.writeByteBuf(content.content()); 43 | 44 | // if this message is last of response 45 | if (content instanceof LastHttpContent) { 46 | ctx.close(); 47 | responsePromise.trySuccess(resultStream); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AsyncDefaultInitializer.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.channel.ChannelHandler; 4 | import io.netty.channel.ChannelInitializer; 5 | import io.netty.channel.ChannelPipeline; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.handler.codec.http.HttpClientCodec; 8 | import io.netty.handler.codec.http.HttpContentDecompressor; 9 | import io.netty.handler.ssl.SslContext; 10 | import io.netty.handler.ssl.SslContextBuilder; 11 | import io.netty.handler.ssl.SslProvider; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import javax.net.ssl.SSLException; 15 | 16 | public class AsyncDefaultInitializer extends ChannelInitializer { 17 | protected static final SslContext sslContext; 18 | 19 | static { 20 | SslContext sslContext1; 21 | try { 22 | sslContext1 = SslContextBuilder.forClient().sslProvider(SslProvider.JDK).build(); 23 | } 24 | catch (SSLException e) { 25 | e.printStackTrace(); 26 | System.err.println("Fail to initialize SslContext."); 27 | System.exit(1); 28 | sslContext1 = null; 29 | } 30 | sslContext = sslContext1; 31 | } 32 | 33 | private final ChannelHandler handler; 34 | 35 | public AsyncDefaultInitializer(@NotNull ChannelHandler handler) { 36 | this.handler = handler; 37 | } 38 | 39 | @Override 40 | public void initChannel(SocketChannel ch) { 41 | ChannelPipeline pipeline = ch.pipeline(); 42 | 43 | // Enable HTTPS. 44 | pipeline.addLast("ssl", sslContext.newHandler(ch.alloc())); 45 | // pipeline.addLast(new LoggingHandler(LogLevel.INFO)); 46 | 47 | pipeline.addLast("codec", new HttpClientCodec()); 48 | 49 | // Remove the following line if you don't want automatic content decompression. 50 | pipeline.addLast("inflater", new HttpContentDecompressor()); 51 | 52 | pipeline.addLast("handler", handler); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AsyncDownloadClient.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 5 | import com.bhyoo.onedrive.utils.ByteBufStream; 6 | import io.netty.bootstrap.Bootstrap; 7 | import io.netty.channel.Channel; 8 | import io.netty.channel.EventLoopGroup; 9 | import io.netty.handler.codec.http.DefaultFullHttpRequest; 10 | import io.netty.handler.codec.http.HttpHeaderNames; 11 | import io.netty.handler.codec.http.HttpMethod; 12 | import io.netty.handler.codec.http.HttpResponse; 13 | import io.netty.util.AsciiString; 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | import java.net.MalformedURLException; 18 | import java.net.URI; 19 | import java.net.URL; 20 | import java.nio.file.Path; 21 | import java.util.concurrent.ExecutionException; 22 | 23 | import static java.net.HttpURLConnection.HTTP_MOVED_TEMP; 24 | 25 | /** 26 | * @author isac322 27 | */ 28 | public class AsyncDownloadClient extends AbstractClient { 29 | private final @NotNull String accessToken; 30 | private final @NotNull Path downloadFolder; 31 | private final @Nullable String newName; 32 | 33 | 34 | public AsyncDownloadClient(@NotNull String accessToken, @NotNull URI itemURI, @NotNull Path downloadFolder) { 35 | this(accessToken, itemURI, downloadFolder, null); 36 | } 37 | 38 | public AsyncDownloadClient(@NotNull String accessToken, @NotNull URI itemURI, 39 | @NotNull Path downloadFolder, @Nullable String newName) { 40 | super(HttpMethod.GET, itemURI, null); 41 | this.accessToken = accessToken; 42 | this.downloadFolder = downloadFolder; 43 | this.newName = newName; 44 | } 45 | 46 | @Override public @NotNull AsyncDownloadClient setHeader(AsciiString header, CharSequence value) { 47 | super.setHeader(header, value); 48 | return this; 49 | } 50 | 51 | @Override public @NotNull AsyncDownloadClient setHeader(String header, String value) { 52 | super.setHeader(header, value); 53 | return this; 54 | } 55 | 56 | @Override 57 | public DownloadFuture execute() { 58 | EventLoopGroup group = RequestTool.group(); 59 | 60 | DownloadPromise downloadPromise = new DefaultDownloadPromise(group.next()) 61 | .setPath(downloadFolder); 62 | 63 | DownloadListener listener = new DownloadListener(downloadPromise, request, newName); 64 | 65 | new AsyncClient(group, method, uri) 66 | .setHeader(HttpHeaderNames.AUTHORIZATION, accessToken) 67 | .execute() 68 | .addListener(listener); 69 | 70 | return downloadPromise; 71 | } 72 | 73 | static class DownloadListener implements ResponseFutureListener { 74 | private final DownloadPromise promise; 75 | private final DefaultFullHttpRequest request; 76 | private final @Nullable String newName; 77 | 78 | DownloadListener(DownloadPromise promise, DefaultFullHttpRequest request, 79 | @Nullable String newName) { 80 | this.promise = promise; 81 | this.request = request; 82 | this.newName = newName; 83 | } 84 | 85 | @Override public void operationComplete(ResponseFuture future) 86 | throws ExecutionException, InterruptedException, ErrorResponseException, MalformedURLException { 87 | HttpResponse response = future.response(); 88 | ByteBufStream result = future.get(); 89 | 90 | // if response is valid 91 | if (!future.isSuccess()) { 92 | // TODO: handle error 93 | } 94 | else if (response.status().code() == HTTP_MOVED_TEMP) { 95 | String uriStr = response.headers().get(HttpHeaderNames.LOCATION); 96 | URL url = new URL(uriStr); 97 | 98 | String host = url.getHost(); 99 | int port = 443; 100 | 101 | // set downloadPromise's URI 102 | promise.setURI(url); 103 | 104 | // change request's url to location of file 105 | request.setUri(uriStr); 106 | 107 | AsyncDownloadHandler downloadHandler = new AsyncDownloadHandler(promise, newName); 108 | 109 | // Configure the client. 110 | Bootstrap bootstrap = new Bootstrap() 111 | .group(RequestTool.group()) 112 | .channel(RequestTool.socketChannelClass()) 113 | .handler(new AsyncDefaultInitializer(downloadHandler)); 114 | 115 | // wait until be connected, and get channel 116 | Channel channel = bootstrap.connect(host, port).syncUninterruptibly().channel(); 117 | 118 | // Send the HTTP request. 119 | channel.writeAndFlush(request); 120 | } 121 | else { 122 | try { 123 | RequestTool.errorHandling(response, result, HTTP_MOVED_TEMP); 124 | } 125 | catch (Exception e) { 126 | promise.setFailure(e); 127 | throw e; 128 | } 129 | } 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AsyncUploadClient.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import io.netty.bootstrap.Bootstrap; 5 | import io.netty.channel.EventLoopGroup; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import static io.netty.handler.codec.http.HttpMethod.PUT; 9 | 10 | /** 11 | * @author isac322 12 | */ 13 | public class AsyncUploadClient extends AbstractClient { 14 | private final UploadPromise uploadPromise; 15 | private final EventLoopGroup group; 16 | 17 | public AsyncUploadClient(@NotNull EventLoopGroup group, UploadPromise uploadPromise) { 18 | super(PUT, uploadPromise.uploadURI(), null); 19 | this.uploadPromise = uploadPromise; 20 | this.group = group; 21 | } 22 | 23 | 24 | @Override 25 | public UploadFuture execute() { 26 | String host = uri.getHost(); 27 | int port = 443; 28 | 29 | // Configure SSL context. 30 | 31 | AsyncUploadHandler clientHandler = new AsyncUploadHandler(uploadPromise, request); 32 | 33 | // Configure the client. 34 | Bootstrap bootstrap = new Bootstrap() 35 | .group(group) 36 | .channel(RequestTool.socketChannelClass()) 37 | .handler(new AsyncDefaultInitializer(clientHandler)); 38 | 39 | 40 | bootstrap.connect(host, port); 41 | 42 | return uploadPromise; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/AsyncUploadHandler.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.PooledByteBufAllocator; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | import io.netty.handler.codec.http.*; 8 | 9 | import java.io.IOException; 10 | import java.nio.ByteBuffer; 11 | import java.nio.channels.FileChannel; 12 | import java.nio.file.StandardOpenOption; 13 | 14 | import static io.netty.handler.codec.http.HttpHeaderNames.*; 15 | import static io.netty.handler.codec.http.HttpHeaderValues.CLOSE; 16 | import static java.net.HttpURLConnection.*; 17 | 18 | /** 19 | * @author isac322 20 | */ 21 | class AsyncUploadHandler extends SimpleChannelInboundHandler { 22 | private static final int UPLOAD_FRAGMENT_SIZE_MIN = 320 * 1024; 23 | private static final int UPLOAD_FRAGMENT_SIZE_MAX = 320 * 1024 * 32; 24 | private final UploadPromise promise; 25 | private final FullHttpRequest request; 26 | private final ByteBuf byteBuf; 27 | private FileChannel fileChannel; 28 | private int status; 29 | private int currentFragSize; 30 | private long currentFilePosition; 31 | 32 | public AsyncUploadHandler(UploadPromise promise, DefaultFullHttpRequest request) { 33 | this.promise = promise; 34 | this.byteBuf = PooledByteBufAllocator.DEFAULT.directBuffer(UPLOAD_FRAGMENT_SIZE_MAX); 35 | // TODO: `AsyncUploadClient` would be useless (make request independently in refactoring) 36 | request.content().release(); 37 | this.request = request.replace(byteBuf); 38 | this.request.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE); 39 | 40 | currentFragSize = 0; 41 | currentFilePosition = 0; 42 | } 43 | 44 | @Override 45 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 46 | super.channelActive(ctx); 47 | fileChannel = FileChannel.open(promise.filePath(), StandardOpenOption.READ); 48 | ctx.writeAndFlush(nextRequest()); 49 | } 50 | 51 | @Override 52 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 53 | super.exceptionCaught(ctx, cause); 54 | promise.setFailure(cause); 55 | ctx.close(); 56 | } 57 | 58 | @Override 59 | public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 60 | super.channelReadComplete(ctx); 61 | ctx.flush(); 62 | } 63 | 64 | private FullHttpRequest nextRequest() throws IOException { 65 | if (currentFragSize < UPLOAD_FRAGMENT_SIZE_MAX) currentFragSize += UPLOAD_FRAGMENT_SIZE_MIN << 2; 66 | 67 | // reset internal buffer status 68 | byteBuf.clear().writerIndex(currentFragSize).retain(); 69 | 70 | // read from file channel 71 | ByteBuffer nioBuffer = byteBuf.internalNioBuffer(0, currentFragSize); 72 | int readBytes = fileChannel.read(nioBuffer); 73 | 74 | long oldPosition = currentFilePosition; 75 | currentFilePosition += readBytes; 76 | 77 | // update request with new range 78 | request.headers() 79 | .set(CONTENT_LENGTH, readBytes) 80 | .set(CONTENT_RANGE, 81 | "bytes " + oldPosition + '-' + (currentFilePosition - 1) + '/' + fileChannel.size()); 82 | 83 | // if this is last request, release internal buffer 84 | if (currentFilePosition == fileChannel.size()) { 85 | request.headers().set(CONNECTION, CLOSE); 86 | byteBuf.release(); 87 | } 88 | 89 | return request; 90 | } 91 | 92 | @Override 93 | protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { 94 | if (msg instanceof HttpResponse) { 95 | HttpResponse response = (HttpResponse) msg; 96 | status = response.status().code(); 97 | } 98 | 99 | if (msg instanceof HttpContent) { 100 | if (msg instanceof LastHttpContent) { 101 | switch (status) { 102 | case HTTP_ACCEPTED: 103 | ctx.write(nextRequest()); 104 | break; 105 | case HTTP_OK: 106 | case HTTP_CREATED: 107 | ctx.close(); 108 | fileChannel.close(); 109 | // TODO: fill argument 110 | promise.trySuccess(null); 111 | break; 112 | default: 113 | break; 114 | } 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DefaultDownloadPromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.handler.codec.http.HttpResponse; 4 | import io.netty.util.concurrent.DefaultPromise; 5 | import io.netty.util.concurrent.EventExecutor; 6 | import io.netty.util.concurrent.Future; 7 | import io.netty.util.concurrent.GenericFutureListener; 8 | 9 | import java.io.File; 10 | import java.net.URL; 11 | import java.nio.file.Path; 12 | 13 | /** 14 | * @author isac322 15 | */ 16 | public class DefaultDownloadPromise extends DefaultPromise implements DownloadPromise { 17 | protected Path downloadPath; 18 | protected URL remoteUri; 19 | protected HttpResponse response; 20 | 21 | public DefaultDownloadPromise(EventExecutor executor) { 22 | super(executor); 23 | } 24 | 25 | @Override public Path downloadPath() { 26 | return downloadPath; 27 | } 28 | 29 | @Override public URL remoteURI() { 30 | return remoteUri; 31 | } 32 | 33 | @Override public HttpResponse response() { 34 | return response; 35 | } 36 | 37 | @Override public DefaultDownloadPromise setResponse(HttpResponse response) { 38 | this.response = response; 39 | return this; 40 | } 41 | 42 | @Override public DefaultDownloadPromise setURI(URL remoteUri) { 43 | this.remoteUri = remoteUri; 44 | return this; 45 | } 46 | 47 | @Override public DefaultDownloadPromise setPath(Path downloadPath) { 48 | this.downloadPath = downloadPath; 49 | return this; 50 | } 51 | 52 | 53 | @Override public DefaultDownloadPromise setSuccess(File result) { 54 | super.setSuccess(result); 55 | return this; 56 | } 57 | 58 | @Override public DefaultDownloadPromise setFailure(Throwable cause) { 59 | super.setFailure(cause); 60 | return this; 61 | } 62 | 63 | @Override 64 | public DefaultDownloadPromise addListener(GenericFutureListener> listener) { 65 | super.addListener(listener); 66 | return this; 67 | } 68 | 69 | @Override 70 | public DefaultDownloadPromise addListeners(GenericFutureListener>[] listeners) { 71 | super.addListeners(listeners); 72 | return this; 73 | } 74 | 75 | @Override 76 | public DefaultDownloadPromise removeListener(GenericFutureListener> listener) { 77 | super.removeListener(listener); 78 | return this; 79 | } 80 | 81 | @Override 82 | public DefaultDownloadPromise removeListeners(GenericFutureListener>[] listeners) { 83 | super.removeListeners(listeners); 84 | return this; 85 | } 86 | 87 | @Override public DefaultDownloadPromise await() throws InterruptedException { 88 | super.await(); 89 | return this; 90 | } 91 | 92 | @Override public DefaultDownloadPromise awaitUninterruptibly() { 93 | super.awaitUninterruptibly(); 94 | return this; 95 | } 96 | 97 | @Override public DefaultDownloadPromise sync() throws InterruptedException { 98 | super.sync(); 99 | return this; 100 | } 101 | 102 | @Override public DefaultDownloadPromise syncUninterruptibly() { 103 | super.syncUninterruptibly(); 104 | return this; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DefaultDriveItemPromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.container.items.DriveItem; 4 | import io.netty.util.concurrent.DefaultPromise; 5 | import io.netty.util.concurrent.EventExecutor; 6 | import io.netty.util.concurrent.Future; 7 | import io.netty.util.concurrent.GenericFutureListener; 8 | 9 | /** 10 | * @author isac322 11 | */ 12 | public class DefaultDriveItemPromise extends DefaultPromise implements DriveItemPromise { 13 | public DefaultDriveItemPromise(EventExecutor executor) { 14 | super(executor); 15 | } 16 | 17 | @Override public DefaultDriveItemPromise setSuccess(DriveItem result) { 18 | super.setSuccess(result); 19 | return this; 20 | } 21 | 22 | @Override public DefaultDriveItemPromise setFailure(Throwable cause) { 23 | super.setFailure(cause); 24 | return this; 25 | } 26 | 27 | @Override 28 | public DefaultDriveItemPromise addListener(GenericFutureListener> listener) { 29 | super.addListener(listener); 30 | return this; 31 | } 32 | 33 | @Override 34 | public DefaultDriveItemPromise addListeners( 35 | GenericFutureListener>[] listeners) { 36 | super.addListeners(listeners); 37 | return this; 38 | } 39 | 40 | @Override 41 | public DefaultDriveItemPromise removeListener( 42 | GenericFutureListener> listener) { 43 | super.removeListener(listener); 44 | return this; 45 | } 46 | 47 | @Override public DefaultDriveItemPromise removeListeners( 48 | GenericFutureListener>[] listeners) { 49 | super.removeListeners(listeners); 50 | return this; 51 | } 52 | 53 | @Override public DefaultDriveItemPromise await() throws InterruptedException { 54 | super.await(); 55 | return this; 56 | } 57 | 58 | @Override public DefaultDriveItemPromise awaitUninterruptibly() { 59 | super.awaitUninterruptibly(); 60 | return this; 61 | } 62 | 63 | @Override public DefaultDriveItemPromise sync() throws InterruptedException { 64 | super.sync(); 65 | return this; 66 | } 67 | 68 | @Override public DefaultDriveItemPromise syncUninterruptibly() { 69 | super.syncUninterruptibly(); 70 | return this; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DefaultResponsePromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.utils.ByteBufStream; 4 | import io.netty.channel.Channel; 5 | import io.netty.handler.codec.http.HttpResponse; 6 | import io.netty.util.concurrent.DefaultPromise; 7 | import io.netty.util.concurrent.EventExecutor; 8 | import io.netty.util.concurrent.Future; 9 | import io.netty.util.concurrent.GenericFutureListener; 10 | 11 | /** 12 | * @author isac322 13 | */ 14 | public class DefaultResponsePromise extends DefaultPromise implements ResponsePromise { 15 | protected HttpResponse response; 16 | protected Channel channel; 17 | 18 | public DefaultResponsePromise(EventExecutor executor) { 19 | super(executor); 20 | } 21 | 22 | @Override public HttpResponse response() { 23 | return response; 24 | } 25 | 26 | @Override public ResponsePromise setResponse(HttpResponse response) { 27 | this.response = response; 28 | return this; 29 | } 30 | 31 | @Override public ResponsePromise setChannel(Channel channel) { 32 | this.channel = channel; 33 | return this; 34 | } 35 | 36 | @Override public Channel channel() { 37 | return channel; 38 | } 39 | 40 | @Override public boolean trySuccess(ByteBufStream result) { 41 | result.setNoMoreBuf(); 42 | return super.trySuccess(result); 43 | } 44 | 45 | @Override public ResponsePromise setSuccess(ByteBufStream result) { 46 | result.setNoMoreBuf(); 47 | super.setSuccess(result); 48 | return this; 49 | } 50 | 51 | @Override public ResponsePromise setFailure(Throwable cause) { 52 | super.setFailure(cause); 53 | return this; 54 | } 55 | 56 | @Override public ResponsePromise addListener( 57 | GenericFutureListener> listener) { 58 | super.addListener(listener); 59 | return this; 60 | } 61 | 62 | @Override public ResponsePromise addListeners( 63 | GenericFutureListener>[] listeners) { 64 | super.addListeners(listeners); 65 | return this; 66 | } 67 | 68 | @Override public ResponsePromise removeListener( 69 | GenericFutureListener> listener) { 70 | super.removeListener(listener); 71 | return this; 72 | } 73 | 74 | @Override public ResponsePromise removeListeners( 75 | GenericFutureListener>[] listeners) { 76 | super.removeListeners(listeners); 77 | return this; 78 | } 79 | 80 | @Override public ResponsePromise await() throws InterruptedException { 81 | super.await(); 82 | return this; 83 | } 84 | 85 | @Override public ResponsePromise awaitUninterruptibly() { 86 | super.awaitUninterruptibly(); 87 | return this; 88 | } 89 | 90 | @Override public ResponsePromise sync() throws InterruptedException { 91 | super.sync(); 92 | return this; 93 | } 94 | 95 | @Override public ResponsePromise syncUninterruptibly() { 96 | super.syncUninterruptibly(); 97 | return this; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DefaultUploadPromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.container.items.FileItem; 4 | import io.netty.util.concurrent.DefaultPromise; 5 | import io.netty.util.concurrent.EventExecutor; 6 | import io.netty.util.concurrent.Future; 7 | import io.netty.util.concurrent.GenericFutureListener; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.net.URI; 12 | import java.nio.file.Path; 13 | 14 | /** 15 | * @author isac322 16 | */ 17 | public class DefaultUploadPromise extends DefaultPromise implements UploadPromise { 18 | @NotNull private final Path filePath; 19 | @Nullable private URI uploadURI; 20 | 21 | 22 | public DefaultUploadPromise(EventExecutor executor, @NotNull Path filePath) { 23 | super(executor); 24 | this.filePath = filePath; 25 | } 26 | 27 | @Override public @NotNull Path filePath() { 28 | return filePath; 29 | } 30 | 31 | @Override public @Nullable URI uploadURI() { 32 | return uploadURI; 33 | } 34 | 35 | @Override public @NotNull UploadPromise setUploadURI(@NotNull URI uri) { 36 | this.uploadURI = uri; 37 | return this; 38 | } 39 | 40 | 41 | @Override public DefaultUploadPromise setSuccess(FileItem result) { 42 | super.setSuccess(result); 43 | return this; 44 | } 45 | 46 | @Override public DefaultUploadPromise setFailure(Throwable cause) { 47 | super.setFailure(cause); 48 | return this; 49 | } 50 | 51 | @Override 52 | public DefaultUploadPromise addListener(GenericFutureListener> listener) { 53 | super.addListener(listener); 54 | return this; 55 | } 56 | 57 | @Override 58 | public DefaultUploadPromise addListeners(GenericFutureListener>[] listeners) { 59 | super.addListeners(listeners); 60 | return this; 61 | } 62 | 63 | @Override 64 | public DefaultUploadPromise removeListener(GenericFutureListener> listener) { 65 | super.removeListener(listener); 66 | return this; 67 | } 68 | 69 | @Override 70 | public DefaultUploadPromise removeListeners( 71 | GenericFutureListener>[] listeners) { 72 | super.removeListeners(listeners); 73 | return this; 74 | } 75 | 76 | @Override public DefaultUploadPromise await() throws InterruptedException { 77 | super.await(); 78 | return this; 79 | } 80 | 81 | @Override public DefaultUploadPromise awaitUninterruptibly() { 82 | super.awaitUninterruptibly(); 83 | return this; 84 | } 85 | 86 | @Override public DefaultUploadPromise sync() throws InterruptedException { 87 | super.sync(); 88 | return this; 89 | } 90 | 91 | @Override public DefaultUploadPromise syncUninterruptibly() { 92 | super.syncUninterruptibly(); 93 | return this; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DownloadFuture.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.handler.codec.http.HttpResponse; 4 | import io.netty.util.concurrent.Future; 5 | import io.netty.util.concurrent.GenericFutureListener; 6 | 7 | import java.io.File; 8 | import java.net.URL; 9 | import java.nio.file.Path; 10 | 11 | /** 12 | * @author isac322 13 | */ 14 | public interface DownloadFuture extends Future { 15 | Path downloadPath(); 16 | 17 | URL remoteURI(); 18 | 19 | HttpResponse response(); 20 | 21 | 22 | @Override DownloadFuture addListener(GenericFutureListener> listener); 23 | 24 | @Override DownloadFuture addListeners(GenericFutureListener>[] listeners); 25 | 26 | @Override DownloadFuture removeListener(GenericFutureListener> listener); 27 | 28 | @Override DownloadFuture removeListeners(GenericFutureListener>[] listeners); 29 | 30 | @Override DownloadFuture sync() throws InterruptedException; 31 | 32 | @Override DownloadFuture syncUninterruptibly(); 33 | 34 | @Override DownloadFuture await() throws InterruptedException; 35 | 36 | @Override DownloadFuture awaitUninterruptibly(); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DownloadFutureListener.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.util.concurrent.GenericFutureListener; 4 | 5 | /** 6 | * @author isac322 7 | */ 8 | public interface DownloadFutureListener extends GenericFutureListener { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DownloadPromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.handler.codec.http.HttpResponse; 4 | import io.netty.util.concurrent.Future; 5 | import io.netty.util.concurrent.GenericFutureListener; 6 | import io.netty.util.concurrent.Promise; 7 | 8 | import java.io.File; 9 | import java.net.URL; 10 | import java.nio.file.Path; 11 | 12 | /** 13 | * @author isac322 14 | */ 15 | public interface DownloadPromise extends DownloadFuture, Promise { 16 | DownloadPromise setResponse(HttpResponse response); 17 | 18 | DownloadPromise setURI(URL remoteUri); 19 | 20 | DownloadPromise setPath(Path downloadPath); 21 | 22 | 23 | @Override DownloadPromise setSuccess(File result); 24 | 25 | @Override DownloadPromise setFailure(Throwable cause); 26 | 27 | @Override DownloadPromise addListener(GenericFutureListener> listener); 28 | 29 | @Override DownloadPromise addListeners(GenericFutureListener>[] listeners); 30 | 31 | @Override DownloadPromise removeListener(GenericFutureListener> listener); 32 | 33 | @Override DownloadPromise removeListeners(GenericFutureListener>[] listeners); 34 | 35 | @Override DownloadPromise sync() throws InterruptedException; 36 | 37 | @Override DownloadPromise syncUninterruptibly(); 38 | 39 | @Override DownloadPromise await() throws InterruptedException; 40 | 41 | @Override DownloadPromise awaitUninterruptibly(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DriveItemFuture.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.container.items.DriveItem; 4 | import io.netty.util.concurrent.Future; 5 | import io.netty.util.concurrent.GenericFutureListener; 6 | 7 | /** 8 | * @author isac322 9 | */ 10 | public interface DriveItemFuture extends Future { 11 | @Override DriveItemFuture addListener(GenericFutureListener> listener); 12 | 13 | @Override DriveItemFuture addListeners(GenericFutureListener>[] listeners); 14 | 15 | @Override DriveItemFuture removeListener(GenericFutureListener> listener); 16 | 17 | @Override DriveItemFuture removeListeners(GenericFutureListener>[] listeners); 18 | 19 | @Override DriveItemFuture sync() throws InterruptedException; 20 | 21 | @Override DriveItemFuture syncUninterruptibly(); 22 | 23 | @Override DriveItemFuture await() throws InterruptedException; 24 | 25 | @Override DriveItemFuture awaitUninterruptibly(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DriveItemHandler.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.client.RequestTool; 4 | import com.bhyoo.onedrive.container.items.DriveItem; 5 | import com.bhyoo.onedrive.utils.ByteBufStream; 6 | import io.netty.channel.ChannelHandlerContext; 7 | import io.netty.channel.SimpleChannelInboundHandler; 8 | import io.netty.handler.codec.http.HttpContent; 9 | import io.netty.handler.codec.http.HttpObject; 10 | import io.netty.handler.codec.http.HttpResponse; 11 | import io.netty.handler.codec.http.LastHttpContent; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | import static java.net.HttpURLConnection.HTTP_OK; 16 | 17 | /** 18 | * @author isac322 19 | */ 20 | public class DriveItemHandler extends SimpleChannelInboundHandler { 21 | private final @NotNull DefaultDriveItemPromise promise; 22 | private final @NotNull RequestTool requestTool; 23 | private final ByteBufStream stream; 24 | private HttpResponse response; 25 | private DriveItem driveItem; 26 | private Thread workerThread; 27 | private @Nullable Exception workerException; 28 | 29 | private final int expectedCode; 30 | 31 | public DriveItemHandler(@NotNull DefaultDriveItemPromise promise, @NotNull RequestTool requestTool) { 32 | this.promise = promise; 33 | this.requestTool = requestTool; 34 | this.stream = new ByteBufStream(); 35 | this.expectedCode = HTTP_OK; 36 | } 37 | 38 | public DriveItemHandler(@NotNull DefaultDriveItemPromise promise, 39 | @NotNull RequestTool requestTool, 40 | int expectedCode) { 41 | this.promise = promise; 42 | this.requestTool = requestTool; 43 | this.stream = new ByteBufStream(); 44 | this.expectedCode = expectedCode; 45 | } 46 | 47 | @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 48 | super.exceptionCaught(ctx, cause); 49 | promise.setFailure(cause); 50 | if (!stream.isClosed()) stream.close(); 51 | ctx.close(); 52 | } 53 | 54 | @Override protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { 55 | if (msg instanceof HttpResponse) { 56 | this.response = (HttpResponse) msg; 57 | 58 | workerThread = new Thread() { 59 | @Override public void run() { 60 | try { 61 | driveItem = requestTool.parseDriveItemAndHandle(response, stream, expectedCode); 62 | } 63 | catch (Exception e) { 64 | workerException = e; 65 | } 66 | } 67 | }; 68 | workerThread.start(); 69 | } 70 | else if (msg instanceof HttpContent) { 71 | HttpContent content = (HttpContent) msg; 72 | 73 | if (content instanceof LastHttpContent) { 74 | ctx.close(); 75 | stream.setNoMoreBuf(); 76 | workerThread.join(); 77 | 78 | if (workerException != null) { 79 | promise.setFailure(workerException); 80 | } 81 | else if (response.status().code() == expectedCode) { 82 | promise.setSuccess(driveItem); 83 | } 84 | else { 85 | throw new IllegalStateException( 86 | "HTTP response code is not " + expectedCode + " and not occurs any exception"); 87 | } 88 | } 89 | else { 90 | stream.writeByteBuf(content.content()); 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/DriveItemPromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.container.items.DriveItem; 4 | import io.netty.util.concurrent.Future; 5 | import io.netty.util.concurrent.GenericFutureListener; 6 | import io.netty.util.concurrent.Promise; 7 | 8 | /** 9 | * @author isac322 10 | */ 11 | public interface DriveItemPromise extends DriveItemFuture, Promise { 12 | @Override DriveItemPromise setSuccess(DriveItem result); 13 | 14 | @Override DriveItemPromise setFailure(Throwable cause); 15 | 16 | @Override DriveItemPromise addListener(GenericFutureListener> listener); 17 | 18 | @Override DriveItemPromise addListeners(GenericFutureListener>[] listeners); 19 | 20 | @Override DriveItemPromise removeListener(GenericFutureListener> listener); 21 | 22 | @Override DriveItemPromise removeListeners(GenericFutureListener>[] listeners); 23 | 24 | @Override DriveItemPromise sync() throws InterruptedException; 25 | 26 | @Override DriveItemPromise syncUninterruptibly(); 27 | 28 | @Override DriveItemPromise await() throws InterruptedException; 29 | 30 | @Override DriveItemPromise awaitUninterruptibly(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/ResponseFuture.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.utils.ByteBufStream; 4 | import io.netty.channel.Channel; 5 | import io.netty.handler.codec.http.HttpResponse; 6 | import io.netty.util.concurrent.Future; 7 | import io.netty.util.concurrent.GenericFutureListener; 8 | 9 | /** 10 | * @author isac322 11 | */ 12 | public interface ResponseFuture extends Future { 13 | HttpResponse response(); 14 | 15 | Channel channel(); 16 | 17 | @Override 18 | ResponseFuture addListener(GenericFutureListener> listener); 19 | 20 | @Override 21 | ResponseFuture addListeners(GenericFutureListener>[] listeners); 22 | 23 | @Override 24 | ResponseFuture removeListener(GenericFutureListener> listener); 25 | 26 | @Override 27 | ResponseFuture removeListeners(GenericFutureListener>[] listeners); 28 | 29 | @Override ResponseFuture sync() throws InterruptedException; 30 | 31 | @Override ResponseFuture syncUninterruptibly(); 32 | 33 | @Override ResponseFuture await() throws InterruptedException; 34 | 35 | @Override ResponseFuture awaitUninterruptibly(); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/ResponseFutureListener.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import io.netty.util.concurrent.GenericFutureListener; 4 | 5 | /** 6 | * @author isac322 7 | */ 8 | public interface ResponseFutureListener extends GenericFutureListener { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/ResponsePromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.utils.ByteBufStream; 4 | import io.netty.channel.Channel; 5 | import io.netty.handler.codec.http.HttpResponse; 6 | import io.netty.util.concurrent.Future; 7 | import io.netty.util.concurrent.GenericFutureListener; 8 | import io.netty.util.concurrent.Promise; 9 | 10 | /** 11 | * @author isac322 12 | */ 13 | public interface ResponsePromise extends ResponseFuture, Promise { 14 | ResponsePromise setResponse(HttpResponse response); 15 | 16 | ResponsePromise setChannel(Channel channel); 17 | 18 | 19 | @Override ResponsePromise setSuccess(ByteBufStream result); 20 | 21 | @Override ResponsePromise setFailure(Throwable cause); 22 | 23 | @Override 24 | ResponsePromise addListener(GenericFutureListener> listener); 25 | 26 | @Override 27 | ResponsePromise addListeners(GenericFutureListener>[] listeners); 28 | 29 | @Override 30 | ResponsePromise removeListener(GenericFutureListener> listener); 31 | 32 | @Override ResponsePromise removeListeners( 33 | GenericFutureListener>[] listeners); 34 | 35 | @Override ResponsePromise sync() throws InterruptedException; 36 | 37 | @Override ResponsePromise syncUninterruptibly(); 38 | 39 | @Override ResponsePromise await() throws InterruptedException; 40 | 41 | @Override ResponsePromise awaitUninterruptibly(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/UploadFuture.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.container.items.FileItem; 4 | import io.netty.util.concurrent.Future; 5 | import io.netty.util.concurrent.GenericFutureListener; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | import java.nio.file.Path; 9 | 10 | /** 11 | * @author isac322 12 | */ 13 | public interface UploadFuture extends Future { 14 | @NotNull Path filePath(); 15 | 16 | @Override UploadFuture addListener(GenericFutureListener> listener); 17 | 18 | @Override UploadFuture addListeners(GenericFutureListener>[] listeners); 19 | 20 | @Override UploadFuture removeListener(GenericFutureListener> listener); 21 | 22 | @Override UploadFuture removeListeners(GenericFutureListener>[] listeners); 23 | 24 | @Override UploadFuture sync() throws InterruptedException; 25 | 26 | @Override UploadFuture syncUninterruptibly(); 27 | 28 | @Override UploadFuture await() throws InterruptedException; 29 | 30 | @Override UploadFuture awaitUninterruptibly(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/async/UploadPromise.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.async; 2 | 3 | import com.bhyoo.onedrive.container.items.FileItem; 4 | import io.netty.util.concurrent.Future; 5 | import io.netty.util.concurrent.GenericFutureListener; 6 | import io.netty.util.concurrent.Promise; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.net.URI; 11 | 12 | /** 13 | * @author isac322 14 | */ 15 | public interface UploadPromise extends UploadFuture, Promise { 16 | @Nullable URI uploadURI(); 17 | 18 | @NotNull UploadPromise setUploadURI(@NotNull URI uri); 19 | 20 | 21 | @Override UploadPromise setSuccess(FileItem result); 22 | 23 | @Override UploadPromise setFailure(Throwable cause); 24 | 25 | @Override UploadPromise addListener(GenericFutureListener> listener); 26 | 27 | @Override UploadPromise addListeners(GenericFutureListener>[] listeners); 28 | 29 | @Override UploadPromise removeListener(GenericFutureListener> listener); 30 | 31 | @Override UploadPromise removeListeners(GenericFutureListener>[] listeners); 32 | 33 | @Override UploadPromise sync() throws InterruptedException; 34 | 35 | @Override UploadPromise syncUninterruptibly(); 36 | 37 | @Override UploadPromise await() throws InterruptedException; 38 | 39 | @Override UploadPromise awaitUninterruptibly(); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/network/sync/SyncResponse.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.network.sync; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import lombok.Getter; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.net.URL; 8 | import java.nio.charset.StandardCharsets; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author isac322 14 | */ 15 | public class SyncResponse { 16 | @Getter protected final URL url; 17 | @Getter protected final int code; 18 | @Getter protected final String message; 19 | @Getter protected final Map> header; 20 | @Getter protected final ByteBuf contentBuf; 21 | protected String contentString; 22 | 23 | public SyncResponse(URL url, int code, String message, 24 | Map> header, ByteBuf contentBuf) { 25 | this.url = url; 26 | this.code = code; 27 | this.message = message; 28 | this.header = header; 29 | this.contentBuf = contentBuf; 30 | } 31 | 32 | /** 33 | * For programmer's convenience, return decoded HTTP response's body as {@code String}.
34 | * Always decode with UTF-8.
35 | * If you want to decode the body with another encoding, you should call {@code getContent()} and decode manually. 36 | * 37 | * @return HTTP response body as {@code String}. Body is forced to decode with UTF-8. 38 | */ 39 | @NotNull 40 | public String getContentString() { 41 | if (contentString == null) { 42 | contentString = new String(contentBuf.array(), 0, contentBuf.readableBytes(), StandardCharsets.UTF_8); 43 | } 44 | 45 | return contentString; 46 | } 47 | 48 | public byte[] getContent() { 49 | return getContent(true); 50 | } 51 | 52 | public byte[] getContent(boolean autoRelease) { 53 | byte[] array = contentBuf.array(); 54 | if (autoRelease) release(); 55 | return array; 56 | } 57 | 58 | public void release() { 59 | contentBuf.release(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/bhyoo/onedrive/utils/ByteBufStream.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.utils; 2 | 3 | import com.bhyoo.onedrive.exceptions.InternalException; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.buffer.CompositeByteBuf; 6 | import io.netty.buffer.PooledByteBufAllocator; 7 | import lombok.Getter; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.io.InputStream; 11 | 12 | /** 13 | * @author isac322 14 | */ 15 | public class ByteBufStream extends InputStream { 16 | @NotNull private static final IndexOutOfBoundsException INDEX_EXCEPTION = new IndexOutOfBoundsException(); 17 | @NotNull final private CompositeByteBuf compositeBuf; 18 | private boolean noMoreBuf; 19 | @Getter private boolean closed; 20 | 21 | 22 | public ByteBufStream() { 23 | this(PooledByteBufAllocator.DEFAULT.compositeBuffer()); 24 | } 25 | 26 | public ByteBufStream(@NotNull CompositeByteBuf byteBuf) { 27 | compositeBuf = byteBuf; 28 | } 29 | 30 | 31 | public ByteBuf getRawBuffer() { 32 | return compositeBuf.duplicate().readerIndex(0); 33 | } 34 | 35 | 36 | public synchronized void setNoMoreBuf() { 37 | noMoreBuf = true; 38 | notifyAll(); 39 | } 40 | 41 | 42 | /** 43 | * Closes this input stream and releases any system resources associated with the stream. 44 | */ 45 | @Override 46 | public synchronized void close() { 47 | if (closed) throw new IllegalStateException("The stream already closed"); 48 | 49 | noMoreBuf = closed = true; 50 | compositeBuf.release(); 51 | notifyAll(); 52 | } 53 | 54 | 55 | /** 56 | * {@inheritDoc} 57 | */ 58 | @Override 59 | public synchronized int read() { 60 | while (!closed && !noMoreBuf && !compositeBuf.isReadable()) { 61 | try { 62 | wait(); 63 | } 64 | catch (InterruptedException e) { 65 | throw new InternalException("wait() is wrong in " + this.getClass().getName() + ".", e); 66 | } 67 | } 68 | 69 | return !closed && compositeBuf.isReadable() ? compositeBuf.readByte() : -1; 70 | } 71 | 72 | 73 | /** 74 | * {@inheritDoc} 75 | */ 76 | @Override 77 | public synchronized int read(@NotNull byte[] b) { 78 | return read(b, 0, b.length); 79 | } 80 | 81 | 82 | /** 83 | * {@inheritDoc} 84 | */ 85 | @Override 86 | public synchronized int read(@NotNull byte[] b, int off, int len) { 87 | if (off < 0 || len < 0 || len > b.length - off) throw INDEX_EXCEPTION; 88 | else if (len == 0) return 0; 89 | else if (closed) return -1; 90 | 91 | final int end = len + off - 1; 92 | int cur = off; 93 | 94 | while (cur <= end) { 95 | while (!closed && !noMoreBuf && !compositeBuf.isReadable()) { 96 | try { 97 | wait(); 98 | } 99 | catch (InterruptedException e) { 100 | throw new InternalException("wait() is wrong in " + this.getClass().getName() + ".", e); 101 | } 102 | } 103 | 104 | if (closed) return cur == off ? -1 : cur - off; 105 | else if (compositeBuf.isReadable()) { 106 | int fetched = Math.min(compositeBuf.readableBytes(), end - cur + 1); 107 | compositeBuf.readBytes(b, cur, fetched); 108 | cur += fetched; 109 | } 110 | else if (noMoreBuf) return cur == off ? -1 : cur - off; 111 | } 112 | 113 | return len; 114 | } 115 | 116 | /** 117 | * Write {@code sourceBuf}'s content to this stream without copy. 118 | * This method will take ownership of {@code sourceBuf}. 119 | * 120 | * @param sourceBuf A {@link ByteBuf} to write 121 | */ 122 | public synchronized void writeByteBuf(@NotNull ByteBuf sourceBuf) { 123 | if (closed || noMoreBuf) throw new IllegalStateException("The stream already closed"); 124 | sourceBuf.retain(); 125 | compositeBuf.addComponent(true, sourceBuf); 126 | notifyAll(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/test/java/com/bhyoo/onedrive/RequestToolTest.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.client.RequestTool; 5 | import com.bhyoo.onedrive.container.items.DriveItem; 6 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 7 | import com.bhyoo.onedrive.network.async.DriveItemFuture; 8 | import com.bhyoo.onedrive.network.async.ResponseFuture; 9 | import io.netty.handler.codec.http.HttpMethod; 10 | import org.junit.jupiter.api.AfterAll; 11 | import org.junit.jupiter.api.BeforeAll; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static org.junit.jupiter.api.Assertions.*; 15 | 16 | /** 17 | * @author isac322 18 | */ 19 | class RequestToolTest { 20 | private static Client client; 21 | private static RequestTool requestTool; 22 | 23 | @BeforeAll 24 | static void getClient() { 25 | assertNull(client); 26 | 27 | final String clientId = "f21d2eff-49e2-4a10-a515-4a077f23c694"; 28 | final String[] scope = {"files.readwrite.all", "offline_access"}; 29 | final String redirectURL = "http://localhost:8080/"; 30 | final String clientSecret = "1t5UhiBewLrVUoKqWZWYiiS"; 31 | 32 | client = new Client(clientId, scope, redirectURL, clientSecret); 33 | 34 | assertNotNull(client); 35 | assertTrue(client.isLogin()); 36 | assertFalse(client.isExpired()); 37 | 38 | assertNotNull(client.getAccessToken()); 39 | assertNotNull(client.getAuthCode()); 40 | assertNotNull(client.getClientId()); 41 | assertNotNull(client.getClientSecret()); 42 | assertNotNull(client.getFullToken()); 43 | assertNotNull(client.getRedirectURL()); 44 | assertNotNull(client.getRefreshToken()); 45 | assertNotNull(client.getTokenType()); 46 | assertArrayEquals(client.getScopes(), scope); 47 | assertNotEquals(client.getExpirationTime(), 0L); 48 | 49 | requestTool = client.requestTool(); 50 | 51 | System.out.println(client.getFullToken()); 52 | } 53 | 54 | @AfterAll 55 | static void logout() { 56 | assertNotNull(client); 57 | assertTrue(client.isLogin()); 58 | 59 | // client.logout(); 60 | 61 | // assertFalse(client.isLogin()); 62 | } 63 | 64 | @Test void getItemAsync() { 65 | DriveItemFuture future2 = requestTool.getItemAsync("/drive/items/D4FD82CA6DF96A47!25786") 66 | .syncUninterruptibly(); 67 | /* DriveItemFuture future = requestTool.getItemAsync(Client.ITEM_ID_PREFIX + "D4FD82CA6DF96A47!25784") 68 | .syncUninterruptibly(); 69 | 70 | if (future.isSuccess()) { 71 | System.out.println(future.get()); 72 | }*/ 73 | } 74 | 75 | @Test void getItem() throws ErrorResponseException { 76 | long before = System.currentTimeMillis(); 77 | for (int i = 0; i < 100; i++) { 78 | long l = System.currentTimeMillis(); 79 | DriveItem item = requestTool.getItem(Client.ITEM_ID_PREFIX + ClientTest.MP3_UTF8_BIG); 80 | System.out.println(System.currentTimeMillis() - l); 81 | } 82 | System.out.println(System.currentTimeMillis() - before); 83 | } 84 | 85 | @Test void getItem1() throws ErrorResponseException { 86 | DriveItem item = requestTool.getItem(Client.ITEM_ID_PREFIX + "D4FD82CA6DF96A47!25784"); 87 | System.out.println(item.getName()); 88 | System.out.println(item.getId()); 89 | } 90 | 91 | @Test void compareJDKAndNetty() { 92 | long netty = 0; 93 | long jdk = 0, before; 94 | 95 | for (int i = 0; i < 100; i++) { 96 | before = System.currentTimeMillis(); 97 | 98 | ResponseFuture responseFuture = requestTool 99 | .doAsync(HttpMethod.GET, Client.ITEM_ID_PREFIX + "D4FD82CA6DF96A47!25784") 100 | .syncUninterruptibly(); 101 | 102 | responseFuture.getNow().close(); 103 | 104 | netty += System.currentTimeMillis() - before; 105 | 106 | before = System.currentTimeMillis(); 107 | requestTool.newRequest(Client.ITEM_ID_PREFIX + "D4FD82CA6DF96A47!25784").doGet(); 108 | jdk += System.currentTimeMillis() - before; 109 | } 110 | 111 | System.out.println("Netty : " + netty + ", JDK : " + jdk); 112 | } 113 | } -------------------------------------------------------------------------------- /src/test/java/com/bhyoo/onedrive/TestCases.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive; 2 | 3 | import com.bhyoo.onedrive.client.Client; 4 | import com.bhyoo.onedrive.container.AsyncJobMonitor; 5 | import com.bhyoo.onedrive.container.AsyncJobStatus; 6 | import com.bhyoo.onedrive.container.items.DriveItem; 7 | import com.bhyoo.onedrive.container.items.FileItem; 8 | import com.bhyoo.onedrive.container.items.FolderItem; 9 | import com.bhyoo.onedrive.container.items.pointer.PathPointer; 10 | import com.bhyoo.onedrive.exceptions.ErrorResponseException; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.junit.jupiter.api.AfterAll; 13 | import org.junit.jupiter.api.BeforeAll; 14 | import org.junit.jupiter.api.Test; 15 | 16 | import java.net.URISyntaxException; 17 | import java.net.URL; 18 | import java.nio.file.Path; 19 | import java.nio.file.Paths; 20 | 21 | import static org.junit.jupiter.api.Assertions.*; 22 | 23 | class TestCases { 24 | private static final String TEST_DIR_NAME = "___for_test"; 25 | private static Client client; 26 | 27 | @BeforeAll 28 | static void getClient() { 29 | assertNull(client); 30 | 31 | final String clientId = "0c4b69a8-adac-4ec1-b310-6c28ff9fa263"; 32 | final String[] scope = {"files.readwrite.all", "offline_access"}; 33 | final String redirectURL = "http://localhost:8080/"; 34 | final String clientSecret = "iqggDGYW25$;#$otqVUH024"; 35 | 36 | client = new Client(clientId, scope, redirectURL, clientSecret); 37 | 38 | 39 | assertNotNull(client); 40 | assertTrue(client.isLogin()); 41 | assertFalse(client.isExpired()); 42 | 43 | System.out.println(client.getFullToken()); 44 | 45 | assertNotNull(client.getAccessToken()); 46 | assertNotNull(client.getAuthCode()); 47 | assertNotNull(client.getClientId()); 48 | assertNotNull(client.getClientSecret()); 49 | assertNotNull(client.getFullToken()); 50 | assertNotNull(client.getRedirectURL()); 51 | assertNotNull(client.getRefreshToken()); 52 | assertNotNull(client.getTokenType()); 53 | assertArrayEquals(client.getScopes(), scope); 54 | assertNotEquals(client.getExpirationTime(), 0L); 55 | } 56 | 57 | @AfterAll 58 | static void logout() throws ErrorResponseException { 59 | assertNotNull(client); 60 | assertTrue(client.isLogin()); 61 | 62 | client.deleteItem(PathPointer.root.resolve(TEST_DIR_NAME)); 63 | 64 | client.logout(); 65 | 66 | assertFalse(client.isLogin()); 67 | } 68 | 69 | /** 70 | * Scenario: 71 | *

72 | * 1. create a directory on root dir 73 | * 2. upload an audio file to the dir 74 | * 3. rename the file 75 | * 4. copy the file to same directory with another name 76 | */ 77 | @Test 78 | void createDirAndUpload() throws ErrorResponseException, URISyntaxException { 79 | // Create directory '___for_test' in root directory of default drive of current account 80 | FolderItem testDir = client.createFolder(PathPointer.root, TEST_DIR_NAME); 81 | 82 | assertEquals(TEST_DIR_NAME, testDir.getName()); 83 | assertEquals( 84 | new PathPointer("/" + TEST_DIR_NAME, testDir.getDriveId()).toASCIIApi(), 85 | testDir.getPathPointer().toASCIIApi()); 86 | assertEquals(0L, testDir.getSize().longValue()); 87 | assertFalse(testDir.isDeleted()); 88 | assertFalse(testDir.isRoot()); 89 | assertFalse(testDir.isSpecial()); 90 | assertArrayEquals(new DriveItem[0], testDir.allChildren()); 91 | 92 | URL resource = ClassLoader.getSystemClassLoader().getResource("SampleAudio_0.7mb.mp3"); 93 | assertNotNull(resource); 94 | 95 | Path path = Paths.get(resource.toURI()); 96 | // Upload local file to '___for_test' asynchronously 97 | FileItem uploaded = (FileItem) testDir.simpleUploadFileAsync(path).awaitUninterruptibly().getNow(); 98 | 99 | assertNotNull(uploaded); 100 | assertEquals("SampleAudio_0.7mb.mp3", uploaded.getName()); 101 | assertEquals(TEST_DIR_NAME, uploaded.getParentReference().getPathPointer().getName()); 102 | 103 | // Rename the uploaded file to 'modified.mp3' 104 | uploaded.rename("modified.mp3"); 105 | 106 | assertNotNull(uploaded); 107 | assertEquals("modified.mp3", uploaded.getName()); 108 | 109 | // Copy the uploaded file to same directory with another name 'copied.mp3' 110 | @NotNull AsyncJobMonitor monitor = uploaded.copyTo(testDir, "copied.mp3"); 111 | 112 | System.out.println(monitor.getPercentageComplete()); 113 | // Wait until copy job is done 114 | while (monitor.getStatus() != AsyncJobStatus.COMPLETED) { 115 | monitor.update(); 116 | System.out.println(monitor.getPercentageComplete()); 117 | } 118 | 119 | assertTrue(testDir.isChildrenFetched()); 120 | assertEquals(0, testDir.childCount()); 121 | 122 | // Update children info `testDir` 123 | testDir.fetchChildren(); 124 | 125 | assertTrue(testDir.isChildrenFetched()); 126 | assertEquals(2, testDir.allChildren().length); 127 | for (DriveItem item : testDir.allChildren()) { 128 | assertTrue(item.getName().equals("copied.mp3") || item.getName().equals("modified.mp3")); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/com/bhyoo/onedrive/container/items/pointer/PathPointerTest.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.container.items.pointer; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | class PathPointerTest { 8 | @Test 9 | void regularPath1Depth() { 10 | PathPointer pointer = new PathPointer("/test"); 11 | 12 | assertNull(pointer.getDriveId()); 13 | assertNotNull(pointer.getReadablePath()); 14 | 15 | assertEquals("/test", pointer.getReadablePath()); 16 | assertEquals("/me/drive/root:/test", pointer.toApi()); 17 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 18 | } 19 | 20 | @Test 21 | void startsWithoutSlash() { 22 | assertThrows(IllegalArgumentException.class, () -> new PathPointer("name")); 23 | } 24 | 25 | @Test 26 | void withLeftSpaces() { 27 | PathPointer pointer = new PathPointer(" /test"); 28 | 29 | assertNull(pointer.getDriveId()); 30 | assertNotNull(pointer.getReadablePath()); 31 | 32 | assertEquals("/test", pointer.getReadablePath()); 33 | assertEquals("/me/drive/root:/test", pointer.toApi()); 34 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 35 | 36 | pointer = new PathPointer("\t\t/test"); 37 | 38 | assertNull(pointer.getDriveId()); 39 | assertNotNull(pointer.getReadablePath()); 40 | 41 | assertEquals("/test", pointer.getReadablePath()); 42 | assertEquals("/me/drive/root:/test", pointer.toApi()); 43 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 44 | } 45 | 46 | @Test 47 | void withRightSpaces() { 48 | PathPointer pointer = new PathPointer("/test "); 49 | 50 | assertNull(pointer.getDriveId()); 51 | assertNotNull(pointer.getReadablePath()); 52 | 53 | assertEquals("/test", pointer.getReadablePath()); 54 | assertEquals("/me/drive/root:/test", pointer.toApi()); 55 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 56 | 57 | pointer = new PathPointer("/test\t\t"); 58 | 59 | assertNull(pointer.getDriveId()); 60 | assertNotNull(pointer.getReadablePath()); 61 | 62 | assertEquals("/test", pointer.getReadablePath()); 63 | assertEquals("/me/drive/root:/test", pointer.toApi()); 64 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 65 | } 66 | 67 | @Test 68 | void withBothSpaces() { 69 | PathPointer pointer = new PathPointer(" /test "); 70 | 71 | assertNull(pointer.getDriveId()); 72 | assertNotNull(pointer.getReadablePath()); 73 | 74 | assertEquals("/test", pointer.getReadablePath()); 75 | assertEquals("/me/drive/root:/test", pointer.toApi()); 76 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 77 | 78 | pointer = new PathPointer("\t\t/test\t\t"); 79 | 80 | assertNull(pointer.getDriveId()); 81 | assertNotNull(pointer.getReadablePath()); 82 | 83 | assertEquals("/test", pointer.getReadablePath()); 84 | assertEquals("/me/drive/root:/test", pointer.toApi()); 85 | assertEquals("/me/drive/root:/test", pointer.toASCIIApi()); 86 | } 87 | 88 | @Test 89 | void nonAscii() { 90 | PathPointer pointer = new PathPointer("/한글"); 91 | 92 | assertNull(pointer.getDriveId()); 93 | assertNotNull(pointer.getReadablePath()); 94 | 95 | assertEquals("/한글", pointer.getReadablePath()); 96 | assertEquals("/me/drive/root:/한글", pointer.toApi()); 97 | assertEquals("/me/drive/root:/%ED%95%9C%EA%B8%80", pointer.toASCIIApi()); 98 | } 99 | 100 | @Test 101 | void root() { 102 | PathPointer pointer = new PathPointer("/"); 103 | 104 | assertNull(pointer.getDriveId()); 105 | assertNotNull(pointer.getReadablePath()); 106 | 107 | assertEquals("/", pointer.getReadablePath()); 108 | assertEquals("/me/drive/root", pointer.toApi()); 109 | assertEquals("/me/drive/root", pointer.toASCIIApi()); 110 | } 111 | 112 | @Test 113 | void urlEncodedName() { 114 | PathPointer pointer = new PathPointer("/%fe%f2.txt"); 115 | 116 | assertNull(pointer.getDriveId()); 117 | assertNotNull(pointer.getReadablePath()); 118 | 119 | assertEquals("/%fe%f2.txt", pointer.getReadablePath()); 120 | assertEquals("/me/drive/root:/%fe%f2.txt", pointer.toApi()); 121 | assertEquals("/me/drive/root:/%25fe%25f2.txt", pointer.toASCIIApi()); 122 | } 123 | 124 | @Test 125 | void resolveTest() { 126 | PathPointer pointer = new PathPointer("/test"); 127 | 128 | PathPointer resolved = pointer.resolve("inner"); 129 | 130 | assertNull(resolved.getDriveId()); 131 | assertNotNull(resolved.getReadablePath()); 132 | 133 | assertEquals("/test/inner", resolved.getReadablePath()); 134 | assertEquals("/me/drive/root:/test/inner", resolved.toApi()); 135 | assertEquals("/me/drive/root:/test/inner", resolved.toASCIIApi()); 136 | 137 | 138 | resolved = resolved.resolve("inner2"); 139 | 140 | assertNull(resolved.getDriveId()); 141 | assertNotNull(resolved.getReadablePath()); 142 | 143 | assertEquals("/test/inner/inner2", resolved.getReadablePath()); 144 | assertEquals("/me/drive/root:/test/inner/inner2", resolved.toApi()); 145 | assertEquals("/me/drive/root:/test/inner/inner2", resolved.toASCIIApi()); 146 | 147 | 148 | resolved = resolved.resolve("한글"); 149 | 150 | assertNull(resolved.getDriveId()); 151 | assertNotNull(resolved.getReadablePath()); 152 | 153 | assertEquals("/test/inner/inner2/한글", resolved.getReadablePath()); 154 | assertEquals("/me/drive/root:/test/inner/inner2/한글", resolved.toApi()); 155 | assertEquals("/me/drive/root:/test/inner/inner2/%ED%95%9C%EA%B8%80", resolved.toASCIIApi()); 156 | } 157 | } -------------------------------------------------------------------------------- /src/test/java/com/bhyoo/onedrive/utils/ByteBufStreamTest.java: -------------------------------------------------------------------------------- 1 | package com.bhyoo.onedrive.utils; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.function.Executable; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 11 | import static org.junit.jupiter.api.Assertions.assertEquals; 12 | import static org.junit.jupiter.api.Assertions.assertThrows; 13 | 14 | 15 | class ByteBufStreamTest { 16 | private static final byte[] first = {0, 1, 2, 3}, second = {4, 5, 6, 7}; 17 | 18 | @Test void testCase1() throws InterruptedException { 19 | ByteBuf buffer = Unpooled.buffer(); 20 | final ByteBufStream inputStream = new ByteBufStream(); 21 | 22 | Thread end = new Thread() { 23 | @Override public void run() { 24 | byte[] bytes = new byte[3]; 25 | int n; 26 | 27 | n = inputStream.read(bytes); 28 | assertEquals(3, n); 29 | assertEquals(first[0], bytes[0]); 30 | assertEquals(first[1], bytes[1]); 31 | assertEquals(first[2], bytes[2]); 32 | 33 | n = inputStream.read(bytes); 34 | assertEquals(3, n); 35 | assertEquals(first[3], bytes[0]); 36 | assertEquals(second[0], bytes[1]); 37 | assertEquals(second[1], bytes[2]); 38 | 39 | n = inputStream.read(bytes); 40 | assertEquals(2, n); 41 | assertEquals(second[2], bytes[0]); 42 | assertEquals(second[3], bytes[1]); 43 | 44 | n = inputStream.read(bytes); 45 | assertEquals(-1, n); 46 | } 47 | }; 48 | end.start(); 49 | 50 | TimeUnit.MILLISECONDS.sleep(50); 51 | buffer.writeBytes(first); 52 | inputStream.writeByteBuf(buffer); 53 | 54 | buffer = Unpooled.buffer(); 55 | buffer.writeBytes(second); 56 | inputStream.writeByteBuf(buffer); 57 | 58 | inputStream.setNoMoreBuf(); 59 | 60 | end.join(); 61 | 62 | inputStream.close(); 63 | } 64 | 65 | @Test void readEmptyStream() throws InterruptedException { 66 | ByteBuf buffer = Unpooled.buffer(); 67 | final ByteBufStream inputStream = new ByteBufStream(); 68 | 69 | Thread end = new Thread() { 70 | @Override public void run() { 71 | byte[] bytes = new byte[3]; 72 | int n; 73 | 74 | n = inputStream.read(bytes); 75 | assertEquals(-1, n); 76 | 77 | assertEquals(-1, inputStream.read()); 78 | } 79 | }; 80 | end.start(); 81 | 82 | TimeUnit.MILLISECONDS.sleep(50); 83 | 84 | inputStream.setNoMoreBuf(); 85 | 86 | end.join(); 87 | 88 | inputStream.close(); 89 | buffer.release(); 90 | } 91 | 92 | @Test void writeAfterClose() { 93 | final ByteBufStream stream = new ByteBufStream(); 94 | ByteBuf buf = Unpooled.buffer(100); 95 | buf.writeBytes(first); 96 | 97 | stream.writeByteBuf(buf); 98 | stream.close(); 99 | 100 | assertThrows(IllegalStateException.class, new Executable() { 101 | @Override public void execute() { 102 | ByteBuf buf = Unpooled.buffer(100); 103 | stream.writeByteBuf(buf); 104 | } 105 | }); 106 | } 107 | 108 | @Test void readAfterClosed() { 109 | ByteBufStream stream = new ByteBufStream(); 110 | stream.close(); 111 | 112 | assertEquals(-1, stream.read()); 113 | } 114 | 115 | @Test void readWithOffset() { 116 | ByteBufStream stream = new ByteBufStream(); 117 | ByteBuf buf = Unpooled.buffer(100); 118 | buf.writeBytes(first); 119 | buf.writeBytes(second); 120 | stream.writeByteBuf(buf); 121 | stream.setNoMoreBuf(); 122 | 123 | byte[] bytes = new byte[100]; 124 | byte[] expectedBytes = new byte[100]; 125 | 126 | expectedBytes[1] = first[0]; 127 | expectedBytes[2] = first[1]; 128 | expectedBytes[3] = first[2]; 129 | expectedBytes[4] = first[3]; 130 | expectedBytes[5] = second[0]; 131 | 132 | int n = stream.read(bytes, 1, 5); 133 | assertEquals(5, n); 134 | 135 | assertArrayEquals(expectedBytes, bytes); 136 | 137 | stream.close(); 138 | } 139 | } -------------------------------------------------------------------------------- /src/test/resources/SampleAudio_0.7mb.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isac322/OneDrive-SDK-java/3d517b4661f88101d4024662747ab44584a75372/src/test/resources/SampleAudio_0.7mb.mp3 --------------------------------------------------------------------------------