@@ -68,9 +68,9 @@ public OneDriveUploader(UploadLogger logger) {
6868 this .logger = logger ;
6969 setAuthProvider (AuthenticationProvider .ONEDRIVE );
7070 try {
71+ setRanges (new String [0 ]);
7172 refreshToken = Authenticator .getRefreshToken (AuthenticationProvider .ONEDRIVE );
7273 retrieveNewAccessToken ();
73- setRanges (new String [0 ]);
7474 } catch (Exception e ) {
7575 MessageUtil .sendConsoleException (e );
7676 setErrorOccurred (true );
@@ -79,6 +79,9 @@ public OneDriveUploader(UploadLogger logger) {
7979
8080 /**
8181 * Gets a new OneDrive access token for the authenticated user
82+ * @throws Exception if the clientId could not be decrypted
83+ * @throws IOException if the request could not be executed, or was not successful
84+ * @throws JSONException if the response does not contain the expected values
8285 */
8386 private void retrieveNewAccessToken () throws Exception {
8487 RequestBody requestBody = new FormBody .Builder ()
@@ -92,13 +95,15 @@ private void retrieveNewAccessToken() throws Exception {
9295 .url ("https://login.microsoftonline.com/common/oauth2/v2.0/token" )
9396 .post (requestBody )
9497 .build ();
95- Response response = DriveBackup .httpClient .newCall (request ).execute ();
96- JSONObject parsedResponse = new JSONObject (response .body ().string ());
97- response .close ();
98- if (!response .isSuccessful ()) {
99- return ;
98+ try (Response response = DriveBackup .httpClient .newCall (request ).execute ()) {
99+ JSONObject parsedResponse = new JSONObject (response .body ().string ());
100+ if (!response .isSuccessful ()) {
101+ String error = parsedResponse .optString ("error" );
102+ String description = parsedResponse .optString ("error_description" );
103+ throw new IOException (String .format ("%s : %s" , error , description ));
104+ }
105+ accessToken = parsedResponse .getString ("access_token" );
100106 }
101- accessToken = parsedResponse .getString ("access_token" );
102107 }
103108 @ Override
104109 public boolean isAuthenticated () {
@@ -262,11 +267,12 @@ private static String concatPath(@NotNull String lhs, @NotNull String rhs) {
262267 * creates all folders in the path if they don't already exist
263268 * @param path to create the folders for
264269 * @return FQID of the last folder in the path
265- * @throws IOException if the folder could not be created;
266- * or if the api request could not be executed due to cancellation, a connectivity problem or timeout.
270+ * @throws IOException if the request could not be executed
271+ * @throws GraphApiErrorException if the folder could not be found or created
272+ * @throws JSONException if the response does not contain the expected items
267273 */
268274 @ NotNull
269- private FQID createPath (@ NotNull String path ) throws IOException {
275+ private FQID createPath (@ NotNull String path ) throws IOException , GraphApiErrorException {
270276 Iterator <String > parts = Arrays .stream (path .split ("/" )).iterator ();
271277 FQID root = createRootFolder (parts .next ());
272278 while (parts .hasNext ()) {
@@ -281,25 +287,26 @@ private FQID createPath(@NotNull String path) throws IOException {
281287 * @param root of where to create the folder
282288 * @param folder name to create
283289 * @return FQID of the folder
284- * @throws IOException if the folder could not be created;
285- * or if the api request could not be executed due to cancellation, a connectivity problem or timeout.
290+ * @throws IOException if the request could not be executed
291+ * @throws GraphApiErrorException if the folder could not be found or created
292+ * @throws JSONException if the response does not contain the expected items
286293 */
287294 @ NotNull
288- private FQID createFolder (@ NotNull FQID root ,@ NotNull String folder ) throws IOException {
295+ private FQID createFolder (@ NotNull FQID root , @ NotNull String folder ) throws IOException , GraphApiErrorException {
289296 FQID item = getFolder (root , folder );
290297 if (item != null ) {
291298 return item ;
292299 }
293300 RequestBody requestBody = RequestBody .create ("{ \" name\" : \" " + folder
294- + "\" , \" folder\" : {}, \" @microsoft.graph.conflictBehavior\" : \" fail\" }" , jsonMediaType );
301+ + "\" , \" folder\" : {}, \" @microsoft.graph.conflictBehavior\" : \" fail\" }" , jsonMediaType );
295302 Request request = new Request .Builder ()
296- .addHeader ("Authorization" , "Bearer " + accessToken )
297- .url ("https://graph.microsoft.com/v1.0/drives/" + root .driveId + "/items/" + root .itemId + "/children" )
298- .post (requestBody )
299- .build ();
303+ .addHeader ("Authorization" , "Bearer " + accessToken )
304+ .url ("https://graph.microsoft.com/v1.0/drives/" + root .driveId + "/items/" + root .itemId + "/children" )
305+ .post (requestBody )
306+ .build ();
300307 try (Response response = DriveBackup .httpClient .newCall (request ).execute ()) {
301- if (! response .isSuccessful () ) {
302- throw new IOException ( "Couldn't create folder " + folder );
308+ if (response .code () != 201 ) {
309+ throw new GraphApiErrorException ( response );
303310 }
304311 JSONObject parsedResponse = new JSONObject (response .body ().string ());
305312 String driveId = parsedResponse .getJSONObject ("parentReference" ).getString ("driveId" );
@@ -312,25 +319,26 @@ private FQID createFolder(@NotNull FQID root,@NotNull String folder) throws IOEx
312319 * creates a folder at the drive root if it doesn't already exist
313320 * @param folder name to create
314321 * @return FQID of the folder
315- * @throws IOException if the folder could not be created;
316- * or if the api request could not be executed due to cancellation, a connectivity problem or timeout.
322+ * @throws IOException if the request could not be executed
323+ * @throws GraphApiErrorException if the root could not be found or created
324+ * @throws JSONException if the response does not contain the expected items
317325 */
318326 @ NotNull
319- private FQID createRootFolder (@ NotNull String folder ) throws IOException {
327+ private FQID createRootFolder (@ NotNull String folder ) throws IOException , GraphApiErrorException {
320328 FQID item = getRootFolder (folder );
321329 if (item != null ) {
322330 return item ;
323331 }
324332 RequestBody requestBody = RequestBody .create ("{ \" name\" : \" "
325- + folder + "\" , \" folder\" : {}, \" @name.conflictBehavior\" : \" fail\" }" , jsonMediaType );
333+ + folder + "\" , \" folder\" : {}, \" @name.conflictBehavior\" : \" fail\" }" , jsonMediaType );
326334 Request request = new Request .Builder ()
327- .addHeader ("Authorization" , "Bearer " + accessToken )
328- .url ("https://graph.microsoft.com/v1.0/me/drive/root/children" )
329- .post (requestBody )
330- .build ();
335+ .addHeader ("Authorization" , "Bearer " + accessToken )
336+ .url ("https://graph.microsoft.com/v1.0/me/drive/root/children" )
337+ .post (requestBody )
338+ .build ();
331339 try (Response response = DriveBackup .httpClient .newCall (request ).execute ()) {
332- if (! response .isSuccessful () ) {
333- throw new IOException ( "Couldn't create folder " + folder );
340+ if (response .code () != 201 ) {
341+ throw new GraphApiErrorException ( response );
334342 }
335343 JSONObject parsedResponse = new JSONObject (response .body ().string ());
336344 String driveId = parsedResponse .getJSONObject ("parentReference" ).getString ("driveId" );
@@ -343,64 +351,70 @@ private FQID createRootFolder(@NotNull String folder) throws IOException {
343351 * tries to find folder in the drive root
344352 * @param folder to search
345353 * @return FQID or null if not found
354+ * @throws IOException if the request could not be executed
355+ * @throws GraphApiErrorException if the root could not be retrieved
356+ * @throws JSONException if the response does not contain the expected items
346357 */
347358 @ Nullable
348- private FQID getRootFolder (@ NotNull String folder ) {
349- try {
350- String folderUrl = folder . isEmpty () ? folder : ":/" + folder ;
351- Request request = new Request . Builder ( )
352- . addHeader ( "Authorization" , "Bearer " + accessToken )
353- . url ( "https://graph.microsoft.com/v1.0/me/drive/root" + folderUrl + "?$select=id,parentReference,remoteItem" )
354- . build () ;
355- JSONObject parsedResponse ;
356- try ( Response response = DriveBackup . httpClient . newCall ( request ). execute () ) {
357- parsedResponse = new JSONObject ( response . body (). string ()) ;
359+ private FQID getRootFolder (@ NotNull String folder ) throws IOException , GraphApiErrorException {
360+ String folderUrl = folder . isEmpty () ? folder : ":/" + folder ;
361+ Request request = new Request . Builder ()
362+ . addHeader ( "Authorization" , "Bearer " + accessToken )
363+ . url ( "https://graph.microsoft.com/v1.0/me/drive/root" + folderUrl + "?$select=id,parentReference,remoteItem" )
364+ . build ();
365+ JSONObject parsedResponse ;
366+ try ( Response response = DriveBackup . httpClient . newCall ( request ). execute ()) {
367+ if ( response . code () == 404 ) {
368+ return null ;
358369 }
359- if (parsedResponse . has ( "remoteItem" )) {
360- parsedResponse = parsedResponse . optJSONObject ( "remoteItem" );
370+ if (! response . isSuccessful ( )) {
371+ throw new GraphApiErrorException ( response );
361372 }
362- String driveId = parsedResponse .getJSONObject ("parentReference" ).getString ("driveId" );
363- String itemId = parsedResponse .getString ("id" );
364- return new FQID (driveId , itemId );
365- } catch (Exception exception ) {
366- return null ;
373+ parsedResponse = new JSONObject (response .body ().string ());
367374 }
375+ if (parsedResponse .has ("remoteItem" )) {
376+ parsedResponse = parsedResponse .getJSONObject ("remoteItem" );
377+ }
378+ String driveId = parsedResponse .getJSONObject ("parentReference" ).getString ("driveId" );
379+ String itemId = parsedResponse .getString ("id" );
380+ return new FQID (driveId , itemId );
368381 }
369382
370383 /**
371384 * tries to find a folder under root
372385 * @param root to search
373386 * @param folder to look for
374387 * @return FQID or null if not found
388+ * @throws IOException if the request could not be executed
389+ * @throws GraphApiErrorException if the children could not be retrieved
390+ * @throws JSONException if the response does not contain the expected items
375391 */
376392 @ Nullable
377- private FQID getFolder (@ NotNull FQID root , @ NotNull String folder ) {
378- try {
379- Request request = new Request . Builder ( )
380- . addHeader ( "Authorization" , "Bearer " + accessToken )
381- . url ( "https://graph.microsoft.com/v1.0/me/drives/" + root . driveId + "/items/" + root . itemId + "/children" )
382- . build () ;
383- JSONObject parsedResponse ;
384- try ( Response response = DriveBackup . httpClient . newCall ( request ). execute ()) {
385- parsedResponse = new JSONObject (response . body (). string () );
393+ private FQID getFolder (@ NotNull FQID root , @ NotNull String folder ) throws IOException , GraphApiErrorException {
394+ Request request = new Request . Builder ()
395+ . addHeader ( "Authorization" , "Bearer " + accessToken )
396+ . url ( "https://graph.microsoft.com/v1.0/drives/" + root . driveId + "/items/" + root . itemId + "/children" )
397+ . build ();
398+ JSONArray children ;
399+ try ( Response response = DriveBackup . httpClient . newCall ( request ). execute ()) {
400+ if (! response . isSuccessful ()) {
401+ throw new GraphApiErrorException (response );
386402 }
387- JSONArray children = parsedResponse .getJSONArray ("value" );
388- for (int i = 0 ; i < children .length (); i ++) {
389- JSONObject childItem = children .getJSONObject (i );
390- String folderName = childItem .getString ("name" ); // TODO filter non folders
391- if (folder .equals (folderName )) {
392- if (childItem .has ("remoteItem" )) {
393- childItem = childItem .optJSONObject ("remoteItem" );
394- }
395- String driveId = childItem .getJSONObject ("parentReference" ).getString ("driveId" );
396- String itemId = childItem .getString ("id" );
397- return new FQID (driveId , itemId );
403+ children = new JSONObject (response .body ().string ()).getJSONArray ("value" );
404+ }
405+ for (int i = 0 ; i < children .length (); i ++) {
406+ JSONObject childItem = children .getJSONObject (i );
407+ String folderName = childItem .getString ("name" ); // TODO filter non folders
408+ if (folder .equals (folderName )) {
409+ if (childItem .has ("remoteItem" )) {
410+ childItem = childItem .getJSONObject ("remoteItem" );
398411 }
412+ String driveId = childItem .getJSONObject ("parentReference" ).getString ("driveId" );
413+ String itemId = childItem .getString ("id" );
414+ return new FQID (driveId , itemId );
399415 }
400- // TODO handle @odata.nextLink
401- } catch (Exception exception ) {
402- return null ;
403416 }
417+ // TODO handle @odata.nextLink
404418 return null ;
405419 }
406420
@@ -410,7 +424,7 @@ private FQID getFolder(@NotNull FQID root, @NotNull String folder) {
410424 * @param driveId the ID of the drive of the item
411425 * @param itemId the ID of the item to be deleted
412426 * @throws IOException if the request could not be executed
413- * @throws GraphApiErrorException if the item was not deleted
427+ * @throws GraphApiErrorException if the item was not recycled
414428 */
415429 private void recycleItem (@ NotNull String driveId , @ NotNull String itemId ) throws IOException , GraphApiErrorException {
416430 Request delteRequest = new Request .Builder ()
@@ -456,9 +470,10 @@ private FQID uploadSmallFile(@NotNull File file, @NotNull FQID destinationFolder
456470 * The number of files to retain is specified by the user in the {@code config.yml}
457471 * @param parent the folder containing the files
458472 * @throws IOException on request execution failure
473+ * @throws GraphApiErrorException if the children could not be retrieved
459474 * @throws JSONException if the response does not contain the expected items
460475 */
461- private void pruneBackups (@ NotNull FQID parent ) throws Exception , JSONException {
476+ private void pruneBackups (@ NotNull FQID parent ) throws IOException , GraphApiErrorException {
462477 int fileLimit = ConfigParser .getConfig ().backupStorage .keepCount ;
463478 if (fileLimit == -1 ) {
464479 return ;
@@ -469,8 +484,10 @@ private void pruneBackups(@NotNull FQID parent) throws Exception, JSONException
469484 .build ();
470485 JSONArray items ;
471486 try (Response childItemResponse = DriveBackup .httpClient .newCall (childItemRequest ).execute ()) {
472- JSONObject parsedResponse = new JSONObject (childItemResponse .body ().string ());
473- items = parsedResponse .getJSONArray ("value" );
487+ if (!childItemResponse .isSuccessful ()) {
488+ throw new GraphApiErrorException (childItemResponse );
489+ }
490+ items = new JSONObject (childItemResponse .body ().string ()).getJSONArray ("value" );
474491 }
475492 if (fileLimit >= items .length ()) { // TODO filter non backup files (folders & files not created by plugin)
476493 return ;
0 commit comments