From f5dc652e949149fbef12479bf06d74be758c17d3 Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:39:51 +0100 Subject: [PATCH 01/13] Typo fixes --- .../aarboard/nextcloud/api/ServerConfig.java | 448 +++++++++--------- .../nextcloud/api/utils/XMLAnswerParser.java | 10 +- 2 files changed, 227 insertions(+), 231 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java b/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java index 9aa159e..aa6b061 100644 --- a/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java +++ b/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java @@ -1,224 +1,224 @@ -/* - * Copyright (C) 2017 a.schild - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.aarboard.nextcloud.api; - -/** - * - * @author a.schild - */ -public class ServerConfig { - - private AuthenticationConfig authenticationConfig; - private String serverName; - private String subPathPrefix; - private boolean useHTTPS; - private int port; - private boolean trustAllCertificates; - - /** - * Use this constructor if your nextcloud instance is installed in the - * root of the webhosting, like https://nextcloud.company.my/ - * - * @param serverName ip or dns name of server - * @param useHTTPS Use https or http to connect - * @param port Port, usuallay 443 for https and 80 for http - * @param loginName - * @param password - */ - public ServerConfig(String serverName, - boolean useHTTPS, - int port, - String loginName, - String password) { - this.authenticationConfig = new AuthenticationConfig(loginName, password); - this.serverName = serverName; - this.subPathPrefix = null; - this.useHTTPS = useHTTPS; - this.port = port; - this.trustAllCertificates = false; - } - - /** - * Use this constructor if your nextcloud instance is installed in the - * root of the webhosting, like https://nextcloud.company.my/ - * - * @param serverName ip or dns name of server - * @param useHTTPS Use https or http to connect - * @param port Port, usuallay 443 for https and 80 for http - * @param authenticationConfig Authentication configuration for authentication - */ - public ServerConfig(String serverName, - boolean useHTTPS, - int port, - AuthenticationConfig authenticationConfig) { - this.authenticationConfig = authenticationConfig; - this.serverName = serverName; - this.subPathPrefix = null; - this.useHTTPS = useHTTPS; - this.port = port; - this.trustAllCertificates = false; - } - - /** - * Is this constructor if your nextcloud is installed in a subfolder of the server - * like https://nextcloud.company.my/nextcloud/ - * - * @param serverName ip or dns name of server - * @param useHTTPS Use https or http to connect - * @param port Port, usuallay 443 for https and 80 for http - * @param subPathPrefix Path to your nextcloud instance, without starting and trailing / - * can be null if installed in root - * @param authenticationConfig Authentication configuration for authentication - */ - public ServerConfig( - String serverName, - boolean useHTTPS, - int port, - String subPathPrefix, - AuthenticationConfig authenticationConfig) { - this.authenticationConfig = authenticationConfig; - this.serverName = serverName; - this.subPathPrefix = subPathPrefix; - this.useHTTPS = useHTTPS; - this.port = port; - this.trustAllCertificates = false; - } - - /** - * @return the authenticationConfig - */ - public AuthenticationConfig getAuthenticationConfig() { - return authenticationConfig; - } - - /** - * @param authenticationConfig authenticationConfig to set - */ - public void setAuthenticationConfig(AuthenticationConfig authenticationConfig) { - this.authenticationConfig = authenticationConfig; - } - - /** - * @return the serverName - */ - public String getServerName() { - return serverName; - } - - /** - * @param serverName - * the serverName to set, defaults to null - */ - public void setServerName(String serverName){ - this.serverName = serverName; - } - - /** - * @deprecated Use getSubPathPrefix() instead - * @return the configured subpath prefix - */ - public String getSubpathPrefix(){ - return getSubPathPrefix(); - } - - /** - * @return the configured sub path prefix - */ - public String getSubPathPrefix(){ - return subPathPrefix; - } - - /** - * @deprecated Use setSubPathPrefix() instead - * @param subpathPrefix to apply - */ - public void setSubpathPrefix(String subpathPrefix){ - setSubPathPrefix(subpathPrefix); - } - - /** - * @param subPathPrefix to apply - */ - public void setSubPathPrefix(String subPathPrefix){ - this.subPathPrefix = subPathPrefix; - } - - /** - * @return the useHTTPS - */ - public boolean isUseHTTPS() { - return useHTTPS; - } - - /** - * @param useHTTPS the useHTTPS to set - */ - public void setUseHTTPS(boolean useHTTPS) { - this.useHTTPS = useHTTPS; - } - - /** - * @return the port - */ - public int getPort() { - return port; - } - - /** - * @param port the port to set - */ - public void setPort(int port) { - this.port = port; - } - - /** - * @param trustAllCertificates if the client should accept any - * HTTPScertificate (e.g. to work against a self-signed - * certificate) - */ - public void setTrustAllCertificates(boolean trustAllCertificates){ - this.trustAllCertificates = trustAllCertificates; - } - - /** - * @return if the client should accept any HTTPS certificate (e.g. to work against a self-signed - * certificate) - */ - public boolean isTrustAllCertificates(){ - return trustAllCertificates; - } - - /** - * - * @return user name of the given user (Is not always the login name) - */ - public String getUserName() - { - // TODO: We need to dynamically lookup the username - // from the server, via https://serverocs/v1.php/cloud/user - return authenticationConfig.getLoginName(); - } - - /** - * - * @return login name of the given user (Is not always the user name) - */ - public String getLoginName() - { - return authenticationConfig.getLoginName(); - } -} +/* + * Copyright (C) 2017 a.schild + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.aarboard.nextcloud.api; + +/** + * + * @author a.schild + */ +public class ServerConfig { + + private AuthenticationConfig authenticationConfig; + private String serverName; + private String subPathPrefix; + private boolean useHTTPS; + private int port; + private boolean trustAllCertificates; + + /** + * Use this constructor if your nextcloud instance is installed in the + * root of the webhosting, like https://nextcloud.company.my/ + * + * @param serverName ip or dns name of server + * @param useHTTPS Use https or http to connect + * @param port Port, usually 443 for https and 80 for http + * @param loginName + * @param password + */ + public ServerConfig(String serverName, + boolean useHTTPS, + int port, + String loginName, + String password) { + this.authenticationConfig = new AuthenticationConfig(loginName, password); + this.serverName = serverName; + this.subPathPrefix = null; + this.useHTTPS = useHTTPS; + this.port = port; + this.trustAllCertificates = false; + } + + /** + * Use this constructor if your nextcloud instance is installed in the + * root of the webhosting, like https://nextcloud.company.my/ + * + * @param serverName ip or dns name of server + * @param useHTTPS Use https or http to connect + * @param port Port, usually 443 for https and 80 for http + * @param authenticationConfig Authentication configuration for authentication + */ + public ServerConfig(String serverName, + boolean useHTTPS, + int port, + AuthenticationConfig authenticationConfig) { + this.authenticationConfig = authenticationConfig; + this.serverName = serverName; + this.subPathPrefix = null; + this.useHTTPS = useHTTPS; + this.port = port; + this.trustAllCertificates = false; + } + + /** + * Is this constructor if your nextcloud is installed in a subfolder of the server + * like https://nextcloud.company.my/nextcloud/ + * + * @param serverName ip or dns name of server + * @param useHTTPS Use https or http to connect + * @param port Port, usually 443 for https and 80 for http + * @param subPathPrefix Path to your nextcloud instance, without starting and trailing / + * can be null if installed in root + * @param authenticationConfig Authentication configuration for authentication + */ + public ServerConfig( + String serverName, + boolean useHTTPS, + int port, + String subPathPrefix, + AuthenticationConfig authenticationConfig) { + this.authenticationConfig = authenticationConfig; + this.serverName = serverName; + this.subPathPrefix = subPathPrefix; + this.useHTTPS = useHTTPS; + this.port = port; + this.trustAllCertificates = false; + } + + /** + * @return the authenticationConfig + */ + public AuthenticationConfig getAuthenticationConfig() { + return authenticationConfig; + } + + /** + * @param authenticationConfig authenticationConfig to set + */ + public void setAuthenticationConfig(AuthenticationConfig authenticationConfig) { + this.authenticationConfig = authenticationConfig; + } + + /** + * @return the serverName + */ + public String getServerName() { + return serverName; + } + + /** + * @param serverName + * the serverName to set, defaults to null + */ + public void setServerName(String serverName){ + this.serverName = serverName; + } + + /** + * @deprecated Use getSubPathPrefix() instead + * @return the configured subpath prefix + */ + public String getSubpathPrefix(){ + return getSubPathPrefix(); + } + + /** + * @return the configured sub path prefix + */ + public String getSubPathPrefix(){ + return subPathPrefix; + } + + /** + * @deprecated Use setSubPathPrefix() instead + * @param subpathPrefix to apply + */ + public void setSubpathPrefix(String subpathPrefix){ + setSubPathPrefix(subpathPrefix); + } + + /** + * @param subPathPrefix to apply + */ + public void setSubPathPrefix(String subPathPrefix){ + this.subPathPrefix = subPathPrefix; + } + + /** + * @return the useHTTPS + */ + public boolean isUseHTTPS() { + return useHTTPS; + } + + /** + * @param useHTTPS the useHTTPS to set + */ + public void setUseHTTPS(boolean useHTTPS) { + this.useHTTPS = useHTTPS; + } + + /** + * @return the port + */ + public int getPort() { + return port; + } + + /** + * @param port the port to set + */ + public void setPort(int port) { + this.port = port; + } + + /** + * @param trustAllCertificates if the client should accept any + * HTTPScertificate (e.g. to work against a self-signed + * certificate) + */ + public void setTrustAllCertificates(boolean trustAllCertificates){ + this.trustAllCertificates = trustAllCertificates; + } + + /** + * @return if the client should accept any HTTPS certificate (e.g. to work against a self-signed + * certificate) + */ + public boolean isTrustAllCertificates(){ + return trustAllCertificates; + } + + /** + * + * @return username of the given user (Is not always the login name) + */ + public String getUserName() + { + // TODO: We need to dynamically lookup the username + // from the server, via https://serverocs/v1.php/cloud/user + return authenticationConfig.getLoginName(); + } + + /** + * + * @return login name of the given user (Is not always the username) + */ + public String getLoginName() + { + return authenticationConfig.getLoginName(); + } +} diff --git a/src/main/java/org/aarboard/nextcloud/api/utils/XMLAnswerParser.java b/src/main/java/org/aarboard/nextcloud/api/utils/XMLAnswerParser.java index c48c651..1191dc6 100644 --- a/src/main/java/org/aarboard/nextcloud/api/utils/XMLAnswerParser.java +++ b/src/main/java/org/aarboard/nextcloud/api/utils/XMLAnswerParser.java @@ -33,11 +33,8 @@ public static XMLAnswerParser getInstance(Class answ { synchronized (PARSERS) { - if (parser == null) - { - parser = new XMLAnswerParser<>(answerClass); - PARSERS.put(answerClass.getName(), parser); - } + parser = new XMLAnswerParser<>(answerClass); + PARSERS.put(answerClass.getName(), parser); } } return parser; @@ -60,8 +57,7 @@ public A parseResponse(Reader xmlStream) } @SuppressWarnings("unchecked") - private A tryParseAnswer(Reader xmlStream) throws JAXBException, IOException - { + private A tryParseAnswer(Reader xmlStream) throws JAXBException { Unmarshaller unmarshaller = jAXBContext.createUnmarshaller(); Object result = unmarshaller.unmarshal(xmlStream); return (A) result; From b0461dace250adb3e5f58080c996da69f718bc8e Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:42:16 +0100 Subject: [PATCH 02/13] Javadoc url's --- .../nextcloud/api/NextcloudConnector.java | 12 +- .../aarboard/nextcloud/api/ServerConfig.java | 12 +- .../api/filesharing/FilesharingConnector.java | 559 ++++---- .../api/filesharing/SharePermissions.java | 2 +- .../nextcloud/api/filesharing/ShareType.java | 4 +- .../api/provisioning/ProvisionConnector.java | 1198 ++++++++--------- .../aarboard/nextcloud/api/webdav/Files.java | 2 +- 7 files changed, 894 insertions(+), 895 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java index daa0a50..b6f74be 100644 --- a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java @@ -73,7 +73,7 @@ public NextcloudConnector(String serverName, boolean useHTTPS, int port, String /** * @param serviceUrl url of the nextcloud instance, e.g. - * https://nextcloud.instance.com:8443/cloud + * ... * @param loginName User for login * @param password Password for login */ @@ -83,7 +83,7 @@ public NextcloudConnector(String serviceUrl, String loginName, String password) /** * @param serviceUrl url of the nextcloud instance, e.g. - * https://nextcloud.instance.com:8443/cloud + * ... * @param bearerToken Bearer token for login */ public NextcloudConnector(String serviceUrl, String bearerToken) { @@ -91,8 +91,8 @@ public NextcloudConnector(String serviceUrl, String bearerToken) { } /** - * @param serviceUrl url of the nextcloud instance, e.g. - * https://nextcloud.instance.com:8443/cloud + * @param originalServiceUrl url of the nextcloud instance, e.g. + * ... * @param authenticationConfig Authentication config */ public NextcloudConnector(String serviceUrl, AuthenticationConfig authenticationConfig) { @@ -968,7 +968,7 @@ public void uploadFile(File srcFile, String remotePath) { * @deprecated Since some nextcloud installations use fpm or fastcgi to * connect to php, here the uploads might get zero empty on the server Use a * (temp) file to upload the data, so the content length is known in advance - * https://github.com/a-schild/nextcloud-java-api/issues/20 + * ... */ public void uploadFile(InputStream inputStream, String remotePath) { fl.uploadFile(inputStream, remotePath); @@ -987,7 +987,7 @@ public void uploadFile(InputStream inputStream, String remotePath) { * @deprecated Since some nextcloud installations use fpm or fastcgi to * connect to php, here the uploads might get zero empty on the server Use a * (temp) file to upload the data, so the content length is known in advance - * https://github.com/a-schild/nextcloud-java-api/issues/20 + * ... */ public void uploadFile(InputStream inputStream, String remotePath, boolean continueHeader) { fl.uploadFile(inputStream, remotePath, continueHeader); diff --git a/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java b/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java index aa6b061..d339281 100644 --- a/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java +++ b/src/main/java/org/aarboard/nextcloud/api/ServerConfig.java @@ -31,8 +31,8 @@ public class ServerConfig { /** * Use this constructor if your nextcloud instance is installed in the - * root of the webhosting, like https://nextcloud.company.my/ - * + * root of the webhosting, like ... + * * @param serverName ip or dns name of server * @param useHTTPS Use https or http to connect * @param port Port, usually 443 for https and 80 for http @@ -54,8 +54,8 @@ public ServerConfig(String serverName, /** * Use this constructor if your nextcloud instance is installed in the - * root of the webhosting, like https://nextcloud.company.my/ - * + * root of the webhosting, like ... + * * @param serverName ip or dns name of server * @param useHTTPS Use https or http to connect * @param port Port, usually 443 for https and 80 for http @@ -75,8 +75,8 @@ public ServerConfig(String serverName, /** * Is this constructor if your nextcloud is installed in a subfolder of the server - * like https://nextcloud.company.my/nextcloud/ - * + * like ...nextcloud/ + * * @param serverName ip or dns name of server * @param useHTTPS Use https or http to connect * @param port Port, usually 443 for https and 80 for http diff --git a/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java b/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java index fa8400e..dfd4957 100644 --- a/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java @@ -1,280 +1,279 @@ -/* - * Copyright (C) 2017 a.schild - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.aarboard.nextcloud.api.filesharing; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; -import org.aarboard.nextcloud.api.ServerConfig; -import org.aarboard.nextcloud.api.exception.MoreThanOneShareFoundException; -import org.aarboard.nextcloud.api.provisioning.ShareData; -import org.aarboard.nextcloud.api.utils.ConnectorCommon; -import org.aarboard.nextcloud.api.utils.NextcloudResponseHelper; -import org.aarboard.nextcloud.api.utils.XMLAnswer; -import org.aarboard.nextcloud.api.utils.XMLAnswerParser; -import org.apache.http.NameValuePair; -import org.apache.http.message.BasicNameValuePair; - -/** - * - * @author a.schild - * - * https://docs.nextcloud.com/server/11/developer_manual/core/ocs-share-api.html - * - * When specifying paths, you don't have to specify any webdav roots, or - * remote.php ... stuff. Just use the root of your file store directly - * - */ -public class FilesharingConnector -{ - private final static String ROOT_PART= "ocs/v1.php/apps/files_sharing/api/v1/"; - private final static String SHARES_PART= ROOT_PART+"shares"; - - private final ConnectorCommon connectorCommon; - - public FilesharingConnector(ServerConfig serverConfig) { - this.connectorCommon = new ConnectorCommon(serverConfig); - } - - /** - * Get all shares of this user - * - * @return all shares - */ - public List getShares() - { - return getShares(null, false, false); - } - - /** - * Get all shares of this user asynchronously - * - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getSharesAsync() - { - return getSharesAsync(null, false, false); - } - - /** - * Gets all shares from a given file/folder - * - * @param path path to file/folder - * @param reShares returns not only the shares from the current user but all shares from the given file - * @param subShares returns all shares within a folder, given that path defines a folder - * @return matching shares - */ - public List getShares(String path, boolean reShares, boolean subShares) - { - return NextcloudResponseHelper.getAndCheckStatus(getSharesAsync(path,reShares,subShares)).getShares(); - } - - /** - * Gets all shares from a given file/folder asynchronously - * - * @param path path to file/folder - * @param reShares returns not only the shares from the current user but all shares from the given file - * @param subShares returns all shares within a folder, given that path defines a folder - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getSharesAsync(String path, boolean reShares, boolean subShares) - { - List queryParams= new LinkedList<>(); - if (path != null) - { - queryParams.add(new BasicNameValuePair("path", path)); - } - if (reShares) - { - queryParams.add(new BasicNameValuePair("reshares", "true")); - } - if (subShares) - { - queryParams.add(new BasicNameValuePair("subfiles", "true")); - } - return connectorCommon.executeGet(SHARES_PART, queryParams, XMLAnswerParser.getInstance(SharesXMLAnswer.class)); - } - - /** - * Get share info for a single share - * - * @param shareId id of share (Not path of share) - * @return the share if it has been found, otherwise null - */ - public Share getShareInfo(int shareId) - { - SharesXMLAnswer xa= NextcloudResponseHelper.getAndCheckStatus(getShareInfoAsync(shareId)); - if (xa.getShares() == null) - { - return null; - } - else if (xa.getShares().size() == 1) - { - return xa.getShares().get(0); - } - throw new MoreThanOneShareFoundException(shareId); - } - - /** - * Get share info for a single share asynchronously - * - * @param shareId id of share (Not path of share) - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getShareInfoAsync(int shareId) - { - return connectorCommon.executeGet(SHARES_PART+"/"+Integer.toString(shareId), null, XMLAnswerParser.getInstance(SharesXMLAnswer.class)); - } - - /** - * Shares the specified path with the provided parameters - * - * @param path path to the file/folder which should be shared - * @param shareType 0 = user; 1 = group; 3 = public link; 4 = email; 6 = federated cloud share - * @param shareWithUserOrGroupIdOrEmail user / group id / email with which the file should be shared - * @param publicUpload allow public upload to a public shared folder (true/false) - * @param password password to protect public link Share with - * @param permissions 1 = read; 2 = update; 4 = create; 8 = delete; 16 = share; 31 = all (default: 31, for public shares: 1) - * @return created share on success - */ - public Share doShare( - String path, - ShareType shareType, - String shareWithUserOrGroupIdOrEmail, - Boolean publicUpload, - String password, - SharePermissions permissions) - { - return NextcloudResponseHelper.getAndCheckStatus(doShareAsync(path, shareType, shareWithUserOrGroupIdOrEmail, publicUpload, password, permissions)).getShare(); - } - - /** - * Shares the specified path with the provided parameters asynchronously - * - * @param path path to the file/folder which should be shared - * @param shareType 0 = user; 1 = group; 3 = public link; 4 = email; 6 = federated cloud share - * @param shareWithUserOrGroupIdOrEmail user / group id / email with which the file should be shared - * @param publicUpload allow public upload to a public shared folder (true/false) - * @param password password to protect public link Share with - * @param permissions 1 = read; 2 = update; 4 = create; 8 = delete; 16 = share; 31 = all (default: 31, for public shares: 1) - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture doShareAsync( - String path, - ShareType shareType, - String shareWithUserOrGroupIdOrEmail, - Boolean publicUpload, - String password, - SharePermissions permissions) - { - List postParams= new LinkedList<>(); - postParams.add(new BasicNameValuePair("path", path)); - postParams.add(new BasicNameValuePair("shareType", Integer.toString(shareType.getIntValue()))); - postParams.add(new BasicNameValuePair("shareWith", shareWithUserOrGroupIdOrEmail)); - if (publicUpload != null) - { - postParams.add(new BasicNameValuePair("publicUpload", publicUpload ? "true" : "false")); - } - if (password != null) - { - postParams.add(new BasicNameValuePair("password", password)); - } - if (permissions != null) - { - postParams.add(new BasicNameValuePair("permissions", Integer.toString(permissions.getCurrentPermission()))); - } - - return connectorCommon.executePost(SHARES_PART, postParams, XMLAnswerParser.getInstance(SingleShareXMLAnswer.class)); - } - - /** - * Changes a single attribute of a share - * - * @param shareId unique identifier of the share - * @param key the attribute to change - * @param value the value to set - * @return true if the operation succeeded - */ - public boolean editShare(int shareId, ShareData key, String value) - { - return NextcloudResponseHelper.isStatusCodeOkay(editShareAsync(shareId, key, value)); - } - - /** - * Changes a single attribute of a share asynchronously - * - * @param shareId unique identifier of the share - * @param key the attribute to change - * @param value the value to set - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture editShareAsync(int shareId, ShareData key, String value) - { - List queryParams= Collections.singletonList(new BasicNameValuePair(key.parameterName, value)); - return connectorCommon.executePut(SHARES_PART, Integer.toString(shareId), queryParams, XMLAnswerParser.getInstance(XMLAnswer.class)); - } - - /** - * Changes multiple attributes of a share at once - * - * @param shareId unique identifier of the share - * @param values a Map containing the attributes to set - * @return true if the operation succeeded - */ - public boolean editShare(int shareId, Map values) - { - return NextcloudResponseHelper.isStatusCodeOkay(editShareAsync(shareId, values)); - } - - /** - * Changes multiple attributes of a share at once asynchronously - * - * @param shareId unique identifier of the share - * @param values a Map containing the attributes to set - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture editShareAsync(int shareId, Map values) { - List queryParams = values.entrySet().stream() - .map(e -> new BasicNameValuePair(e.getKey().parameterName, e.getValue())).collect(Collectors.toList()); - return connectorCommon.executePut(SHARES_PART, Integer.toString(shareId), queryParams, XMLAnswerParser.getInstance(XMLAnswer.class)); - } - - /** - * Deletes a share - * - * @param shareId unique identifier of the share - * @return true if the operation succeeded - */ - public boolean deleteShare(int shareId) - { - return NextcloudResponseHelper.isStatusCodeOkay(deleteShareAsync(shareId)); - } - - /** - * Deletes a share asynchronously - * - * @param shareId unique identifier of the share - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture deleteShareAsync(int shareId) - { - return connectorCommon.executeDelete(SHARES_PART, Integer.toString(shareId), null, XMLAnswerParser.getInstance(XMLAnswer.class)); - } -} +/* + * Copyright (C) 2017 a.schild + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.aarboard.nextcloud.api.filesharing; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import org.aarboard.nextcloud.api.ServerConfig; +import org.aarboard.nextcloud.api.exception.MoreThanOneShareFoundException; +import org.aarboard.nextcloud.api.provisioning.ShareData; +import org.aarboard.nextcloud.api.utils.ConnectorCommon; +import org.aarboard.nextcloud.api.utils.NextcloudResponseHelper; +import org.aarboard.nextcloud.api.utils.XMLAnswer; +import org.aarboard.nextcloud.api.utils.XMLAnswerParser; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +/** + * + * @author a.schild + * + * ... + * When specifying paths, you don't have to specify any webdav roots, or + * remote.php ... stuff. Just use the root of your file store directly + * + */ +public class FilesharingConnector +{ + private final static String ROOT_PART= "ocs/v1.php/apps/files_sharing/api/v1/"; + private final static String SHARES_PART= ROOT_PART+"shares"; + + private final ConnectorCommon connectorCommon; + + public FilesharingConnector(ServerConfig serverConfig) { + this.connectorCommon = new ConnectorCommon(serverConfig); + } + + /** + * Get all shares of this user + * + * @return all shares + */ + public List getShares() + { + return getShares(null, false, false); + } + + /** + * Get all shares of this user asynchronously + * + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getSharesAsync() + { + return getSharesAsync(null, false, false); + } + + /** + * Gets all shares from a given file/folder + * + * @param path path to file/folder + * @param reShares returns not only the shares from the current user but all shares from the given file + * @param subShares returns all shares within a folder, given that path defines a folder + * @return matching shares + */ + public List getShares(String path, boolean reShares, boolean subShares) + { + return NextcloudResponseHelper.getAndCheckStatus(getSharesAsync(path,reShares,subShares)).getShares(); + } + + /** + * Gets all shares from a given file/folder asynchronously + * + * @param path path to file/folder + * @param reShares returns not only the shares from the current user but all shares from the given file + * @param subShares returns all shares within a folder, given that path defines a folder + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getSharesAsync(String path, boolean reShares, boolean subShares) + { + List queryParams= new LinkedList<>(); + if (path != null) + { + queryParams.add(new BasicNameValuePair("path", path)); + } + if (reShares) + { + queryParams.add(new BasicNameValuePair("reshares", "true")); + } + if (subShares) + { + queryParams.add(new BasicNameValuePair("subfiles", "true")); + } + return connectorCommon.executeGet(SHARES_PART, queryParams, XMLAnswerParser.getInstance(SharesXMLAnswer.class)); + } + + /** + * Get share info for a single share + * + * @param shareId id of share (Not path of share) + * @return the share if it has been found, otherwise null + */ + public Share getShareInfo(int shareId) + { + SharesXMLAnswer xa= NextcloudResponseHelper.getAndCheckStatus(getShareInfoAsync(shareId)); + if (xa.getShares() == null) + { + return null; + } + else if (xa.getShares().size() == 1) + { + return xa.getShares().get(0); + } + throw new MoreThanOneShareFoundException(shareId); + } + + /** + * Get share info for a single share asynchronously + * + * @param shareId id of share (Not path of share) + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getShareInfoAsync(int shareId) + { + return connectorCommon.executeGet(SHARES_PART+"/"+Integer.toString(shareId), null, XMLAnswerParser.getInstance(SharesXMLAnswer.class)); + } + + /** + * Shares the specified path with the provided parameters + * + * @param path path to the file/folder which should be shared + * @param shareType 0 = user; 1 = group; 3 = public link; 4 = email; 6 = federated cloud share + * @param shareWithUserOrGroupIdOrEmail user / group id / email with which the file should be shared + * @param publicUpload allow public upload to a public shared folder (true/false) + * @param password password to protect public link Share with + * @param permissions 1 = read; 2 = update; 4 = create; 8 = delete; 16 = share; 31 = all (default: 31, for public shares: 1) + * @return created share on success + */ + public Share doShare( + String path, + ShareType shareType, + String shareWithUserOrGroupIdOrEmail, + Boolean publicUpload, + String password, + SharePermissions permissions) + { + return NextcloudResponseHelper.getAndCheckStatus(doShareAsync(path, shareType, shareWithUserOrGroupIdOrEmail, publicUpload, password, permissions)).getShare(); + } + + /** + * Shares the specified path with the provided parameters asynchronously + * + * @param path path to the file/folder which should be shared + * @param shareType 0 = user; 1 = group; 3 = public link; 4 = email; 6 = federated cloud share + * @param shareWithUserOrGroupIdOrEmail user / group id / email with which the file should be shared + * @param publicUpload allow public upload to a public shared folder (true/false) + * @param password password to protect public link Share with + * @param permissions 1 = read; 2 = update; 4 = create; 8 = delete; 16 = share; 31 = all (default: 31, for public shares: 1) + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture doShareAsync( + String path, + ShareType shareType, + String shareWithUserOrGroupIdOrEmail, + Boolean publicUpload, + String password, + SharePermissions permissions) + { + List postParams= new LinkedList<>(); + postParams.add(new BasicNameValuePair("path", path)); + postParams.add(new BasicNameValuePair("shareType", Integer.toString(shareType.getIntValue()))); + postParams.add(new BasicNameValuePair("shareWith", shareWithUserOrGroupIdOrEmail)); + if (publicUpload != null) + { + postParams.add(new BasicNameValuePair("publicUpload", publicUpload ? "true" : "false")); + } + if (password != null) + { + postParams.add(new BasicNameValuePair("password", password)); + } + if (permissions != null) + { + postParams.add(new BasicNameValuePair("permissions", Integer.toString(permissions.getCurrentPermission()))); + } + + return connectorCommon.executePost(SHARES_PART, postParams, XMLAnswerParser.getInstance(SingleShareXMLAnswer.class)); + } + + /** + * Changes a single attribute of a share + * + * @param shareId unique identifier of the share + * @param key the attribute to change + * @param value the value to set + * @return true if the operation succeeded + */ + public boolean editShare(int shareId, ShareData key, String value) + { + return NextcloudResponseHelper.isStatusCodeOkay(editShareAsync(shareId, key, value)); + } + + /** + * Changes a single attribute of a share asynchronously + * + * @param shareId unique identifier of the share + * @param key the attribute to change + * @param value the value to set + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture editShareAsync(int shareId, ShareData key, String value) + { + List queryParams= Collections.singletonList(new BasicNameValuePair(key.parameterName, value)); + return connectorCommon.executePut(SHARES_PART, Integer.toString(shareId), queryParams, XMLAnswerParser.getInstance(XMLAnswer.class)); + } + + /** + * Changes multiple attributes of a share at once + * + * @param shareId unique identifier of the share + * @param values a Map containing the attributes to set + * @return true if the operation succeeded + */ + public boolean editShare(int shareId, Map values) + { + return NextcloudResponseHelper.isStatusCodeOkay(editShareAsync(shareId, values)); + } + + /** + * Changes multiple attributes of a share at once asynchronously + * + * @param shareId unique identifier of the share + * @param values a Map containing the attributes to set + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture editShareAsync(int shareId, Map values) { + List queryParams = values.entrySet().stream() + .map(e -> new BasicNameValuePair(e.getKey().parameterName, e.getValue())).collect(Collectors.toList()); + return connectorCommon.executePut(SHARES_PART, Integer.toString(shareId), queryParams, XMLAnswerParser.getInstance(XMLAnswer.class)); + } + + /** + * Deletes a share + * + * @param shareId unique identifier of the share + * @return true if the operation succeeded + */ + public boolean deleteShare(int shareId) + { + return NextcloudResponseHelper.isStatusCodeOkay(deleteShareAsync(shareId)); + } + + /** + * Deletes a share asynchronously + * + * @param shareId unique identifier of the share + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture deleteShareAsync(int shareId) + { + return connectorCommon.executeDelete(SHARES_PART, Integer.toString(shareId), null, XMLAnswerParser.getInstance(XMLAnswer.class)); + } +} diff --git a/src/main/java/org/aarboard/nextcloud/api/filesharing/SharePermissions.java b/src/main/java/org/aarboard/nextcloud/api/filesharing/SharePermissions.java index a4a33e3..3eab367 100644 --- a/src/main/java/org/aarboard/nextcloud/api/filesharing/SharePermissions.java +++ b/src/main/java/org/aarboard/nextcloud/api/filesharing/SharePermissions.java @@ -17,7 +17,7 @@ package org.aarboard.nextcloud.api.filesharing; /** - * https://docs.nextcloud.com/server/11/developer_manual/core/ocs-share-api.html + * ... * @author a.schild */ public class SharePermissions { diff --git a/src/main/java/org/aarboard/nextcloud/api/filesharing/ShareType.java b/src/main/java/org/aarboard/nextcloud/api/filesharing/ShareType.java index 174b034..0953dd5 100644 --- a/src/main/java/org/aarboard/nextcloud/api/filesharing/ShareType.java +++ b/src/main/java/org/aarboard/nextcloud/api/filesharing/ShareType.java @@ -22,8 +22,8 @@ import java.security.InvalidParameterException; /** - * https://docs.nextcloud.com/server/11/developer_manual/core/ocs-share-api.html - * + * ... + * * @author a.schild */ @XmlType diff --git a/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java b/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java index 3db45c1..92e4d61 100644 --- a/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java @@ -1,599 +1,599 @@ -/* - * Copyright (C) 2017 a.schild - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.aarboard.nextcloud.api.provisioning; - -import org.aarboard.nextcloud.api.ServerConfig; -import org.aarboard.nextcloud.api.utils.*; -import org.apache.http.NameValuePair; -import org.apache.http.message.BasicNameValuePair; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - -/** - * - * @author a.schild - * - * https://docs.nextcloud.com/server/11.0/admin_manual/configuration_user/user_provisioning_api.html - * - */ -public class ProvisionConnector -{ - private final static String ROOT_PART= "ocs/v1.php/cloud/"; - private final static String USER_PART= ROOT_PART+"user"; - private final static String USERS_PART= ROOT_PART+"users"; - private final static String GROUPS_PART= ROOT_PART+"groups"; - - private final ConnectorCommon connectorCommon; - - public ProvisionConnector(ServerConfig serverConfig) { - this.connectorCommon = new ConnectorCommon(serverConfig); - } - - /** - * Creates a user with corresponding user information asynchronously - * - * @param userId unique identifier of the user - * @param password password needs to meet nextcloud criteria or operation will fail - * @param displayName the display name of the user - * @param email the email address of the user - * @param quota the quota of the user - * @param language the language of the user - * @param groups the groups the user should be added to - * @return true if the operation succeeded - */ - public CompletableFuture createUserAsync(String userId, String password, - Optional displayName, Optional email, - Optional quota, Optional language, List groups) { - List postParams= new LinkedList<>(); - postParams.add(new BasicNameValuePair("userid", userId)); - postParams.add(new BasicNameValuePair("password", password)); - if (displayName.isPresent()) { - postParams.add(new BasicNameValuePair("displayName", displayName.get())); - } - if (email.isPresent()) { - postParams.add(new BasicNameValuePair("email", email.get())); - } - if (quota.isPresent()) { - postParams.add(new BasicNameValuePair("quota", quota.get())); - } - if (language.isPresent()) { - postParams.add(new BasicNameValuePair("language", language.get())); - } - groups.forEach(group -> { - postParams.add(new BasicNameValuePair("groups[]", group)); - }); - - return connectorCommon.executePost(USERS_PART, postParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Deletes a user - * - * @param userId unique identifier of the user - * @return true if the operation succeeded - */ - public boolean deleteUser(String userId) { - return NextcloudResponseHelper.isStatusCodeOkay(deleteUserAsync(userId)); - } - - /** - * Deletes a user asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture deleteUserAsync(String userId) - { - return connectorCommon.executeDelete(USERS_PART, userId, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Gets all user IDs of this instance - * - * @return all user IDs - */ - public List getAllUsers() { - return getAllUsers(null, -1, -1); - } - - /** - * Gets all user IDs of this instance asynchronously - * - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getAllUsersAsync() { - return getAllUsersAsync(null, -1, -1); - } - - /** - * Get all matching user IDs - * - * @param search pass null when you don't wish to filter - * @param limit pass -1 for no limit - * @param offset pass -1 for no offset - * @return matched user IDs - */ - public List getAllUsers(String search, int limit, int offset) { - return NextcloudResponseHelper.getAndCheckStatus(getAllUsersAsync(search, limit, offset)).getAllUsers(); - } - - /** - * Get all matching user IDs asynchronously - * - * @param search pass null when you don't wish to filter - * @param limit pass -1 for no limit - * @param offset pass -1 for no offset - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getAllUsersAsync(String search, int limit, int offset) { - NextcloudSearch nextcloudSearch = new NextcloudSearch(search, limit, offset); - return connectorCommon.executeGet(USERS_PART, nextcloudSearch.asQueryParameters(), JsonAnswerParser.getInstance(UserListAnswer.class)); - } - - /** - * Gets all user details of this instance - * - * @return all user details - */ - public List getAllUserDetails() { - return getAllUserDetails(null, -1, -1); - } - - /** - * Gets all user details of this instance asynchronously - * - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getAllUserDetailsAsync() { - return getAllUserDetailsAsync(null, -1, -1); - } - - /** - * Get all matching user details - * - * @param search pass null when you don't wish to filter - * @param limit pass -1 for no limit - * @param offset pass -1 for no offset - * @return matched user details - */ - public List getAllUserDetails(String search, int limit, int offset) { - return NextcloudResponseHelper.getAndCheckStatus(getAllUserDetailsAsync(search, limit, offset)).getAllUserDetails(); - } - - /** - * Get all matching user details asynchronously - * - * @param search pass null when you don't wish to filter - * @param limit pass -1 for no limit - * @param offset pass -1 for no offset - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getAllUserDetailsAsync(String search, int limit, int offset) { - NextcloudSearch nextcloudSearch = new NextcloudSearch(search, limit, offset); - return connectorCommon.executeGet(USERS_PART+"/details", nextcloudSearch.asQueryParameters(), JsonAnswerParser.getInstance(UserDetailsListAnswer.class)); - } - - /** - * Gets all available information of one user - * - * @param userId unique identifier of the user - * @return user object containing all information - */ - public User getUser(String userId) { - return NextcloudResponseHelper.getAndWrapException(getUserAsync(userId)).getUserDetails(); - } - - /** - * Gets all available information of one user asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getUserAsync(String userId) { - return connectorCommon.executeGet(USERS_PART+"/"+userId, JsonAnswerParser.getInstance(UserDetailsAnswer.class)); - } - - /** - * Get user details for the logged in user - * - * @return user details of logged in user - */ - public User getCurrentUser() { - return NextcloudResponseHelper.getAndCheckStatus(getCurrentUserAsync()).getUserDetails(); - } - - /** - * Get user details for the logged in user asynchronously - * - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getCurrentUserAsync() { - return connectorCommon.executeGet(USER_PART, JsonAnswerParser.getInstance(UserDetailsAnswer.class)); - } - - /** - * Changes a single attribute of a user - * - * @param userId unique identifier of the user - * @param key the attribute to change - * @param value the value to set - * @return true if the operation succeeded - */ - public boolean editUser(String userId, UserData key, String value) { - return NextcloudResponseHelper.isStatusCodeOkay(editUserAsync(userId, key, value)); - } - - /** - * Changes a single attribute of a user asynchronously - * - * @param userId unique identifier of the user - * @param key the attribute to change - * @param value the value to set - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture editUserAsync(String userId, UserData key, String value) { - List queryParams= new LinkedList<>(); - queryParams.add(new BasicNameValuePair("key", key.name().toLowerCase())); - queryParams.add(new BasicNameValuePair("value", value)); - return connectorCommon.executePut(USERS_PART, userId, queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Enables a user - * - * @param userId unique identifier of the user - * @return true if the operation succeeded - */ - public boolean enableUser(String userId) { - return NextcloudResponseHelper.isStatusCodeOkay(enableUserAsync(userId)); - } - - /** - * Enables a user asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture enableUserAsync(String userId) { - return connectorCommon.executePut(USERS_PART, userId + "/enable", null, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Disables a user - * - * @param userId unique identifier of the user - * @return true if the operation succeeded - */ - public boolean disableUser(String userId) { - return NextcloudResponseHelper.isStatusCodeOkay(disableUserAsync(userId)); - } - - /** - * Disables a user asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture disableUserAsync(String userId) { - return connectorCommon.executePut(USERS_PART, userId + "/disable", null, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Gets all groups of a user - * - * @param userId unique identifier of the user - * @return matched group IDs - */ - public List getGroupsOfUser(String userId) { - return NextcloudResponseHelper.getAndCheckStatus(getGroupsOfUserAsync(userId)).getAllGroups(); - } - - /** - * Gets all groups of a user asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getGroupsOfUserAsync(String userId) { - return connectorCommon.executeGet(USERS_PART + "/" + userId + "/groups", null, JsonAnswerParser.getInstance(GroupListAnswer.class)); - } - - /** - * Adds a user to a group - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return true if the operation succeeded - */ - public boolean addUserToGroup(String userId, String groupId) { - return NextcloudResponseHelper.isStatusCodeOkay(addUserToGroupAsync(userId, groupId)); - } - - /** - * Adds a user to a group asynchronously - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture addUserToGroupAsync(String userId, String groupId) { - List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executePost(USERS_PART + "/" + userId + "/groups", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Removes a user from a group - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return true if the operation succeeded - */ - public boolean removeUserFromGroup(String userId, String groupId) { - return NextcloudResponseHelper.isStatusCodeOkay(removeUserFromGroupAsync(userId, groupId)); - } - - /** - * Removes a user from a group asynchronously - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture removeUserFromGroupAsync(String userId, String groupId) { - List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executeDelete(USERS_PART, userId + "/groups", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Gets all groups this user is a subadministrator of - * - * @param userId unique identifier of the user - * @return matched group IDs - */ - public List getSubadminGroupsOfUser(String userId) { - return NextcloudResponseHelper.getAndCheckStatus(getSubadminGroupsOfUserAsync(userId)).getResult(); - } - - /** - * Gets all groups this user is a subadministrator of asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getSubadminGroupsOfUserAsync(String userId) { - return connectorCommon.executeGet(USERS_PART + "/" + userId + "/subadmins", null, JsonAnswerParser.getInstance(JsonListAnswer.class)); - } - - /** - * Promotes a user to a subadministrator of a group - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return true if the operation succeeded - */ - public boolean promoteToSubadmin(String userId, String groupId) { - return NextcloudResponseHelper.isStatusCodeOkay(promoteToSubadminAsync(userId, groupId)); - } - - /** - * Promotes a user to a subadministrator of a group asynchronously - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture promoteToSubadminAsync(String userId, String groupId) { - List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executePost(USERS_PART + "/" + userId + "/subadmins", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Remove subadministrator rights of a user for a group - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return true if the operation succeeded - */ - public boolean demoteSubadmin(String userId, String groupId) { - return NextcloudResponseHelper.isStatusCodeOkay(demoteSubadminAsync(userId, groupId)); - } - - /** - * Remove subadministrator rights of a user for a group asynchronously - * - * @param userId unique identifier of the user - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture demoteSubadminAsync(String userId, String groupId) { - List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executeDelete(USERS_PART, userId + "/subadmins", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Sends the welcome email to a user - * - * @param userId unique identifier of the user - * @return true if the operation succeeded - */ - public boolean sendWelcomeMail(String userId) { - return NextcloudResponseHelper.isStatusCodeOkay(sendWelcomeMailAsync(userId)); - } - - /** - * Sends the welcome email to a user asynchronously - * - * @param userId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture sendWelcomeMailAsync(String userId) { - return connectorCommon.executePost(USERS_PART + "/" + userId + "/welcome", JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Gets all members of a group - * - * @param groupId unique identifier of the user - * @return user IDs of members - */ - public List getMembersOfGroup(String groupId) { - return NextcloudResponseHelper.getAndCheckStatus(getMembersOfGroupAsync(groupId)).getAllUsers(); - } - - /** - * Gets all members of a group asynchronously - * - * @param groupId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getMembersOfGroupAsync(String groupId) { - return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/users", JsonAnswerParser.getInstance(UserListAnswer.class)); - } - - /** - * Gets all members details of a group - * - * @param groupId unique identifier of the user - * @return user IDs of members - */ - public List getMembersDetailsOfGroup(String groupId) { - return NextcloudResponseHelper.getAndCheckStatus(getMembersDetailsOfGroupAsync(groupId)).getAllUserDetails(); - } - - /** - * Gets all members details of a group asynchronously - * - * @param groupId unique identifier of the user - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getMembersDetailsOfGroupAsync(String groupId) { - return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/users/details", JsonAnswerParser.getInstance(UserDetailsListAnswer.class)); - } - - /** - * Gets all subadministrators of a group - * - * @param groupId unique identifier of the group - * @return user IDs of subadministrators - */ - public List getSubadminsOfGroup(String groupId) { - return NextcloudResponseHelper.getAndCheckStatus(getSubadminsOfGroupAsync(groupId)).getResult(); - } - - /** - * Gets all subadministrators of a group asynchronously - * - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getSubadminsOfGroupAsync(String groupId) { - return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/subadmins", null, JsonAnswerParser.getInstance(JsonListAnswer.class)); - } - - /** - * Creates a group - * - * @param groupId unique identifier of the group - * @return true if the operation succeeded - */ - public boolean createGroup(String groupId) { - return NextcloudResponseHelper.isStatusCodeOkay(createGroupAsync(groupId)); - } - - /** - * Creates a group asynchronously - * - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture createGroupAsync(String groupId) { - List postParams= new LinkedList<>(); - postParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executePost(GROUPS_PART, postParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Deletes a group - * - * @param groupId unique identifier of the group - * @return true if the operation succeeded - */ - public boolean deleteGroup(String groupId) { - return NextcloudResponseHelper.isStatusCodeOkay(deleteGroupAsync(groupId)); - } - - /** - * Deletes a group asynchronously - * - * @param groupId unique identifier of the group - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture deleteGroupAsync(String groupId) { - return connectorCommon.executeDelete(GROUPS_PART, groupId, null, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); - } - - /** - * Get all group IDs of this instance - * - * @return all group IDs - */ - public List getGroups() { - return getGroups(null, -1, -1); - } - - /** - * Get all group IDs of this instance asynchronously - * - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getGroupsAsync() { - return getGroupsAsync(null, -1, -1); - } - - /** - * Get all matching group IDs - * - * @param search pass null when you don't wish to filter - * @param limit pass -1 for no limit - * @param offset pass -1 for no offset - * @return matching group IDs - */ - public List getGroups(String search, int limit, int offset) { - return NextcloudResponseHelper.getAndCheckStatus(getGroupsAsync(search, limit, offset)).getAllGroups(); - } - - /** - * Get all matching group IDs asynchronously - * - * @param search pass null when you don't wish to filter - * @param limit pass -1 for no limit - * @param offset pass -1 for no offset - * @return a CompletableFuture containing the result of the operation - */ - public CompletableFuture getGroupsAsync(String search, int limit, int offset) { - NextcloudSearch nextcloudSearch = new NextcloudSearch(search, limit, offset); - return connectorCommon.executeGet(GROUPS_PART, nextcloudSearch.asQueryParameters(), JsonAnswerParser.getInstance(GroupListAnswer.class)); - } -} +/* + * Copyright (C) 2017 a.schild + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.aarboard.nextcloud.api.provisioning; + +import org.aarboard.nextcloud.api.ServerConfig; +import org.aarboard.nextcloud.api.utils.*; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +/** + * + * @author a.schild + * + * ... + * + */ +public class ProvisionConnector +{ + private final static String ROOT_PART= "ocs/v1.php/cloud/"; + private final static String USER_PART= ROOT_PART+"user"; + private final static String USERS_PART= ROOT_PART+"users"; + private final static String GROUPS_PART= ROOT_PART+"groups"; + + private final ConnectorCommon connectorCommon; + + public ProvisionConnector(ServerConfig serverConfig) { + this.connectorCommon = new ConnectorCommon(serverConfig); + } + + /** + * Creates a user with corresponding user information asynchronously + * + * @param userId unique identifier of the user + * @param password password needs to meet nextcloud criteria or operation will fail + * @param displayName the display name of the user + * @param email the email address of the user + * @param quota the quota of the user + * @param language the language of the user + * @param groups the groups the user should be added to + * @return true if the operation succeeded + */ + public CompletableFuture createUserAsync(String userId, String password, + Optional displayName, Optional email, + Optional quota, Optional language, List groups) { + List postParams= new LinkedList<>(); + postParams.add(new BasicNameValuePair("userid", userId)); + postParams.add(new BasicNameValuePair("password", password)); + if (displayName.isPresent()) { + postParams.add(new BasicNameValuePair("displayName", displayName.get())); + } + if (email.isPresent()) { + postParams.add(new BasicNameValuePair("email", email.get())); + } + if (quota.isPresent()) { + postParams.add(new BasicNameValuePair("quota", quota.get())); + } + if (language.isPresent()) { + postParams.add(new BasicNameValuePair("language", language.get())); + } + groups.forEach(group -> { + postParams.add(new BasicNameValuePair("groups[]", group)); + }); + + return connectorCommon.executePost(USERS_PART, postParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Deletes a user + * + * @param userId unique identifier of the user + * @return true if the operation succeeded + */ + public boolean deleteUser(String userId) { + return NextcloudResponseHelper.isStatusCodeOkay(deleteUserAsync(userId)); + } + + /** + * Deletes a user asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture deleteUserAsync(String userId) + { + return connectorCommon.executeDelete(USERS_PART, userId, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Gets all user IDs of this instance + * + * @return all user IDs + */ + public List getAllUsers() { + return getAllUsers(null, -1, -1); + } + + /** + * Gets all user IDs of this instance asynchronously + * + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getAllUsersAsync() { + return getAllUsersAsync(null, -1, -1); + } + + /** + * Get all matching user IDs + * + * @param search pass null when you don't wish to filter + * @param limit pass -1 for no limit + * @param offset pass -1 for no offset + * @return matched user IDs + */ + public List getAllUsers(String search, int limit, int offset) { + return NextcloudResponseHelper.getAndCheckStatus(getAllUsersAsync(search, limit, offset)).getAllUsers(); + } + + /** + * Get all matching user IDs asynchronously + * + * @param search pass null when you don't wish to filter + * @param limit pass -1 for no limit + * @param offset pass -1 for no offset + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getAllUsersAsync(String search, int limit, int offset) { + NextcloudSearch nextcloudSearch = new NextcloudSearch(search, limit, offset); + return connectorCommon.executeGet(USERS_PART, nextcloudSearch.asQueryParameters(), JsonAnswerParser.getInstance(UserListAnswer.class)); + } + + /** + * Gets all user details of this instance + * + * @return all user details + */ + public List getAllUserDetails() { + return getAllUserDetails(null, -1, -1); + } + + /** + * Gets all user details of this instance asynchronously + * + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getAllUserDetailsAsync() { + return getAllUserDetailsAsync(null, -1, -1); + } + + /** + * Get all matching user details + * + * @param search pass null when you don't wish to filter + * @param limit pass -1 for no limit + * @param offset pass -1 for no offset + * @return matched user details + */ + public List getAllUserDetails(String search, int limit, int offset) { + return NextcloudResponseHelper.getAndCheckStatus(getAllUserDetailsAsync(search, limit, offset)).getAllUserDetails(); + } + + /** + * Get all matching user details asynchronously + * + * @param search pass null when you don't wish to filter + * @param limit pass -1 for no limit + * @param offset pass -1 for no offset + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getAllUserDetailsAsync(String search, int limit, int offset) { + NextcloudSearch nextcloudSearch = new NextcloudSearch(search, limit, offset); + return connectorCommon.executeGet(USERS_PART+"/details", nextcloudSearch.asQueryParameters(), JsonAnswerParser.getInstance(UserDetailsListAnswer.class)); + } + + /** + * Gets all available information of one user + * + * @param userId unique identifier of the user + * @return user object containing all information + */ + public User getUser(String userId) { + return NextcloudResponseHelper.getAndWrapException(getUserAsync(userId)).getUserDetails(); + } + + /** + * Gets all available information of one user asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getUserAsync(String userId) { + return connectorCommon.executeGet(USERS_PART+"/"+userId, JsonAnswerParser.getInstance(UserDetailsAnswer.class)); + } + + /** + * Get user details for the logged in user + * + * @return user details of logged in user + */ + public User getCurrentUser() { + return NextcloudResponseHelper.getAndCheckStatus(getCurrentUserAsync()).getUserDetails(); + } + + /** + * Get user details for the logged in user asynchronously + * + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getCurrentUserAsync() { + return connectorCommon.executeGet(USER_PART, JsonAnswerParser.getInstance(UserDetailsAnswer.class)); + } + + /** + * Changes a single attribute of a user + * + * @param userId unique identifier of the user + * @param key the attribute to change + * @param value the value to set + * @return true if the operation succeeded + */ + public boolean editUser(String userId, UserData key, String value) { + return NextcloudResponseHelper.isStatusCodeOkay(editUserAsync(userId, key, value)); + } + + /** + * Changes a single attribute of a user asynchronously + * + * @param userId unique identifier of the user + * @param key the attribute to change + * @param value the value to set + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture editUserAsync(String userId, UserData key, String value) { + List queryParams= new LinkedList<>(); + queryParams.add(new BasicNameValuePair("key", key.name().toLowerCase())); + queryParams.add(new BasicNameValuePair("value", value)); + return connectorCommon.executePut(USERS_PART, userId, queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Enables a user + * + * @param userId unique identifier of the user + * @return true if the operation succeeded + */ + public boolean enableUser(String userId) { + return NextcloudResponseHelper.isStatusCodeOkay(enableUserAsync(userId)); + } + + /** + * Enables a user asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture enableUserAsync(String userId) { + return connectorCommon.executePut(USERS_PART, userId + "/enable", null, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Disables a user + * + * @param userId unique identifier of the user + * @return true if the operation succeeded + */ + public boolean disableUser(String userId) { + return NextcloudResponseHelper.isStatusCodeOkay(disableUserAsync(userId)); + } + + /** + * Disables a user asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture disableUserAsync(String userId) { + return connectorCommon.executePut(USERS_PART, userId + "/disable", null, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Gets all groups of a user + * + * @param userId unique identifier of the user + * @return matched group IDs + */ + public List getGroupsOfUser(String userId) { + return NextcloudResponseHelper.getAndCheckStatus(getGroupsOfUserAsync(userId)).getAllGroups(); + } + + /** + * Gets all groups of a user asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getGroupsOfUserAsync(String userId) { + return connectorCommon.executeGet(USERS_PART + "/" + userId + "/groups", null, JsonAnswerParser.getInstance(GroupListAnswer.class)); + } + + /** + * Adds a user to a group + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return true if the operation succeeded + */ + public boolean addUserToGroup(String userId, String groupId) { + return NextcloudResponseHelper.isStatusCodeOkay(addUserToGroupAsync(userId, groupId)); + } + + /** + * Adds a user to a group asynchronously + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture addUserToGroupAsync(String userId, String groupId) { + List queryParams = new LinkedList<>(); + queryParams.add(new BasicNameValuePair("groupid", groupId)); + return connectorCommon.executePost(USERS_PART + "/" + userId + "/groups", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Removes a user from a group + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return true if the operation succeeded + */ + public boolean removeUserFromGroup(String userId, String groupId) { + return NextcloudResponseHelper.isStatusCodeOkay(removeUserFromGroupAsync(userId, groupId)); + } + + /** + * Removes a user from a group asynchronously + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture removeUserFromGroupAsync(String userId, String groupId) { + List queryParams = new LinkedList<>(); + queryParams.add(new BasicNameValuePair("groupid", groupId)); + return connectorCommon.executeDelete(USERS_PART, userId + "/groups", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Gets all groups this user is a subadministrator of + * + * @param userId unique identifier of the user + * @return matched group IDs + */ + public List getSubadminGroupsOfUser(String userId) { + return NextcloudResponseHelper.getAndCheckStatus(getSubadminGroupsOfUserAsync(userId)).getResult(); + } + + /** + * Gets all groups this user is a subadministrator of asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getSubadminGroupsOfUserAsync(String userId) { + return connectorCommon.executeGet(USERS_PART + "/" + userId + "/subadmins", null, JsonAnswerParser.getInstance(JsonListAnswer.class)); + } + + /** + * Promotes a user to a subadministrator of a group + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return true if the operation succeeded + */ + public boolean promoteToSubadmin(String userId, String groupId) { + return NextcloudResponseHelper.isStatusCodeOkay(promoteToSubadminAsync(userId, groupId)); + } + + /** + * Promotes a user to a subadministrator of a group asynchronously + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture promoteToSubadminAsync(String userId, String groupId) { + List queryParams = new LinkedList<>(); + queryParams.add(new BasicNameValuePair("groupid", groupId)); + return connectorCommon.executePost(USERS_PART + "/" + userId + "/subadmins", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Remove subadministrator rights of a user for a group + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return true if the operation succeeded + */ + public boolean demoteSubadmin(String userId, String groupId) { + return NextcloudResponseHelper.isStatusCodeOkay(demoteSubadminAsync(userId, groupId)); + } + + /** + * Remove subadministrator rights of a user for a group asynchronously + * + * @param userId unique identifier of the user + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture demoteSubadminAsync(String userId, String groupId) { + List queryParams = new LinkedList<>(); + queryParams.add(new BasicNameValuePair("groupid", groupId)); + return connectorCommon.executeDelete(USERS_PART, userId + "/subadmins", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Sends the welcome email to a user + * + * @param userId unique identifier of the user + * @return true if the operation succeeded + */ + public boolean sendWelcomeMail(String userId) { + return NextcloudResponseHelper.isStatusCodeOkay(sendWelcomeMailAsync(userId)); + } + + /** + * Sends the welcome email to a user asynchronously + * + * @param userId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture sendWelcomeMailAsync(String userId) { + return connectorCommon.executePost(USERS_PART + "/" + userId + "/welcome", JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Gets all members of a group + * + * @param groupId unique identifier of the user + * @return user IDs of members + */ + public List getMembersOfGroup(String groupId) { + return NextcloudResponseHelper.getAndCheckStatus(getMembersOfGroupAsync(groupId)).getAllUsers(); + } + + /** + * Gets all members of a group asynchronously + * + * @param groupId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getMembersOfGroupAsync(String groupId) { + return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/users", JsonAnswerParser.getInstance(UserListAnswer.class)); + } + + /** + * Gets all members details of a group + * + * @param groupId unique identifier of the user + * @return user IDs of members + */ + public List getMembersDetailsOfGroup(String groupId) { + return NextcloudResponseHelper.getAndCheckStatus(getMembersDetailsOfGroupAsync(groupId)).getAllUserDetails(); + } + + /** + * Gets all members details of a group asynchronously + * + * @param groupId unique identifier of the user + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getMembersDetailsOfGroupAsync(String groupId) { + return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/users/details", JsonAnswerParser.getInstance(UserDetailsListAnswer.class)); + } + + /** + * Gets all subadministrators of a group + * + * @param groupId unique identifier of the group + * @return user IDs of subadministrators + */ + public List getSubadminsOfGroup(String groupId) { + return NextcloudResponseHelper.getAndCheckStatus(getSubadminsOfGroupAsync(groupId)).getResult(); + } + + /** + * Gets all subadministrators of a group asynchronously + * + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getSubadminsOfGroupAsync(String groupId) { + return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/subadmins", null, JsonAnswerParser.getInstance(JsonListAnswer.class)); + } + + /** + * Creates a group + * + * @param groupId unique identifier of the group + * @return true if the operation succeeded + */ + public boolean createGroup(String groupId) { + return NextcloudResponseHelper.isStatusCodeOkay(createGroupAsync(groupId)); + } + + /** + * Creates a group asynchronously + * + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture createGroupAsync(String groupId) { + List postParams= new LinkedList<>(); + postParams.add(new BasicNameValuePair("groupid", groupId)); + return connectorCommon.executePost(GROUPS_PART, postParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Deletes a group + * + * @param groupId unique identifier of the group + * @return true if the operation succeeded + */ + public boolean deleteGroup(String groupId) { + return NextcloudResponseHelper.isStatusCodeOkay(deleteGroupAsync(groupId)); + } + + /** + * Deletes a group asynchronously + * + * @param groupId unique identifier of the group + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture deleteGroupAsync(String groupId) { + return connectorCommon.executeDelete(GROUPS_PART, groupId, null, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + } + + /** + * Get all group IDs of this instance + * + * @return all group IDs + */ + public List getGroups() { + return getGroups(null, -1, -1); + } + + /** + * Get all group IDs of this instance asynchronously + * + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getGroupsAsync() { + return getGroupsAsync(null, -1, -1); + } + + /** + * Get all matching group IDs + * + * @param search pass null when you don't wish to filter + * @param limit pass -1 for no limit + * @param offset pass -1 for no offset + * @return matching group IDs + */ + public List getGroups(String search, int limit, int offset) { + return NextcloudResponseHelper.getAndCheckStatus(getGroupsAsync(search, limit, offset)).getAllGroups(); + } + + /** + * Get all matching group IDs asynchronously + * + * @param search pass null when you don't wish to filter + * @param limit pass -1 for no limit + * @param offset pass -1 for no offset + * @return a CompletableFuture containing the result of the operation + */ + public CompletableFuture getGroupsAsync(String search, int limit, int offset) { + NextcloudSearch nextcloudSearch = new NextcloudSearch(search, limit, offset); + return connectorCommon.executeGet(GROUPS_PART, nextcloudSearch.asQueryParameters(), JsonAnswerParser.getInstance(GroupListAnswer.class)); + } +} diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java index 0aa4c54..287e64f 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java @@ -235,7 +235,7 @@ public InputStream downloadFile(String remotePath) throws IOException { * @param remotePath Remotepath of the resource to query for * server * @param allProperties Return all properties, not only base properties - * https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/basic.html#requesting-properties + * ... * @return InputStream * @throws IOException In case of IO errors */ From 83048998a91a663236f1cfa426f5f9f5bae34e6b Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:46:25 +0100 Subject: [PATCH 03/13] Modifiers order + QoL --- .../nextcloud/api/NextcloudConnector.java | 44 +++++++++---------- .../nextcloud/api/config/ConfigConnector.java | 4 +- .../api/filesharing/FilesharingConnector.java | 5 ++- .../api/provisioning/ProvisionConnector.java | 24 ++++------ .../nextcloud/api/provisioning/ShareData.java | 2 +- .../provisioning/UserDetailsListAnswer.java | 3 +- .../nextcloud/api/utils/ConnectorCommon.java | 2 +- .../nextcloud/api/utils/JsonAnswerParser.java | 6 +-- .../nextcloud/api/webdav/AWebdavHandler.java | 33 +++++++------- .../aarboard/nextcloud/api/webdav/Files.java | 6 +-- .../nextcloud/api/webdav/Folders.java | 8 ++-- .../api/webdav/ResourceProperties.java | 1 + .../webdav/pathresolver/NextcloudVersion.java | 10 ++--- .../WebDavPathResolverBuilder.java | 17 ++++--- 14 files changed, 79 insertions(+), 86 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java index b6f74be..08989f6 100644 --- a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java @@ -41,7 +41,7 @@ public class NextcloudConnector { - private final ServerConfig _serverConfig; + private final ServerConfig serverConfig; private final ProvisionConnector pc; private final FilesharingConnector fc; private final ConfigConnector cc; @@ -95,20 +95,20 @@ public NextcloudConnector(String serviceUrl, String bearerToken) { * ... * @param authenticationConfig Authentication config */ - public NextcloudConnector(String serviceUrl, AuthenticationConfig authenticationConfig) { + public NextcloudConnector(String originalServiceUrl, AuthenticationConfig authenticationConfig) { try { - URL _serviceUrl = new URL(serviceUrl); - boolean useHTTPS = serviceUrl.startsWith("https"); - _serverConfig = new ServerConfig(_serviceUrl.getHost(), useHTTPS, _serviceUrl.getPort(), + URL serviceUrl = new URL(originalServiceUrl); + boolean useHTTPS = originalServiceUrl.startsWith("https"); + this.serverConfig = new ServerConfig(serviceUrl.getHost(), useHTTPS, serviceUrl.getPort(), authenticationConfig); - if (!_serviceUrl.getPath().isEmpty()) { - _serverConfig.setSubPathPrefix(_serviceUrl.getPath()); + if (!serviceUrl.getPath().isEmpty()) { + this.serverConfig.setSubPathPrefix(serviceUrl.getPath()); } - pc = new ProvisionConnector(_serverConfig); - fc = new FilesharingConnector(_serverConfig); - cc = new ConfigConnector(_serverConfig); - fd = new Folders(_serverConfig); - fl = new Files(_serverConfig); + pc = new ProvisionConnector(this.serverConfig); + fc = new FilesharingConnector(this.serverConfig); + cc = new ConfigConnector(this.serverConfig); + fd = new Folders(this.serverConfig); + fl = new Files(this.serverConfig); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); @@ -124,12 +124,12 @@ public NextcloudConnector(String serviceUrl, AuthenticationConfig authentication */ public NextcloudConnector(String serverName, boolean useHTTPS, int port, AuthenticationConfig authenticationConfig) { - _serverConfig = new ServerConfig(serverName, useHTTPS, port, authenticationConfig); - pc = new ProvisionConnector(_serverConfig); - fc = new FilesharingConnector(_serverConfig); - cc = new ConfigConnector(_serverConfig); - fd = new Folders(_serverConfig); - fl = new Files(_serverConfig); + this.serverConfig = new ServerConfig(serverName, useHTTPS, port, authenticationConfig); + pc = new ProvisionConnector(this.serverConfig); + fc = new FilesharingConnector(this.serverConfig); + cc = new ConfigConnector(this.serverConfig); + fd = new Folders(this.serverConfig); + fl = new Files(this.serverConfig); } /** @@ -171,8 +171,8 @@ public void setWebDavPathResolverAsType(final WebDavPathResolverBuilder.TYPE typ WebDavPathResolver resolver = WebDavPathResolverBuilder.get(type) .ofVersion(NextcloudVersion.get(getServerVersion())) .withUserName(getCurrentUser().getId()) -// .withUserName(_serverConfig.getUserName()) - .withBasePathPrefix(_serverConfig.getSubPathPrefix()).build(); +// .withUserName(this.serverConfig.getUserName()) + .withBasePathPrefix(this.serverConfig.getSubPathPrefix()).build(); this.fd.setWebDavPathResolver(resolver); this.fl.setWebDavPathResolver(resolver); @@ -195,7 +195,7 @@ public void shutdown() throws IOException { * @param trustAllCertificates Do we accep self signed certificates or not */ public void trustAllCertificates(boolean trustAllCertificates) { - _serverConfig.setTrustAllCertificates(trustAllCertificates); + this.serverConfig.setTrustAllCertificates(trustAllCertificates); } /** @@ -206,7 +206,7 @@ public void trustAllCertificates(boolean trustAllCertificates) { * installed in root */ public void setSubpathPrefix(String subpathPrefix) { - _serverConfig.setSubPathPrefix(subpathPrefix); + this.serverConfig.setSubPathPrefix(subpathPrefix); } /** diff --git a/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java b/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java index 9741d71..d4fda4a 100644 --- a/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java @@ -30,8 +30,8 @@ public class ConfigConnector { - private final static String CONFIG_PART = "ocs/v2.php/apps/provisioning_api/api/v1/config/"; - + private static final String CONFIG_PART = "ocs/v2.php/apps/provisioning_api/api/v1/config/apps"; + private final ConnectorCommon connectorCommon; public ConfigConnector(ServerConfig serverConfig){ diff --git a/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java b/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java index dfd4957..568debc 100644 --- a/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java @@ -43,8 +43,9 @@ */ public class FilesharingConnector { - private final static String ROOT_PART= "ocs/v1.php/apps/files_sharing/api/v1/"; - private final static String SHARES_PART= ROOT_PART+"shares"; + + private static final String ROOT_PART= "ocs/v1.php/apps/files_sharing/api/v1/"; + private static final String SHARES_PART= ROOT_PART+"shares"; private final ConnectorCommon connectorCommon; diff --git a/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java b/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java index 92e4d61..147670d 100644 --- a/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java @@ -40,6 +40,10 @@ public class ProvisionConnector private final static String USER_PART= ROOT_PART+"user"; private final static String USERS_PART= ROOT_PART+"users"; private final static String GROUPS_PART= ROOT_PART+"groups"; + private static final String ROOT_PART= "ocs/v1.php/cloud/"; + private static final String USER_PART= ROOT_PART+"user"; + private static final String USERS_PART= ROOT_PART+"users"; + private static final String GROUPS_PART= ROOT_PART+"groups"; private final ConnectorCommon connectorCommon; @@ -65,21 +69,11 @@ public CompletableFuture createUserAsync(String userId, String p List postParams= new LinkedList<>(); postParams.add(new BasicNameValuePair("userid", userId)); postParams.add(new BasicNameValuePair("password", password)); - if (displayName.isPresent()) { - postParams.add(new BasicNameValuePair("displayName", displayName.get())); - } - if (email.isPresent()) { - postParams.add(new BasicNameValuePair("email", email.get())); - } - if (quota.isPresent()) { - postParams.add(new BasicNameValuePair("quota", quota.get())); - } - if (language.isPresent()) { - postParams.add(new BasicNameValuePair("language", language.get())); - } - groups.forEach(group -> { - postParams.add(new BasicNameValuePair("groups[]", group)); - }); + displayName.ifPresent(s -> postParams.add(new BasicNameValuePair("displayName", s))); + email.ifPresent(s -> postParams.add(new BasicNameValuePair("email", s))); + quota.ifPresent(s -> postParams.add(new BasicNameValuePair("quota", s))); + language.ifPresent(s -> postParams.add(new BasicNameValuePair("language", s))); + groups.forEach(group -> postParams.add(new BasicNameValuePair("groups[]", group))); return connectorCommon.executePost(USERS_PART, postParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); } diff --git a/src/main/java/org/aarboard/nextcloud/api/provisioning/ShareData.java b/src/main/java/org/aarboard/nextcloud/api/provisioning/ShareData.java index 7c692c1..9db4026 100644 --- a/src/main/java/org/aarboard/nextcloud/api/provisioning/ShareData.java +++ b/src/main/java/org/aarboard/nextcloud/api/provisioning/ShareData.java @@ -9,7 +9,7 @@ public enum ShareData public final String parameterName; - private ShareData(String parameterName) + ShareData(String parameterName) { this.parameterName = parameterName; } diff --git a/src/main/java/org/aarboard/nextcloud/api/provisioning/UserDetailsListAnswer.java b/src/main/java/org/aarboard/nextcloud/api/provisioning/UserDetailsListAnswer.java index 7576403..6914b33 100644 --- a/src/main/java/org/aarboard/nextcloud/api/provisioning/UserDetailsListAnswer.java +++ b/src/main/java/org/aarboard/nextcloud/api/provisioning/UserDetailsListAnswer.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonRootName; +import java.util.ArrayList; import org.aarboard.nextcloud.api.utils.JsonAnswer; import java.util.Collections; @@ -18,7 +19,7 @@ public class UserDetailsListAnswer extends JsonAnswer { @JsonIgnore public List getAllUserDetails() { if (data != null && data.users != null) { - return data.users.values().stream().collect(Collectors.toList()); + return new ArrayList<>(data.users.values()); } return Collections.emptyList(); } diff --git a/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java b/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java index a6520da..fa75984 100644 --- a/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java +++ b/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java @@ -186,7 +186,7 @@ private HttpClientContext prepareContext() { return HttpClientContext.create(); } - private final class ResponseCallback implements FutureCallback { + private static final class ResponseCallback implements FutureCallback { private final ResponseParser parser; private final CompletableFuture futureResponse; diff --git a/src/main/java/org/aarboard/nextcloud/api/utils/JsonAnswerParser.java b/src/main/java/org/aarboard/nextcloud/api/utils/JsonAnswerParser.java index 29b5b6e..c514d4a 100644 --- a/src/main/java/org/aarboard/nextcloud/api/utils/JsonAnswerParser.java +++ b/src/main/java/org/aarboard/nextcloud/api/utils/JsonAnswerParser.java @@ -28,10 +28,8 @@ public static JsonAnswerParser getInstance(Class an JsonAnswerParser parser = (JsonAnswerParser) PARSERS.get(answerClass.getName()); if (parser == null) { synchronized (PARSERS) { - if (parser == null) { - parser = new JsonAnswerParser<>(answerClass); - PARSERS.put(answerClass.getName(), parser); - } + parser = new JsonAnswerParser<>(answerClass); + PARSERS.put(answerClass.getName(), parser); } } return parser; diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java b/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java index 7e54be4..29e04c4 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java @@ -47,17 +47,17 @@ public abstract class AWebdavHandler private static final Logger LOG = LoggerFactory.getLogger(AWebdavHandler.class); public static final int FILE_BUFFER_SIZE= 4096; - public static String WEB_DAV_BASE_PATH = "remote.php/webdav/"; + public static final String WEB_DAV_BASE_PATH = "remote.php/webdav/"; - private final ServerConfig _serverConfig; + private final ServerConfig serverConfig; private WebDavPathResolver resolver; private String nextcloudServerVersion; - public AWebdavHandler(ServerConfig serverConfig) + protected AWebdavHandler(ServerConfig serverConfig) { - _serverConfig = serverConfig; + this.serverConfig = serverConfig; } public void setWebDavPathResolver(final WebDavPathResolver resolver) @@ -80,7 +80,7 @@ public String getServerVersion() private void resolveNextcloudServerVersion() { - final WebDavPathResolver versionResolver = WebDavPathResolverBuilder.get(WebDavPathResolverBuilder.TYPE.VERSION).withBasePathPrefix(_serverConfig.getSubPathPrefix()).build(); + final WebDavPathResolver versionResolver = WebDavPathResolverBuilder.get(WebDavPathResolverBuilder.TYPE.VERSION).withBasePathPrefix(this.serverConfig.getSubPathPrefix()).build(); final String url = buildWebdavPath(versionResolver, ""); final Sardine sardine = buildAuthSardine(); @@ -91,7 +91,7 @@ private void resolveNextcloudServerVersion() .lines().collect(Collectors.joining("\n")); //TODO parse with proper json api - nextcloudServerVersion = Arrays.asList(json.split(",")).stream().filter(x -> x.contains("version")).map(x -> x.split(":")[1]).findAny().orElse("20.0").replaceAll("\"", ""); + nextcloudServerVersion = Arrays.stream(json.split(",")).filter(x -> x.contains("version")).map(x -> x.split(":")[1]).findAny().orElse("20.0").replace("\"", ""); } catch (IOException ex) @@ -122,13 +122,13 @@ protected WebDavPathResolver getWebDavPathResolver() { if (null == this.resolver) { - ProvisionConnector pc= new ProvisionConnector(_serverConfig); + ProvisionConnector pc= new ProvisionConnector(this.serverConfig); User currentUser= pc.getCurrentUser(); this.resolver = WebDavPathResolverBuilder.get(WebDavPathResolverBuilder.TYPE.FILES)// .ofVersion(NextcloudVersion.get(getServerVersion())) .withUserName(currentUser.getId()) .withBasePathSuffix("files") - .withBasePathPrefix(_serverConfig.getSubPathPrefix()).build(); + .withBasePathPrefix(this.serverConfig.getSubPathPrefix()).build(); } return this.resolver; @@ -148,9 +148,9 @@ protected String buildWebdavPath(String remotePath) protected String buildWebdavPath(WebDavPathResolver resolver, String remotePath) { URIBuilder uB = new URIBuilder() - .setScheme(_serverConfig.isUseHTTPS() ? "https" : "http") - .setHost(_serverConfig.getServerName()) - .setPort(_serverConfig.getPort()) + .setScheme(this.serverConfig.isUseHTTPS() ? "https" : "http") + .setHost(this.serverConfig.getServerName()) + .setPort(this.serverConfig.getPort()) .setPath(resolver.getWebDavPath(remotePath)); return uB.toString(); } @@ -174,15 +174,14 @@ protected String getWebdavPathPrefix() */ protected Sardine buildAuthSardine() { - if (_serverConfig.getAuthenticationConfig().usesBasicAuthentication()) { + if (this.serverConfig.getAuthenticationConfig().usesBasicAuthentication()) { Sardine sardine = SardineFactory.begin(); - sardine.setCredentials(_serverConfig.getUserName(), - _serverConfig.getAuthenticationConfig().getPassword()); - sardine.enablePreemptiveAuthentication(_serverConfig.getServerName()); + sardine.setCredentials(this.serverConfig.getUserName(), + this.serverConfig.getAuthenticationConfig().getPassword()); + sardine.enablePreemptiveAuthentication(this.serverConfig.getServerName()); return sardine; } - Sardine sardine = new SardineImpl(_serverConfig.getAuthenticationConfig().getBearerToken()); - return sardine; + return new SardineImpl(this.serverConfig.getAuthenticationConfig().getBearerToken()); } /** diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java index 287e64f..85fdb02 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java @@ -147,7 +147,7 @@ public void renameFile(String oldPath, String newPath, boolean overwriteExisting * @throws IOException In case of IO errors */ public boolean downloadFile(String remotePath, String downloadDirPath) throws IOException { - boolean status = false; + boolean status; String path = buildWebdavPath(remotePath); Sardine sardine = buildAuthSardine(); @@ -207,7 +207,7 @@ public InputStream downloadFile(String remotePath) throws IOException { String path = buildWebdavPath(remotePath); Sardine sardine = buildAuthSardine(); - WebdavInputStream in = null; + WebdavInputStream in; try { in = new WebdavInputStream(sardine, sardine.get(path)); @@ -322,7 +322,7 @@ public ResourceProperties getProperties(String remotePath, boolean allProperties private long convertStringToLong(String number) { - if (number == null || number.equals("")) + if (number == null || number.isEmpty()) { return 0; } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java b/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java index e3ae9c6..8abb982 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java @@ -24,6 +24,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.LinkedList; import java.util.List; import org.aarboard.nextcloud.api.ServerConfig; @@ -239,7 +240,6 @@ public void downloadFolder(String remotePath, String rootDownloadDirPath) throws for (DavResource res : resources) { - System.out.println(res.getName()); //Skip the Documents folder which is listed as default as first by the sardine output if(count != 0) { if(res.isDirectory()) { @@ -252,20 +252,20 @@ public void downloadFolder(String remotePath, String rootDownloadDirPath) throws filePath = buildWebdavPath(remotePath + "/" + fileName); retVal.add(res.getName()); - InputStream in = null; + InputStream in; if (sardine.exists(filePath)) { in = sardine.get(filePath); byte[] buffer = new byte[AWebdavHandler.FILE_BUFFER_SIZE]; int bytesRead; File targetFile = new File(newDownloadDir + "/" + fileName); - try (OutputStream outStream = new FileOutputStream(targetFile)) + try (OutputStream outStream = Files.newOutputStream( + targetFile.toPath())) { while ((bytesRead = in.read(buffer)) != -1) { outStream.write(buffer, 0, bytesRead); } outStream.flush(); - outStream.close(); } } } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/ResourceProperties.java b/src/main/java/org/aarboard/nextcloud/api/webdav/ResourceProperties.java index 2393062..66ef3cd 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/ResourceProperties.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/ResourceProperties.java @@ -46,6 +46,7 @@ public class ResourceProperties { private long size; // Unlike contentlength, this property also works for folders reporting the size of everything in the folder public ResourceProperties() { + //no-op } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/NextcloudVersion.java b/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/NextcloudVersion.java index 52be61b..793281d 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/NextcloudVersion.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/NextcloudVersion.java @@ -38,8 +38,8 @@ public class NextcloudVersion { - private final static String PROPERTIES_PATH_PATTERN = "/org/aarboard/nextcloud/api/webdav/pathresolver/webdavpathresolver_{0}.properties"; - private final static String APPEND_USERNAME_PATTERN = "nextcloud.webdav.base.{0}.suffix.append.username"; + private static final String PROPERTIES_PATH_PATTERN = "/org/aarboard/nextcloud/api/webdav/pathresolver/webdavpathresolver_{0}.properties"; + private static final String APPEND_USERNAME_PATTERN = "nextcloud.webdav.base.{0}.suffix.append.username"; private final String versionValue; @@ -52,7 +52,7 @@ public class NextcloudVersion private String patch = "0"; private String revision = "0"; - private Properties configProperties = new Properties(); + private final Properties configProperties = new Properties(); /** * defaults to files */ @@ -89,9 +89,9 @@ public static NextcloudVersion get(final String value) return new NextcloudVersion(value); } - public NextcloudVersion ofType(WebDavPathResolverBuilder.TYPE _type) + public NextcloudVersion ofType(WebDavPathResolverBuilder.TYPE type) { - this.webdavType = _type; + this.webdavType = type; return this; } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/WebDavPathResolverBuilder.java b/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/WebDavPathResolverBuilder.java index 45ebe55..bfb3c07 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/WebDavPathResolverBuilder.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/pathresolver/WebDavPathResolverBuilder.java @@ -25,13 +25,13 @@ public class WebDavPathResolverBuilder { - public final static String NEXTCLOUD_WEBDAV_BASE_PATH = "nextcloud.webdav.base.path"; + public static final String NEXTCLOUD_WEBDAV_BASE_PATH = "nextcloud.webdav.base.path"; - public final static String NEXTCLOUD_WEBDAV_BASE_PATH_SUFFIX = "nextcloud.webdav.base.suffix.path"; + public static final String NEXTCLOUD_WEBDAV_BASE_PATH_SUFFIX = "nextcloud.webdav.base.suffix.path"; - public final static String NEXTCLOUD_WEBDAV_BASE_PATH_PREFIX = "nextcloud.webdav.base.prefix.path"; + public static final String NEXTCLOUD_WEBDAV_BASE_PATH_PREFIX = "nextcloud.webdav.base.prefix.path"; - public final static String NEXTCLOUD_USER_NAME = "nextcloud.userName"; + public static final String NEXTCLOUD_USER_NAME = "nextcloud.userName"; /** * Type of the resolver FILES, VCARD, CALDAV, VERSION @@ -69,16 +69,14 @@ public String getSuffix() } - private WebDavPathResolver result; - - private TYPE type; + private final TYPE type; /** * Defaults to the latest */ private NextcloudVersion version = NextcloudVersion.get("20.0.4"); - private Map valueMap = new HashMap<>(); + private final Map valueMap = new HashMap<>(); public static WebDavPathResolverBuilder get(final TYPE type) { @@ -174,7 +172,8 @@ public WebDavPathResolverBuilder withBasePath(String path) */ public WebDavPathResolver build() { - switch (type) + WebDavPathResolver result; + switch (type) { case FILES: case CALDAV: From 994f435dd500b893815f9422aeb76ff8e7a286c5 Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:47:25 +0100 Subject: [PATCH 04/13] Try-with resources --- .../aarboard/nextcloud/api/webdav/Files.java | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java index 85fdb02..104c6d8 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java @@ -164,34 +164,22 @@ public boolean downloadFile(String remotePath, String downloadDirPath) throws IO String filename = segments[segments.length - 1]; downloadDirPath = downloadDirPath + "/" + filename; } - InputStream in = null; - try - { - in = sardine.get(path); - byte[] buffer = new byte[AWebdavHandler.FILE_BUFFER_SIZE]; - int bytesRead; - File targetFile = new File(downloadDirPath); - try (OutputStream outStream = new FileOutputStream(targetFile)) - { - while ((bytesRead = in.read(buffer)) != -1) - { - outStream.write(buffer, 0, bytesRead); - } - outStream.flush(); - outStream.close(); - } - status = true; - } catch (IOException e) - { - throw new NextcloudApiException(e); - } finally - { - sardine.shutdown(); - if (in != null) - { - in.close(); - } + try (InputStream in = sardine.get(path)) { + byte[] buffer = new byte[AWebdavHandler.FILE_BUFFER_SIZE]; + int bytesRead; + File targetFile = new File(downloadDirPath); + try (OutputStream outStream = java.nio.file.Files.newOutputStream(targetFile.toPath())) { + while ((bytesRead = in.read(buffer)) != -1) { + outStream.write(buffer, 0, bytesRead); + } + outStream.flush(); } + status = true; + } catch (IOException e) { + throw new NextcloudApiException(e); + } finally { + sardine.shutdown(); + } return status; } From aae2fed748a16c4e22d71ebae4e732b3837ac891 Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:48:23 +0100 Subject: [PATCH 05/13] Use constants where possible --- .../nextcloud/api/config/ConfigConnector.java | 8 +-- .../api/provisioning/ProvisionConnector.java | 25 ++++----- .../nextcloud/api/webdav/AWebdavHandler.java | 9 +-- .../aarboard/nextcloud/api/webdav/Files.java | 55 ++++++++++--------- .../nextcloud/api/webdav/Folders.java | 10 ++-- 5 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java b/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java index d4fda4a..7ef2d90 100644 --- a/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java @@ -44,7 +44,7 @@ public List getAppConfigApps(){ } private CompletableFuture getAppConfigAppsAsync(){ - return connectorCommon.executeGet(CONFIG_PART + "apps", Collections.emptyList(), + return connectorCommon.executeGet(CONFIG_PART, Collections.emptyList(), XMLAnswerParser.getInstance(AppConfigAppsAnswer.class)); } @@ -54,7 +54,7 @@ public List getAppConfigAppKeys(String appConfigApp){ } private CompletableFuture getAppConfigAppsAsync(String appConfigApp){ - return connectorCommon.executeGet(CONFIG_PART + "apps/" + appConfigApp, + return connectorCommon.executeGet(CONFIG_PART + "/" + appConfigApp, Collections.emptyList(), XMLAnswerParser.getInstance(AppConfigAppsAnswer.class)); } @@ -72,7 +72,7 @@ public String getAppConfigAppKeyValue(String appConfigAppKeyPath){ private CompletableFuture getAppConfigAppsKeyAsync( String appConfigAppKeyPath){ - return connectorCommon.executeGet(CONFIG_PART + "apps/" + appConfigAppKeyPath, + return connectorCommon.executeGet(CONFIG_PART + "/" + appConfigAppKeyPath, Collections.emptyList(), XMLAnswerParser.getInstance(AppConfigAppKeyValueAnswer.class)); } @@ -91,7 +91,7 @@ public CompletableFuture setAppConfigAppKeyValueAsyn String appConfigAppKeyPath, Object value){ List postParams = new LinkedList<>(); postParams.add(new BasicNameValuePair("value", value.toString())); - return connectorCommon.executePost(CONFIG_PART + "apps/" + appConfigAppKeyPath, postParams, + return connectorCommon.executePost(CONFIG_PART + "/" + appConfigAppKeyPath, postParams, XMLAnswerParser.getInstance(AppConfigAppKeyValueAnswer.class)); } diff --git a/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java b/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java index 147670d..0643cc9 100644 --- a/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/provisioning/ProvisionConnector.java @@ -36,14 +36,13 @@ */ public class ProvisionConnector { - private final static String ROOT_PART= "ocs/v1.php/cloud/"; - private final static String USER_PART= ROOT_PART+"user"; - private final static String USERS_PART= ROOT_PART+"users"; - private final static String GROUPS_PART= ROOT_PART+"groups"; + private static final String ROOT_PART= "ocs/v1.php/cloud/"; private static final String USER_PART= ROOT_PART+"user"; private static final String USERS_PART= ROOT_PART+"users"; private static final String GROUPS_PART= ROOT_PART+"groups"; + public static final String GROUPID_KEY = "groupid"; + public static final String SUBADMINS_PART = "/subadmins"; private final ConnectorCommon connectorCommon; @@ -330,7 +329,7 @@ public boolean addUserToGroup(String userId, String groupId) { */ public CompletableFuture addUserToGroupAsync(String userId, String groupId) { List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); + queryParams.add(new BasicNameValuePair(GROUPID_KEY, groupId)); return connectorCommon.executePost(USERS_PART + "/" + userId + "/groups", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); } @@ -354,7 +353,7 @@ public boolean removeUserFromGroup(String userId, String groupId) { */ public CompletableFuture removeUserFromGroupAsync(String userId, String groupId) { List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); + queryParams.add(new BasicNameValuePair(GROUPID_KEY, groupId)); return connectorCommon.executeDelete(USERS_PART, userId + "/groups", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); } @@ -375,7 +374,7 @@ public List getSubadminGroupsOfUser(String userId) { * @return a CompletableFuture containing the result of the operation */ public CompletableFuture getSubadminGroupsOfUserAsync(String userId) { - return connectorCommon.executeGet(USERS_PART + "/" + userId + "/subadmins", null, JsonAnswerParser.getInstance(JsonListAnswer.class)); + return connectorCommon.executeGet(USERS_PART + "/" + userId + SUBADMINS_PART, null, JsonAnswerParser.getInstance(JsonListAnswer.class)); } /** @@ -398,8 +397,8 @@ public boolean promoteToSubadmin(String userId, String groupId) { */ public CompletableFuture promoteToSubadminAsync(String userId, String groupId) { List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executePost(USERS_PART + "/" + userId + "/subadmins", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + queryParams.add(new BasicNameValuePair(GROUPID_KEY, groupId)); + return connectorCommon.executePost(USERS_PART + "/" + userId + SUBADMINS_PART, queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); } /** @@ -422,8 +421,8 @@ public boolean demoteSubadmin(String userId, String groupId) { */ public CompletableFuture demoteSubadminAsync(String userId, String groupId) { List queryParams = new LinkedList<>(); - queryParams.add(new BasicNameValuePair("groupid", groupId)); - return connectorCommon.executeDelete(USERS_PART, userId + "/subadmins", queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); + queryParams.add(new BasicNameValuePair(GROUPID_KEY, groupId)); + return connectorCommon.executeDelete(USERS_PART, userId + SUBADMINS_PART, queryParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); } /** @@ -503,7 +502,7 @@ public List getSubadminsOfGroup(String groupId) { * @return a CompletableFuture containing the result of the operation */ public CompletableFuture getSubadminsOfGroupAsync(String groupId) { - return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + "/subadmins", null, JsonAnswerParser.getInstance(JsonListAnswer.class)); + return connectorCommon.executeGet(GROUPS_PART + "/" + groupId + SUBADMINS_PART, null, JsonAnswerParser.getInstance(JsonListAnswer.class)); } /** @@ -524,7 +523,7 @@ public boolean createGroup(String groupId) { */ public CompletableFuture createGroupAsync(String groupId) { List postParams= new LinkedList<>(); - postParams.add(new BasicNameValuePair("groupid", groupId)); + postParams.add(new BasicNameValuePair(GROUPID_KEY, groupId)); return connectorCommon.executePost(GROUPS_PART, postParams, JsonAnswerParser.getInstance(JsonVoidAnswer.class)); } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java b/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java index 29e04c4..b1f32b2 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/AWebdavHandler.java @@ -45,6 +45,7 @@ public abstract class AWebdavHandler { private static final Logger LOG = LoggerFactory.getLogger(AWebdavHandler.class); + private static final String ERROR_CLOSING = "error in closing sardine connector"; public static final int FILE_BUFFER_SIZE= 4096; public static final String WEB_DAV_BASE_PATH = "remote.php/webdav/"; @@ -106,7 +107,7 @@ private void resolveNextcloudServerVersion() } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } @@ -211,7 +212,7 @@ public boolean pathExists(String remotePath) } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } } @@ -242,7 +243,7 @@ public void deletePath(String remotePath) } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } } @@ -273,7 +274,7 @@ public void renamePath(String oldPath, String newPath, boolean overwriteExisting } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java index 104c6d8..5433b1a 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/Files.java @@ -4,7 +4,6 @@ import com.github.sardine.DavResource; import com.github.sardine.Sardine; import java.io.File; -import java.io.FileOutputStream; import java.io.OutputStream; import java.io.IOException; import java.io.InputStream; @@ -25,7 +24,11 @@ * */ public class Files extends AWebdavHandler{ + private static final Logger LOG = LoggerFactory.getLogger(Files.class); + private static final String ERROR_SHUTDOWN = "Error in sardine shutdown"; + public static final String URI_NS_OWNCLOUD = "http://owncloud.org/ns"; + public static final String URI_NS_DAV = "DAV:"; public Files(ServerConfig serverConfig) { super(serverConfig); @@ -66,7 +69,7 @@ public void uploadFile(File localSource, String remotePath) { } catch(Exception ex2) { - LOG.warn("Error in sardine shutdown", ex2); + LOG.warn(ERROR_SHUTDOWN, ex2); } } } @@ -109,7 +112,7 @@ public void uploadFile(InputStream inputStream, String remotePath, boolean conti } catch(Exception ex2) { - LOG.warn("Error in sardine shutdown", ex2); + LOG.warn(ERROR_SHUTDOWN, ex2); } } } @@ -189,9 +192,8 @@ public boolean downloadFile(String remotePath, String downloadDirPath) throws IO * @param remotePath Remotepath where the file is saved in the nextcloud * server * @return InputStream - * @throws IOException In case of IO errors */ - public InputStream downloadFile(String remotePath) throws IOException { + public InputStream downloadFile(String remotePath) { String path = buildWebdavPath(remotePath); Sardine sardine = buildAuthSardine(); @@ -211,7 +213,7 @@ public InputStream downloadFile(String remotePath) throws IOException { } catch(Exception ex2) { - LOG.warn("Error in sardine shutdown", ex2); + LOG.warn(ERROR_SHUTDOWN, ex2); } } return in; @@ -225,9 +227,8 @@ public InputStream downloadFile(String remotePath) throws IOException { * @param allProperties Return all properties, not only base properties * ... * @return InputStream - * @throws IOException In case of IO errors */ - public ResourceProperties getProperties(String remotePath, boolean allProperties) throws IOException { + public ResourceProperties getProperties(String remotePath, boolean allProperties) { String path = buildWebdavPath(remotePath); Sardine sardine = buildAuthSardine(); @@ -236,25 +237,25 @@ public ResourceProperties getProperties(String remotePath, boolean allProperties Set props= new HashSet<>(); if (allProperties) { - props.add(new QName("DAV:", "getlastmodified", "d")); - props.add(new QName("DAV:", "getetag", "d")); - props.add(new QName("DAV:", "getcontenttype", "d")); - props.add(new QName("DAV:", "resourcetype", "d")); - props.add(new QName("DAV:", "getcontentlength", "d")); - props.add(new QName("DAV:", "displayname", "d")); - props.add(new QName("http://owncloud.org/ns", "id", "oc")); - props.add(new QName("http://owncloud.org/ns", "fileid", "oc")); - props.add(new QName("http://owncloud.org/ns", "favorite", "oc")); - props.add(new QName("http://owncloud.org/ns", "comments-href", "oc")); - props.add(new QName("http://owncloud.org/ns", "comments-count", "oc")); - props.add(new QName("http://owncloud.org/ns", "comments-unread", "oc")); - props.add(new QName("http://owncloud.org/ns", "owner-id", "oc")); - props.add(new QName("http://owncloud.org/ns", "owner-display-name", "oc")); - props.add(new QName("http://owncloud.org/ns", "share-types", "oc")); - props.add(new QName("http://owncloud.org/ns", "checksums", "oc")); + props.add(new QName(URI_NS_DAV, "getlastmodified", "d")); + props.add(new QName(URI_NS_DAV, "getetag", "d")); + props.add(new QName(URI_NS_DAV, "getcontenttype", "d")); + props.add(new QName(URI_NS_DAV, "resourcetype", "d")); + props.add(new QName(URI_NS_DAV, "getcontentlength", "d")); + props.add(new QName(URI_NS_DAV, "displayname", "d")); + props.add(new QName(URI_NS_OWNCLOUD, "id", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "fileid", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "favorite", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "comments-href", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "comments-count", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "comments-unread", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "owner-id", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "owner-display-name", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "share-types", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "checksums", "oc")); props.add(new QName("http://nextcloud.org/ns", "has-preview", "nc")); - props.add(new QName("http://owncloud.org/ns", "permissions", "oc")); - props.add(new QName("http://owncloud.org/ns", "size", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "permissions", "oc")); + props.add(new QName(URI_NS_OWNCLOUD, "size", "oc")); } List resources= sardine.propfind(path, 0, props); if (resources != null && resources.size() == 1) @@ -303,7 +304,7 @@ public ResourceProperties getProperties(String remotePath, boolean allProperties } catch(Exception ex2) { - LOG.warn("Error in sardine shutdown", ex2); + LOG.warn(ERROR_SHUTDOWN, ex2); } } } diff --git a/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java b/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java index 8abb982..fe19cfc 100644 --- a/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java +++ b/src/main/java/org/aarboard/nextcloud/api/webdav/Folders.java @@ -20,7 +20,6 @@ import com.github.sardine.DavResource; import com.github.sardine.Sardine; import java.io.File; -import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; @@ -39,6 +38,7 @@ public class Folders extends AWebdavHandler{ private static final Logger LOG = LoggerFactory.getLogger(Folders.class); + public static final String ERROR_SARDINE_CLOSING = "error in closing sardine connector"; public Folders(ServerConfig serverConfig) { super(serverConfig); @@ -116,7 +116,7 @@ public List listFolderContent(String remotePath, int depth, boolean excl } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_SARDINE_CLOSING, ex); } } for (DavResource res : resources) @@ -180,7 +180,7 @@ public void createFolder(String remotePath) } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_SARDINE_CLOSING, ex); } } } @@ -220,7 +220,7 @@ public void downloadFolder(String remotePath, String rootDownloadDirPath) throws String newDownloadDir = rootDownloadDirPath + "/" + folderName; File nefile1 = new File(newDownloadDir); if(!nefile1.exists()) { - LOG.info("Creating new download directory: "+newDownloadDir); + LOG.info("Creating new download directory: {}", newDownloadDir); nefile1.mkdir(); } @@ -280,7 +280,7 @@ public void downloadFolder(String remotePath, String rootDownloadDirPath) throws } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_SARDINE_CLOSING, ex); } } } From dd12890d30f2edc1ce93dfbc66139f228bbe4240 Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:49:00 +0100 Subject: [PATCH 06/13] Removed redundant Exception throwing --- .../aarboard/nextcloud/api/provisioning/QuotaDeserializer.java | 2 +- .../java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/provisioning/QuotaDeserializer.java b/src/main/java/org/aarboard/nextcloud/api/provisioning/QuotaDeserializer.java index b25ae34..b7fae7f 100644 --- a/src/main/java/org/aarboard/nextcloud/api/provisioning/QuotaDeserializer.java +++ b/src/main/java/org/aarboard/nextcloud/api/provisioning/QuotaDeserializer.java @@ -12,7 +12,7 @@ public class QuotaDeserializer extends JsonDeserializer> { @Override - public Optional deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + public Optional deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { Long result = null; String quota = jsonParser.getValueAsString(); if (NumberUtils.isCreatable(quota)) { diff --git a/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java b/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java index fa75984..f8e776c 100644 --- a/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java +++ b/src/main/java/org/aarboard/nextcloud/api/utils/ConnectorCommon.java @@ -150,7 +150,7 @@ private URI buildUrl(String subPath, List queryParams, boolean us } } - private CompletableFuture executeRequest(final ResponseParser parser, HttpRequestBase request) throws IOException, ClientProtocolException { + private CompletableFuture executeRequest(final ResponseParser parser, HttpRequestBase request) throws IOException { // https://docs.nextcloud.com/server/14/developer_manual/core/ocs-share-api.html request.addHeader("OCS-APIRequest", "true"); request.addHeader("Content-Type", "application/x-www-form-urlencoded"); From 290471fecab723d648b67a32007cc0064d092b6c Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:49:20 +0100 Subject: [PATCH 07/13] Simplified assertions in tests --- .../nextcloud/api/TestConfigConnector.java | 17 ++--------- .../org/aarboard/nextcloud/api/TestFiles.java | 29 ++++++++++++------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/test/java/org/aarboard/nextcloud/api/TestConfigConnector.java b/src/test/java/org/aarboard/nextcloud/api/TestConfigConnector.java index 56bc991..65549e9 100644 --- a/src/test/java/org/aarboard/nextcloud/api/TestConfigConnector.java +++ b/src/test/java/org/aarboard/nextcloud/api/TestConfigConnector.java @@ -16,20 +16,9 @@ */ package org.aarboard.nextcloud.api; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Collection; import java.util.List; - -import org.aarboard.nextcloud.api.provisioning.User; -import org.aarboard.nextcloud.api.provisioning.UserData; -import org.junit.AfterClass; -import org.junit.Before; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; @@ -47,7 +36,7 @@ public void t01_testGetConfigApps() { if (_nc != null) { List apps = _nc.getAppConfigApps(); - assertTrue(apps != null); + assertNotNull(apps); } } @@ -57,7 +46,7 @@ public void t02_testGetConfigAppsFiles() { if (_nc != null) { List appKeys = _nc.getAppConfigAppKeys("files"); - assertTrue(appKeys != null); + assertNotNull(appKeys); } } @@ -67,7 +56,7 @@ public void t03_testGetConfigAppsFilesVersion() { if (_nc != null) { String version = _nc.getAppConfigAppKeyValue("files", "installed_version"); - assertTrue(version != null); + assertNotNull(version); } } } diff --git a/src/test/java/org/aarboard/nextcloud/api/TestFiles.java b/src/test/java/org/aarboard/nextcloud/api/TestFiles.java index e15804a..b35f3db 100644 --- a/src/test/java/org/aarboard/nextcloud/api/TestFiles.java +++ b/src/test/java/org/aarboard/nextcloud/api/TestFiles.java @@ -16,6 +16,7 @@ */ package org.aarboard.nextcloud.api; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -26,6 +27,8 @@ import org.aarboard.nextcloud.api.webdav.ResourceProperties; import org.junit.Assert; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; @@ -257,11 +260,13 @@ public void t27_99_testFileProperties() { try { _nc.getProperties(TESTFILE2+"-not-existing", false); - assertFalse("Resource should throw 404 error", true); + fail("Resource should throw 404 error"); } catch (Exception ex) { - assertTrue("com.github.sardine.impl.SardineException: status code: 404, reason phrase: Unexpected response (404 Not Found)".equals(ex.getMessage())); + assertEquals( + "com.github.sardine.impl.SardineException: status code: 404, reason phrase: Unexpected response (404 Not Found)", + ex.getMessage()); } } } @@ -280,7 +285,8 @@ public void t28_3_testDowloadFile() throws IOException { nCount++; } is.close(); - assertTrue("Downloaded content size does not match", nCount == TEST3_FILE_CONTENT.length()); + assertEquals("Downloaded content size does not match", nCount, + TEST3_FILE_CONTENT.length()); } } @@ -292,11 +298,12 @@ public void t29_3_testDowloadFile() throws IOException { File of= new File(System.getProperty("java.io.tmpdir")+File.separator+TESTFILE1); if (_nc.downloadFile(TESTFILE1, of.getParent())) { - assertTrue("Downloaded content size does not match", of.length() == TEST1_FILE_CONTENT.length()); + assertEquals("Downloaded content size does not match", of.length(), + TEST1_FILE_CONTENT.length()); } else { - assertTrue("Downloaded file failed", false); + fail("Downloaded file failed"); } if (of.exists()) { @@ -313,11 +320,11 @@ public void t29_3_testDowloadFile4() throws IOException { File of= new File(System.getProperty("java.io.tmpdir")+File.separator+TESTFILE4); if (_nc.downloadFile(TESTFILE4, of.getParent())) { - assertTrue("Downloaded content size does not match", of.length() == 0); + assertEquals("Downloaded content size does not match", 0, of.length()); } else { - assertTrue("Downloaded file failed", false); + fail("Downloaded file failed"); } if (of.exists()) { @@ -335,11 +342,11 @@ public void t29_6_testDowloadFile6() throws IOException { if (_nc.downloadFile(TESTFILE6, of.getParent())) { File srcFile= new File("src/test/resources/"+TESTFILE6); - assertTrue("Downloaded content size does not match", of.length() == srcFile.length()); + assertEquals("Downloaded content size does not match", of.length(), srcFile.length()); } else { - assertTrue("Downloaded file failed", false); + fail("Downloaded file failed"); } if (of.exists()) { @@ -357,11 +364,11 @@ public void t29_6_testDowloadFile7() throws IOException { if (_nc.downloadFile(TESTFILE7, of.getParent())) { File srcFile= new File("src/test/resources/"+TESTFILE7); - assertTrue("Downloaded content size does not match", of.length() == srcFile.length()); + assertEquals("Downloaded content size does not match", of.length(), srcFile.length()); } else { - assertTrue("Downloaded file failed", false); + fail("Downloaded file failed"); } if (of.exists()) { From 4f4bfbff02eca5a085e4c486fb44aa6099d493e7 Mon Sep 17 00:00:00 2001 From: Mathias Bosman <436498+mathiasbosman@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:49:34 +0100 Subject: [PATCH 08/13] Some more typo's --- .../aarboard/nextcloud/api/NextcloudConnector.java | 12 ++++++------ .../api/webdav/pathresolver/NextcloudVersion.java | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java index 08989f6..e0f6a85 100644 --- a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java @@ -192,7 +192,7 @@ public void shutdown() throws IOException { * Trust all HTTPS certificates presented by the server. This is e.g. used * to work against a Nextcloud instance with a self-signed certificate. * - * @param trustAllCertificates Do we accep self signed certificates or not + * @param trustAllCertificates Do we accept self-signed certificates or not */ public void trustAllCertificates(boolean trustAllCertificates) { this.serverConfig.setTrustAllCertificates(trustAllCertificates); @@ -662,7 +662,7 @@ public CompletableFuture getUserAsync(String userId) { } /** - * Gets user details of currently logged in user + * Gets user details of currently logged-in user * * @return all user details */ @@ -1136,7 +1136,7 @@ public CompletableFuture editShareAsync(int shareId, Map Date: Sat, 16 Mar 2024 11:49:47 +0100 Subject: [PATCH 09/13] Incr. version + changelog --- Changelog.md | 10 ++++++++++ pom.xml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 180828d..1bcf1be 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,14 @@ # Changelog for nextcloud api +## Version 13.0.2 +- 2024-03-16 + - Typo fixes + - Javadoc url's + - Modifiers should be declared in the correct order + - Try-with resources + - Use constants where possible + - Removed redundant Exception throwing + - Simplified assertions in tests + ## Version 13.0.1 - 2023-09-29 - Release 13.0.1 diff --git a/pom.xml b/pom.xml index 31433ce..1e95f6f 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.aarboard.nextcloud nextcloud-api - 13.0.1 + 13.0.2 jar From 9db019470790060484f464277dfee21eed10a7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Schild?= Date: Tue, 7 May 2024 09:57:04 +0200 Subject: [PATCH 10/13] Merged in enhancements, updated dependencies, updated readme --- Changelog.md | 5 +++++ README.md | 2 +- pom.xml | 14 +++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Changelog.md b/Changelog.md index 180828d..b05c3ea 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,9 @@ # Changelog for nextcloud api +## Version 13.1.0 +- 2024-05-07 + - Release 13.1.0 + - Merged enhancements and cleanups (Thanks to mathiasbosman) + ## Version 13.0.1 - 2023-09-29 - Release 13.0.1 diff --git a/README.md b/README.md index 69f079a..5d0958a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Java api library to access nextcloud features from java applications com.github.a-schild nextcloud-java-api - 13.0.1 + 13.1.0 ``` diff --git a/pom.xml b/pom.xml index 31433ce..aab0c42 100644 --- a/pom.xml +++ b/pom.xml @@ -3,19 +3,19 @@ 4.0.0 org.aarboard.nextcloud nextcloud-api - 13.0.1 + 13.1.0-SNAPSHOT jar 4.4.16 4.1.5 4.5.14 - 2.0.9 + 2.0.13 5.12 - 2.13.0 - 3.13.0 - 1.16.0 - 2.15.2 + 2.16.1 + 3.14.0 + 1.17.0 + 2.17.1 4.0.1 2.1.1 3.0.0 @@ -274,7 +274,7 @@ false - true + false From 196242d4ba194d1469d4962047b2f28921b4fa16 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Fri, 21 Mar 2025 13:24:32 +0100 Subject: [PATCH 11/13] Make NextcloudConnector implement AutoCloseable To make it work with try-with-resources --- .../aarboard/nextcloud/api/NextcloudConnector.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java index e0f6a85..5515b51 100644 --- a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java @@ -39,7 +39,7 @@ import org.aarboard.nextcloud.api.webdav.pathresolver.WebDavPathResolver; import org.aarboard.nextcloud.api.webdav.pathresolver.WebDavPathResolverBuilder; -public class NextcloudConnector { +public class NextcloudConnector implements AutoCloseable { private final ServerConfig serverConfig; private final ProvisionConnector pc; @@ -188,6 +188,16 @@ public void shutdown() throws IOException { ConnectorCommon.shutdown(); } + /** + * Close the HTTP client. Perform this to cleanly shut down this + * application. + * + * @throws Exception In case of errors + */ + public void close() throws Exception { + shutdown(); + } + /** * Trust all HTTPS certificates presented by the server. This is e.g. used * to work against a Nextcloud instance with a self-signed certificate. From 79d442e5f1990addaefafd9a6c95a28c1579e0b8 Mon Sep 17 00:00:00 2001 From: kindlich Date: Sat, 29 Mar 2025 11:18:34 +0100 Subject: [PATCH 12/13] Bump Java Version to 11 Reason: We can't compile at Java 8 due to XML-Bind API needing Java 11 ``` ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project nextcloud-api: Compilation failure [ERROR] /home/klenk/Dev/idm/libraries/nextcloud-java-api/src/main/java/org/aarboard/nextcloud/api/config/AppConfigAppsAnswer.java:[19,35] cannot access jakarta.xml.bind.annotation.XmlAccessType [ERROR] bad class file: /home/klenk/.m2/repository/jakarta/xml/bind/jakarta.xml.bind-api/4.0.1/jakarta.xml.bind-api-4.0.1.jar(jakarta/xml/bind/annotation/XmlAccessType.class) [ERROR] class file has wrong version 55.0, should be 52.0 [ERROR] Please remove or make sure it appears in the correct subdirectory of the classpath. ``` --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b1d93b1..6044c8c 100644 --- a/pom.xml +++ b/pom.xml @@ -42,8 +42,8 @@ 3.1.2 2.7.9 - 1.8 - 1.8 + 11 + 11 gpl30 NextCloud Java API library From ec7671a613baae996682308456c4c50208a40c18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Jul 2025 01:30:49 +0000 Subject: [PATCH 13/13] Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.18.0 Bumps org.apache.commons:commons-lang3 from 3.14.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b1d93b1..6831dbc 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ 2.0.13 5.12 2.16.1 - 3.14.0 + 3.18.0 1.17.0 2.17.1 4.0.1