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/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..5559661 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 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.18.0 + 1.17.0 + 2.17.1 4.0.1 2.1.1 3.0.0 @@ -42,8 +42,8 @@ 3.1.2 2.7.9 - 1.8 - 1.8 + 11 + 11 gpl30 NextCloud Java API library @@ -274,7 +274,7 @@ false - true + false diff --git a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java index daa0a50..5515b51 100644 --- a/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java +++ b/src/main/java/org/aarboard/nextcloud/api/NextcloudConnector.java @@ -39,9 +39,9 @@ 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 ServerConfig serverConfig; private final ProvisionConnector pc; private final FilesharingConnector fc; private final ConfigConnector cc; @@ -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,24 +91,24 @@ 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) { + 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); @@ -188,14 +188,24 @@ 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. * - * @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) { - _serverConfig.setTrustAllCertificates(trustAllCertificates); + this.serverConfig.setTrustAllCertificates(trustAllCertificates); } /** @@ -206,7 +216,7 @@ public void trustAllCertificates(boolean trustAllCertificates) { * installed in root */ public void setSubpathPrefix(String subpathPrefix) { - _serverConfig.setSubPathPrefix(subpathPrefix); + this.serverConfig.setSubPathPrefix(subpathPrefix); } /** @@ -662,7 +672,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 */ @@ -968,7 +978,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 +997,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); @@ -1136,7 +1146,7 @@ public CompletableFuture editShareAsync(int shareId, Map. - */ -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 ... + * + * @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 ... + * + * @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 ...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/config/ConfigConnector.java b/src/main/java/org/aarboard/nextcloud/api/config/ConfigConnector.java index 9741d71..7ef2d90 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){ @@ -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/filesharing/FilesharingConnector.java b/src/main/java/org/aarboard/nextcloud/api/filesharing/FilesharingConnector.java index fa8400e..568debc 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,280 @@ -/* - * 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 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; + + 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..0643cc9 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,592 @@ -/* - * 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 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; + + 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)); + 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)); + } + + /** + * 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_KEY, 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_KEY, 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_PART, 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_KEY, groupId)); + return connectorCommon.executePost(USERS_PART + "/" + userId + SUBADMINS_PART, 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_KEY, groupId)); + return connectorCommon.executeDelete(USERS_PART, userId + SUBADMINS_PART, 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_PART, 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_KEY, 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/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/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..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"); @@ -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/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; 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..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,19 +45,20 @@ 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 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 +81,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 +92,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) @@ -106,7 +107,7 @@ private void resolveNextcloudServerVersion() } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } @@ -122,13 +123,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 +149,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 +175,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()); } /** @@ -212,7 +212,7 @@ public boolean pathExists(String remotePath) } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } } @@ -243,7 +243,7 @@ public void deletePath(String remotePath) } catch (IOException ex) { - LOG.warn("error in closing sardine connector", ex); + LOG.warn(ERROR_CLOSING, ex); } } } @@ -274,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 0aa4c54..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); } } } @@ -147,7 +150,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(); @@ -164,34 +167,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; } @@ -201,13 +192,12 @@ 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(); - WebdavInputStream in = null; + WebdavInputStream in; try { in = new WebdavInputStream(sardine, sardine.get(path)); @@ -223,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; @@ -235,11 +225,10 @@ 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 */ - public ResourceProperties getProperties(String remotePath, boolean allProperties) throws IOException { + public ResourceProperties getProperties(String remotePath, boolean allProperties) { String path = buildWebdavPath(remotePath); Sardine sardine = buildAuthSardine(); @@ -248,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) @@ -315,14 +304,14 @@ public ResourceProperties getProperties(String remotePath, boolean allProperties } catch(Exception ex2) { - LOG.warn("Error in sardine shutdown", ex2); + LOG.warn(ERROR_SHUTDOWN, ex2); } } } 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..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,10 +20,10 @@ 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; +import java.nio.file.Files; import java.util.LinkedList; import java.util.List; import org.aarboard.nextcloud.api.ServerConfig; @@ -38,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); @@ -115,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) @@ -179,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); } } } @@ -219,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(); } @@ -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(); } } } @@ -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); } } } 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..7739994 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 */ @@ -71,7 +71,7 @@ public class NextcloudVersion * major.minor.path(.revision) E.g. 20.4.0.0 or 14.1.3 * * @param value of NextCloudInstance - * @return a versionbn instance + * @return a version instance * @since 11.5 */ public static NextcloudVersion get(final String value) @@ -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; } @@ -103,7 +103,7 @@ public String getWebdavBasePath() /** * - * @return true if usernae shall appendend to path, false otherwise + * @return true if username shall be appended to path, false otherwise */ public boolean isAppendUserName() { @@ -112,7 +112,7 @@ public boolean isAppendUserName() /** * - * @return true if appendSuffix shall appendend to path, false otherwise + * @return true if appendSuffix shall be appended to path, false otherwise */ public boolean isAppendSuffix() { 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: 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()) {