From 2481774545de18a774f2d88d8a20cbd799f0d5e2 Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Tue, 11 Jun 2024 17:34:39 +0300 Subject: [PATCH 1/7] [#1] Define SDK structure, add operations with container and object Signed-off-by: Ori Bruk --- .gitignore | 40 + CONTRIBUTING.md | 156 ++++ README.md | 91 ++ client/pom.xml | 48 ++ .../main/java/info/FrostFS/sdk/Client.java | 36 + .../java/info/FrostFS/sdk/GrpcClient.java | 89 ++ .../info/FrostFS/sdk/RequestConstructor.java | 50 ++ .../java/info/FrostFS/sdk/RequestSigner.java | 114 +++ .../main/java/info/FrostFS/sdk/Verifier.java | 116 +++ .../FrostFS/sdk/services/ContainerClient.java | 16 + .../FrostFS/sdk/services/ObjectClient.java | 19 + .../sdk/services/impl/ContainerService.java | 107 +++ .../sdk/services/impl/FrostFSClient.java | 85 ++ .../sdk/services/impl/NetmapService.java | 42 + .../sdk/services/impl/ObjectReader.java | 48 ++ .../sdk/services/impl/ObjectService.java | 257 ++++++ .../sdk/services/impl/ObjectWriter.java | 59 ++ .../sdk/services/impl/SearchReader.java | 26 + .../sdk/services/impl/SessionService.java | 55 ++ cryptography/pom.xml | 44 + .../java/info/FrostFS/sdk/ArrayHelper.java | 12 + .../main/java/info/FrostFS/sdk/Base58.java | 127 +++ .../main/java/info/FrostFS/sdk/Helper.java | 36 + .../java/info/FrostFS/sdk/KeyExtension.java | 161 ++++ modelsV2/pom.xml | 38 + .../java/info/FrostFS/sdk/UUIDExtension.java | 21 + .../FrostFS/sdk/constants/XHeaderConst.java | 7 + .../java/info/FrostFS/sdk/enums/BasicAcl.java | 33 + .../info/FrostFS/sdk/enums/NodeState.java | 33 + .../FrostFS/sdk/enums/ObjectMatchType.java | 16 + .../info/FrostFS/sdk/enums/ObjectType.java | 32 + .../info/FrostFS/sdk/enums/StatusCode.java | 46 + .../java/info/FrostFS/sdk/jdo/Constants.java | 6 + .../java/info/FrostFS/sdk/jdo/Container.java | 58 ++ .../info/FrostFS/sdk/jdo/ContainerId.java | 35 + .../java/info/FrostFS/sdk/jdo/MetaHeader.java | 41 + .../info/FrostFS/sdk/jdo/ObjectAttribute.java | 27 + .../info/FrostFS/sdk/jdo/ObjectFilter.java | 58 ++ .../info/FrostFS/sdk/jdo/ObjectFrostFs.java | 37 + .../info/FrostFS/sdk/jdo/ObjectHeader.java | 71 ++ .../java/info/FrostFS/sdk/jdo/ObjectId.java | 31 + .../java/info/FrostFS/sdk/jdo/OwnerId.java | 25 + .../java/info/FrostFS/sdk/jdo/Status.java | 45 + .../java/info/FrostFS/sdk/jdo/Version.java | 36 + .../info/FrostFS/sdk/jdo/netmap/NodeInfo.java | 30 + .../sdk/jdo/netmap/PlacementPolicy.java | 27 + .../info/FrostFS/sdk/jdo/netmap/Replica.java | 34 + .../sdk/mappers/ContainerIdMapper.java | 16 + .../FrostFS/sdk/mappers/ContainerMapper.java | 39 + .../FrostFS/sdk/mappers/MetaHeaderMapper.java | 15 + .../sdk/mappers/ObjectAttributeMapper.java | 17 + .../sdk/mappers/ObjectFilterMapper.java | 25 + .../sdk/mappers/ObjectHeaderMapper.java | 48 ++ .../FrostFS/sdk/mappers/ObjectIdMapper.java | 13 + .../FrostFS/sdk/mappers/ObjectMapper.java | 15 + .../FrostFS/sdk/mappers/OwnerIdMapper.java | 13 + .../FrostFS/sdk/mappers/StatusMapper.java | 23 + .../FrostFS/sdk/mappers/VersionMapper.java | 18 + .../sdk/mappers/netmap/NodeInfoMapper.java | 21 + .../mappers/netmap/PlacementPolicyMapper.java | 25 + .../sdk/mappers/netmap/ReplicaMapper.java | 17 + pom.xml | 23 + protosV2/pom.xml | 106 +++ .../src/main/proto/accounting/service.proto | 71 ++ .../src/main/proto/accounting/types.proto | 22 + protosV2/src/main/proto/acl/types.proto | 227 +++++ .../src/main/proto/apemanager/service.proto | 172 ++++ .../src/main/proto/apemanager/types.proto | 34 + .../src/main/proto/container/service.proto | 431 +++++++++ protosV2/src/main/proto/container/types.proto | 76 ++ protosV2/src/main/proto/lock/types.proto | 19 + protosV2/src/main/proto/netmap/service.proto | 162 ++++ protosV2/src/main/proto/netmap/types.proto | 323 +++++++ protosV2/src/main/proto/object/service.proto | 816 ++++++++++++++++++ protosV2/src/main/proto/object/types.proto | 266 ++++++ protosV2/src/main/proto/refs/types.proto | 150 ++++ protosV2/src/main/proto/session/service.proto | 69 ++ protosV2/src/main/proto/session/types.proto | 238 +++++ protosV2/src/main/proto/status/types.proto | 157 ++++ protosV2/src/main/proto/tombstone/types.proto | 27 + 80 files changed, 6315 insertions(+) create mode 100644 .gitignore create mode 100644 CONTRIBUTING.md create mode 100644 client/pom.xml create mode 100644 client/src/main/java/info/FrostFS/sdk/Client.java create mode 100644 client/src/main/java/info/FrostFS/sdk/GrpcClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/RequestConstructor.java create mode 100644 client/src/main/java/info/FrostFS/sdk/RequestSigner.java create mode 100644 client/src/main/java/info/FrostFS/sdk/Verifier.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java create mode 100644 cryptography/pom.xml create mode 100644 cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java create mode 100644 cryptography/src/main/java/info/FrostFS/sdk/Base58.java create mode 100644 cryptography/src/main/java/info/FrostFS/sdk/Helper.java create mode 100644 cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java create mode 100644 modelsV2/pom.xml create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/UUIDExtension.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/enums/NodeState.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectType.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/enums/StatusCode.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java create mode 100644 pom.xml create mode 100644 protosV2/pom.xml create mode 100644 protosV2/src/main/proto/accounting/service.proto create mode 100644 protosV2/src/main/proto/accounting/types.proto create mode 100644 protosV2/src/main/proto/acl/types.proto create mode 100644 protosV2/src/main/proto/apemanager/service.proto create mode 100644 protosV2/src/main/proto/apemanager/types.proto create mode 100644 protosV2/src/main/proto/container/service.proto create mode 100644 protosV2/src/main/proto/container/types.proto create mode 100644 protosV2/src/main/proto/lock/types.proto create mode 100644 protosV2/src/main/proto/netmap/service.proto create mode 100644 protosV2/src/main/proto/netmap/types.proto create mode 100644 protosV2/src/main/proto/object/service.proto create mode 100644 protosV2/src/main/proto/object/types.proto create mode 100644 protosV2/src/main/proto/refs/types.proto create mode 100644 protosV2/src/main/proto/session/service.proto create mode 100644 protosV2/src/main/proto/session/types.proto create mode 100644 protosV2/src/main/proto/status/types.proto create mode 100644 protosV2/src/main/proto/tombstone/types.proto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c3f0616 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +### Maven ### +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +.idea/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6538ca1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,156 @@ +# Contribution guide + +First, thank you for contributing! We love and encourage pull requests from +everyone. Please follow the guidelines: + +- Check the open [issues](https://git.frostfs.info/TrueCloudLab/frostfs-sdk-java/issues) and + [pull requests](https://git.frostfs.info/TrueCloudLab/frostfs-sdk-java/pulls) for existing + discussions. + +- Open an issue first, to discuss a new feature or enhancement. + +- Write tests and make sure the test suite passes locally and on CI. + +- Open a pull request and reference the relevant issue(s). + +- Make sure your commits are logically separated and have good comments + explaining the details of your change. + +- After receiving a feedback, amend your commits or add new ones as + appropriate. + +- **Have fun!** + +## Development Workflow + +Start by forking the `frostfs-sdk-java` repository, make changes in a branch and then +send a pull request. We encourage pull requests to discuss code changes. Here +are the steps in details: + +### Set up your git repository +Fork [FrostFS S3 Gateway +upstream](https://git.frostfs.info/repo/fork/346) source repository +to your own personal repository. Copy the URL of your fork (you will need it for +the `git clone` command below). + +```sh +$ git clone https://git.frostfs.info//frostfs-sdk-java.git +``` + +### Set up git remote as ``upstream`` +```sh +$ cd frostfs-sdk-java +$ git remote add upstream https://git.frostfs.info/TrueCloudLab/frostfs-sdk-java.git +$ git fetch upstream +$ git merge upstream/master +... +``` + +### Create your feature branch +Before making code changes, make sure you create a separate branch for these +changes. Maybe you will find it convenient to name a branch in +`/-` format. + +``` +$ git checkout -b feature/123-something_awesome +``` + +### Test your changes +After your code changes, make sure + +- To add test cases for the new code. +- To run `mvn clean verify` +- To squash your commits into a single commit or a series of logically separated + commits with `git rebase -i`. It's okay to force update your pull request. +- To run `mvn clean package` successfully. + +### Commit changes +After verification, commit your changes. There is a [great +post](https://chris.beams.io/posts/git-commit/) on how to write useful commit +messages. Try following this template: + +``` +[#Issue] Summary + +Description + + + + +``` + +``` +$ git commit -ams '[#123] Add some feature' +``` + +### Push to the branch +Push your locally committed changes to the remote origin (your fork) +``` +$ git push origin feature/123-something_awesome +``` + +### Create a Pull Request +Pull requests can be created via Forgejo. Refer to [this +document](https://docs.codeberg.org/collaborating/pull-requests-and-git-flow/) for +detailed steps on how to create a pull request. After a Pull Request gets peer +reviewed and approved, it will be merged. + +## DCO Sign off + +All authors to the project retain copyright to their work. However, to ensure +that they are only submitting work that they have rights to, we require +everyone to acknowledge this by signing their work. + +Any copyright notices in this repository should specify the authors as "the +contributors". + +To sign your work, just add a line like this at the end of your commit message: + +``` +Signed-off-by: Samii Sakisaka +``` + +This can be easily done with the `--signoff` option to `git commit`. + +By doing this you state that you can certify the following (from [The Developer +Certificate of Origin](https://developercertificate.org/)): + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` \ No newline at end of file diff --git a/README.md b/README.md index 9f37b2a..26697ca 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,94 @@ # frostfs-sdk-java Java implementation of FrostFS SDK + +## Prerequisites + +### Get the key for your wallet + +1. Get the address +```bash +cat | jq .accounts[0].address | tr -d '"' +``` + +2. Get the key +```bash +neo-go wallet export -w -d +``` + +## Example usage + +### Container + +```java +import info.FrostFS.sdk.enums.BasicAcl; +import info.FrostFS.sdk.jdo.Container; +import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; +import info.FrostFS.sdk.jdo.netmap.Replica; +import info.FrostFS.sdk.services.impl.FrostFSClient; + +public class ContainerExample { + + public void example() { + Client client = new Client( < your_key >); + GrpcClient grpcClient = new GrpcClient( < your_host >); + FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client); + + // Create container + var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)}); + var containerId = frostFSClient.createContainerAsync(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); + + // Get container + var container = frostFSClient.getContainerAsync(containerId); + + // List containers + var containerIds = frostFSClient.listContainersAsync(); + + // Delete container + frostFSClient.deleteContainerAsync(containerId); + } +} +``` + +### Object + +```java +import info.FrostFS.sdk.enums.ObjectType; +import info.FrostFS.sdk.jdo.ContainerId; +import info.FrostFS.sdk.jdo.ObjectAttribute; +import info.FrostFS.sdk.jdo.ObjectFilter; +import info.FrostFS.sdk.jdo.ObjectHeader; +import info.FrostFS.sdk.services.impl.FrostFSClient; + +import java.io.FileInputStream; +import java.io.IOException; + +public class ObjectExample { + + public void example() { + Client client = new Client( < your_key >); + GrpcClient grpcClient = new GrpcClient( < your_host >); + FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client); + + // Put object + info.FrostFS.sdk.jdo.ObjectId objectId; + try (FileInputStream fis = new FileInputStream("cat.jpg")) { + var cat = new ObjectHeader( + containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")} + ); + objectId = frostFSClient.putObjectAsync(cat, fis); + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Get object + var obj = frostFSClient.getObjectAsync(containerId, objectId); + + // Get object header + var objectHeader = frostFSClient.getObjectHeadAsync(containerId, objectId); + + // Search regular objects + var objectIds = frostFSClient.searchObjectsAsync(containerId, ObjectFilter.RootFilter()); + } +} +``` \ No newline at end of file diff --git a/client/pom.xml b/client/pom.xml new file mode 100644 index 0000000..f748035 --- /dev/null +++ b/client/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + info.FrostFS.sdk + FrostFS-sdk-java + 0.1.0 + + + client + + + 11 + 11 + UTF-8 + + + + + info.FrostFS.sdk + cryptography + 0.1.0 + + + info.FrostFS.sdk + protosV2 + 0.1.0 + + + info.FrostFS.sdk + modelsV2 + 0.1.0 + + + org.apache.logging.log4j + log4j-api + 2.7 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.7 + + + + \ No newline at end of file diff --git a/client/src/main/java/info/FrostFS/sdk/Client.java b/client/src/main/java/info/FrostFS/sdk/Client.java new file mode 100644 index 0000000..2d254b9 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/Client.java @@ -0,0 +1,36 @@ +package info.FrostFS.sdk; + +import info.FrostFS.sdk.jdo.OwnerId; +import info.FrostFS.sdk.jdo.Version; + +import static info.FrostFS.sdk.KeyExtension.getPrivateKeyFromWIF; +import static info.FrostFS.sdk.KeyExtension.loadPublicKey; + +public class Client { + private final OwnerId ownerId; + private final Version version = new Version(2, 13); + private final byte[] privateKey; + private final byte[] publicKey; + + public Client(String key) { + this.privateKey = getPrivateKeyFromWIF(key); + this.publicKey = loadPublicKey(privateKey); + this.ownerId = OwnerId.fromKey(publicKey); + } + + public OwnerId getOwnerId() { + return ownerId; + } + + public Version getVersion() { + return version; + } + + public byte[] getPrivateKey() { + return privateKey; + } + + public byte[] getPublicKey() { + return publicKey; + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/GrpcClient.java b/client/src/main/java/info/FrostFS/sdk/GrpcClient.java new file mode 100644 index 0000000..0b32277 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/GrpcClient.java @@ -0,0 +1,89 @@ +package info.FrostFS.sdk; + +import frostFS.container.ContainerServiceGrpc; +import frostFS.netmap.NetmapServiceGrpc; +import frostFS.object.ObjectServiceGrpc; +import frostFS.session.SessionServiceGrpc; +import io.grpc.Channel; +import io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.NettyChannelBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLException; +import java.net.URI; +import java.net.URISyntaxException; + +public class GrpcClient { + private static final Logger log = LoggerFactory.getLogger(GrpcClient.class); + + private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceBlockingClient; + private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceBlockingClient; + private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; + private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; + private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceBlockingClient; + + public GrpcClient(String host) { + Channel channel = initGrpcChannel(host); + this.containerServiceBlockingClient = ContainerServiceGrpc.newBlockingStub(channel); + this.netmapServiceBlockingClient = NetmapServiceGrpc.newBlockingStub(channel); + this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(channel); + this.objectServiceClient = ObjectServiceGrpc.newStub(channel); + this.sessionServiceBlockingClient = SessionServiceGrpc.newBlockingStub(channel); + } + + public static Channel initGrpcChannel(String host) { + URI uri; + try { + uri = new URI(host); + } catch (URISyntaxException exp) { + var message = String.format("Host %s has invalid format. Error: %s", host, exp.getMessage()); + log.error(message); + throw new IllegalArgumentException(message); + } + + var channelBuilder = NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()) + .usePlaintext(); + + switch (uri.getScheme()) { + case "https": + try { + channelBuilder.sslContext( + GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build() + ); + } catch (SSLException e) { + throw new RuntimeException(e); + } + break; + case "http": + break; + default: + var message = String.format("Host %s has invalid URI scheme: %s", host, uri.getScheme()); + log.error(message); + throw new IllegalArgumentException(message); + } + + return channelBuilder.build(); + } + + public ContainerServiceGrpc.ContainerServiceBlockingStub getContainerServiceBlockingClient() { + return containerServiceBlockingClient; + } + + public NetmapServiceGrpc.NetmapServiceBlockingStub getNetmapServiceBlockingClient() { + return netmapServiceBlockingClient; + } + + public ObjectServiceGrpc.ObjectServiceBlockingStub getObjectServiceBlockingClient() { + return objectServiceBlockingClient; + } + + public ObjectServiceGrpc.ObjectServiceStub getObjectServiceClient() { + return objectServiceClient; + } + + public SessionServiceGrpc.SessionServiceBlockingStub getSessionServiceBlockingClient() { + return sessionServiceBlockingClient; + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java b/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java new file mode 100644 index 0000000..304a878 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java @@ -0,0 +1,50 @@ +package info.FrostFS.sdk; + +import com.google.protobuf.AbstractMessage; +import frostFS.session.Types; +import info.FrostFS.sdk.jdo.MetaHeader; +import info.FrostFS.sdk.mappers.MetaHeaderMapper; + +import static info.FrostFS.sdk.RequestSigner.signMessagePart; +import static java.util.Objects.isNull; + +public class RequestConstructor { + + public static void addMetaHeader(AbstractMessage.Builder request) { + addMetaHeader(request, null); + } + + public static void addMetaHeader(AbstractMessage.Builder request, Types.RequestMetaHeader metaHeader) { + if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) { + metaHeader = MetaHeaderMapper.toGrpcMessage(MetaHeader.getDefault()); + var field = request.getDescriptorForType().findFieldByName("meta_header"); + request.setField(field, metaHeader); + } + } + + public static void addObjectSessionToken(AbstractMessage.Builder request, + Types.SessionToken sessionToken, + frostFS.refs.Types.ContainerID cid, + frostFS.refs.Types.ObjectID oid, + Types.ObjectSessionContext.Verb verb, + byte[] publicKey, byte[] privateKey) { + var headerField = request.getDescriptorForType().findFieldByName("meta_header"); + var header = (Types.RequestMetaHeader) request.getField(headerField); + if (header.getSessionToken().getSerializedSize() > 0) { + return; + } + + var ctx = Types.ObjectSessionContext.newBuilder() + .setTarget(Types.ObjectSessionContext.Target.newBuilder().setContainer(cid).addObjects(oid).build()) + .setVerb(verb) + .build(); + + var body = sessionToken.getBody().toBuilder().setObject(ctx).build(); + sessionToken = sessionToken.toBuilder() + .setSignature(signMessagePart(publicKey, privateKey, body)) + .setBody(body) + .build(); + + request.setField(headerField, header.toBuilder().setSessionToken(sessionToken).build()); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java b/client/src/main/java/info/FrostFS/sdk/RequestSigner.java new file mode 100644 index 0000000..264d52a --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/RequestSigner.java @@ -0,0 +1,114 @@ +package info.FrostFS.sdk; + +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.ByteString; +import frostFS.session.Types; +import org.apache.commons.codec.digest.DigestUtils; +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.crypto.signers.HMacDSAKCalculator; + +import java.math.BigInteger; +import java.security.Signature; + +import static info.FrostFS.sdk.KeyExtension.loadPrivateKey; +import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; +import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; + +public class RequestSigner { + public static final int RFC6979_SIGNATURE_SIZE = 64; + + public static byte[] signData(byte[] privateKey, byte[] data) { + var hash = new byte[65]; + hash[0] = 0x04; + try { + Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format"); + signature.initSign(loadPrivateKey(privateKey)); + signature.update(DigestUtils.sha512(data)); + byte[] sig = signature.sign(); + System.arraycopy(sig, 0, hash, 1, sig.length); + } catch (Exception exp) { + throw new RuntimeException(exp); + } + + return hash; + } + + public static byte[] signRFC6979(byte[] privateKey, byte[] data) { + var digest = createSHA256(); + var secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); + + var ecParameters = new ECDomainParameters(secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN()); + var ecPrivateKey = new ECPrivateKeyParameters(new BigInteger(1, privateKey), ecParameters); + var signer = new ECDSASigner(new HMacDSAKCalculator(digest)); + var hash = new byte[digest.getDigestSize()]; + + digest.update(data, 0, data.length); + digest.doFinal(hash, 0); + signer.init(true, ecPrivateKey); + + var rs = signer.generateSignature(hash); + var rBytes = asUnsignedByteArray(rs[0]); + var sBytes = asUnsignedByteArray(rs[1]); + + var signature = new byte[RFC6979_SIGNATURE_SIZE]; + var index = RFC6979_SIGNATURE_SIZE / 2 - rBytes.length; + System.arraycopy(rBytes, 0, signature, index, rBytes.length); + index = RFC6979_SIGNATURE_SIZE - sBytes.length; + System.arraycopy(sBytes, 0, signature, index, sBytes.length); + return signature; + } + + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, byte[] privateKey, AbstractMessage message) { + return frostFS.refs.Types.SignatureRFC6979.newBuilder() + .setKey(ByteString.copyFrom(publicKey)) + .setSign(ByteString.copyFrom(signRFC6979(privateKey, message.toByteArray()))) + .build(); + } + + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, byte[] privateKey, ByteString data) { + return frostFS.refs.Types.SignatureRFC6979.newBuilder() + .setKey(ByteString.copyFrom(publicKey)) + .setSign(ByteString.copyFrom(signRFC6979(privateKey, data.toByteArray()))) + .build(); + } + + public static frostFS.refs.Types.Signature signMessagePart(byte[] publicKey, byte[] privateKey, AbstractMessage data) { + var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); + + return frostFS.refs.Types.Signature.newBuilder() + .setKey(ByteString.copyFrom(publicKey)) + .setSign(ByteString.copyFrom(signData(privateKey, data2Sign))) + .build(); + } + + public static void sign(AbstractMessage.Builder request, byte[] publicKey, byte[] privateKey) { + var meta = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("meta_header")); + var body = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("body")); + var verify = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("verify_header")); + + AbstractMessage.Builder verifyBuilder; + if (verify instanceof Types.RequestVerificationHeader) { + verifyBuilder = Types.RequestVerificationHeader.newBuilder(); + } else if (verify instanceof Types.ResponseVerificationHeader) { + verifyBuilder = Types.ResponseVerificationHeader.newBuilder(); + } else { + throw new IllegalArgumentException("Unsopported message type"); + } + + var verifyOrigin = (AbstractMessage) verify.getField(verify.getDescriptorForType().findFieldByName("origin")); + if (verifyOrigin.getSerializedSize() == 0) { + verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("body_signature"), signMessagePart(publicKey, privateKey, body)); + } else { + verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin); + } + + verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"), signMessagePart(publicKey, privateKey, meta)); + verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"), signMessagePart(publicKey, privateKey, verifyOrigin)); + + request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build()); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/Verifier.java b/client/src/main/java/info/FrostFS/sdk/Verifier.java new file mode 100644 index 0000000..657be82 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/Verifier.java @@ -0,0 +1,116 @@ +package info.FrostFS.sdk; + +import com.google.protobuf.AbstractMessage; +import frostFS.refs.Types; +import info.FrostFS.sdk.mappers.StatusMapper; +import org.apache.commons.codec.digest.DigestUtils; +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.crypto.signers.ECDSASigner; +import org.bouncycastle.crypto.signers.HMacDSAKCalculator; + +import java.math.BigInteger; +import java.security.PublicKey; +import java.security.Signature; +import java.util.Arrays; + +import static info.FrostFS.sdk.KeyExtension.getPublicKeyByPublic; +import static java.util.Objects.isNull; +import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; +import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; + +public class Verifier { + public static final int RFC6979_SIGNATURE_SIZE = 64; + + public static boolean verifyRFC6979(Types.SignatureRFC6979 signature, AbstractMessage message) { + return verifyRFC6979(signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray()); + } + + public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) { + if (isNull(publicKey) || isNull(data) || isNull(sig)) return false; + + var rs = decodeSignature(sig); + var digest = createSHA256(); + var signer = new ECDSASigner(new HMacDSAKCalculator(digest)); + var secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); + var ecParameters = new ECDomainParameters(secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN()); + var ecPublicKey = new ECPublicKeyParameters(secp256R1.getCurve().decodePoint(publicKey), ecParameters); + var hash = new byte[digest.getDigestSize()]; + digest.update(data, 0, data.length); + digest.doFinal(hash, 0); + signer.init(false, ecPublicKey); + return signer.verifySignature(hash, rs[0], rs[1]); + } + + private static BigInteger[] decodeSignature(byte[] sig) { + if (sig.length != RFC6979_SIGNATURE_SIZE) { + throw new IllegalArgumentException( + String.format("Wrong signature size. Expected length=%s, actual=%s", + RFC6979_SIGNATURE_SIZE, sig.length) + ); + } + + var rs = new BigInteger[2]; + + rs[0] = fromUnsignedByteArray(Arrays.copyOfRange(sig, 0, (RFC6979_SIGNATURE_SIZE / 2) - 1)); + rs[1] = fromUnsignedByteArray(Arrays.copyOfRange(sig, RFC6979_SIGNATURE_SIZE / 2, RFC6979_SIGNATURE_SIZE - 1)); + return rs; + } + + public static void checkResponse(AbstractMessage response) { + if (!verify(response)) { + throw new IllegalArgumentException("Invalid response"); + } + var metaHeader = (frostFS.session.Types.ResponseMetaHeader) response + .getField(response.getDescriptorForType().findFieldByName("meta_header")); + var status = StatusMapper.toModel(metaHeader.getStatus()); + if (!status.isSuccess()) { + throw new IllegalArgumentException(status.toString()); + } + } + + public static boolean verify(AbstractMessage message) { + var body = (AbstractMessage) message.getField(message.getDescriptorForType().findFieldByName("body")); + var metaHeader = (frostFS.session.Types.ResponseMetaHeader) + message.getField(message.getDescriptorForType().findFieldByName("meta_header")); + var verifyHeader = (frostFS.session.Types.ResponseVerificationHeader) + message.getField(message.getDescriptorForType().findFieldByName("verify_header")); + + return verifyMatryoshkaLevel(body, metaHeader, verifyHeader); + } + + public static boolean verifyMatryoshkaLevel(AbstractMessage body, + frostFS.session.Types.ResponseMetaHeader meta, + frostFS.session.Types.ResponseVerificationHeader verification) { + if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false; + var origin = verification.getOrigin(); + if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false; + if (origin.getSerializedSize() == 0) { + return verifyMessagePart(verification.getBodySignature(), body); + } + return verification.getBodySignature().getSerializedSize() == 0 + && verifyMatryoshkaLevel(body, meta.getOrigin(), origin); + } + + public static boolean verifyMessagePart(Types.Signature sig, AbstractMessage data) { + if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false; + + var publicKey = getPublicKeyByPublic(sig.getKey().toByteArray()); + + var data2Verify = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); + return verifyData(publicKey, data2Verify, sig.getSign().toByteArray()); + } + + public static boolean verifyData(PublicKey publicKey, byte[] data, byte[] sig) { + try { + Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format"); + signature.initVerify(publicKey); + signature.update(DigestUtils.sha512(data)); + return signature.verify(Arrays.copyOfRange(sig, 1, sig.length)); + } catch (Exception exp) { + throw new RuntimeException(exp); + } + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java b/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java new file mode 100644 index 0000000..3cdb8c2 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java @@ -0,0 +1,16 @@ +package info.FrostFS.sdk.services; + +import info.FrostFS.sdk.jdo.Container; +import info.FrostFS.sdk.jdo.ContainerId; + +import java.util.List; + +public interface ContainerClient { + Container getContainerAsync(ContainerId cid); + + List listContainersAsync(); + + ContainerId createContainerAsync(Container container); + + void deleteContainerAsync(ContainerId cid); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java b/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java new file mode 100644 index 0000000..682d52a --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java @@ -0,0 +1,19 @@ +package info.FrostFS.sdk.services; + +import info.FrostFS.sdk.jdo.*; + +import java.io.FileInputStream; + +public interface ObjectClient { + ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId); + + ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId); + + ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload); + + ObjectId putObjectAsync(ObjectHeader header, byte[] payload); + + void deleteObjectAsync(ContainerId containerId, ObjectId objectId); + + Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java new file mode 100644 index 0000000..782c218 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java @@ -0,0 +1,107 @@ +package info.FrostFS.sdk.services.impl; + +import frostFS.container.ContainerServiceGrpc; +import frostFS.container.Service; +import info.FrostFS.sdk.Client; +import info.FrostFS.sdk.Verifier; +import info.FrostFS.sdk.jdo.Container; +import info.FrostFS.sdk.jdo.ContainerId; +import info.FrostFS.sdk.mappers.ContainerIdMapper; +import info.FrostFS.sdk.mappers.ContainerMapper; +import info.FrostFS.sdk.mappers.OwnerIdMapper; +import info.FrostFS.sdk.mappers.VersionMapper; +import info.FrostFS.sdk.services.ContainerClient; + +import java.util.List; +import java.util.stream.Collectors; + +import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.RequestSigner.sign; +import static info.FrostFS.sdk.RequestSigner.signRFC6979; + +public class ContainerService implements ContainerClient { + private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient; + private final Client client; + + public ContainerService(ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient, Client client) { + this.containerServiceAsyncClient = containerServiceAsyncClient; + this.client = client; + } + + public Container getContainerAsync(ContainerId cid) { + var request = Service.GetRequest.newBuilder() + .setBody( + Service.GetRequest.Body.newBuilder().setContainerId(ContainerIdMapper.toGrpcMessage(cid)).build() + ); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = containerServiceAsyncClient.get(request.build()); + + Verifier.checkResponse(response); + return ContainerMapper.toModel(response.getBody().getContainer()); + } + + public List listContainersAsync() { + var request = Service.ListRequest.newBuilder() + .setBody( + Service.ListRequest.Body.newBuilder().setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())).build() + ); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = containerServiceAsyncClient.list(request.build()); + + Verifier.checkResponse(response); + + return response.getBody().getContainerIdsList().stream() + .map(cid -> ContainerId.fromHash(cid.getValue().toByteArray())) + .collect(Collectors.toList()); + } + + public ContainerId createContainerAsync(Container container) { + var grpcContainer = ContainerMapper.toGrpcMessage(container); + + grpcContainer = grpcContainer.toBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(client.getVersion())) + .build(); + + var request = Service.PutRequest.newBuilder() + .setBody( + Service.PutRequest.Body.newBuilder() + .setContainer(grpcContainer) + .setSignature(signRFC6979(client.getPublicKey(), client.getPrivateKey(), grpcContainer)) + .build() + ); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = containerServiceAsyncClient.put(request.build()); + + Verifier.checkResponse(response); + return ContainerId.fromHash(response.getBody().getContainerId().getValue().toByteArray()); + } + + public void deleteContainerAsync(ContainerId cid) { + var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid); + + var request = Service.DeleteRequest.newBuilder() + .setBody( + Service.DeleteRequest.Body.newBuilder() + .setContainerId(grpcContainerId) + .setSignature(signRFC6979(client.getPublicKey(), client.getPrivateKey(), grpcContainerId.getValue())) + .build() + ); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = containerServiceAsyncClient.delete(request.build()); + + Verifier.checkResponse(response); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java b/client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java new file mode 100644 index 0000000..a720d4c --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java @@ -0,0 +1,85 @@ +package info.FrostFS.sdk.services.impl; + +import info.FrostFS.sdk.Client; +import info.FrostFS.sdk.GrpcClient; +import info.FrostFS.sdk.jdo.*; +import info.FrostFS.sdk.services.ContainerClient; +import info.FrostFS.sdk.services.ObjectClient; + +import java.io.FileInputStream; +import java.util.List; + +public class FrostFSClient implements ContainerClient, ObjectClient { + private final ContainerService containerService; + private final NetmapService netmapService; + private final ObjectService objectService; + + public FrostFSClient(GrpcClient grpcClient, Client client) { + this.containerService = new ContainerService(grpcClient.getContainerServiceBlockingClient(), client); + this.netmapService = new NetmapService(grpcClient.getNetmapServiceBlockingClient(), client); + SessionService sessionService = new SessionService(grpcClient.getSessionServiceBlockingClient(), client); + this.objectService = new ObjectService( + grpcClient.getObjectServiceBlockingClient(), grpcClient.getObjectServiceClient(), sessionService, client + ); + checkFrostFsVersionSupport(client); + } + + private void checkFrostFsVersionSupport(Client client) { + var localNodeInfo = netmapService.getLocalNodeInfoAsync(); + if (!localNodeInfo.getVersion().isSupported(client.getVersion())) { + var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion()); + System.out.println(msg); + throw new IllegalArgumentException(msg); + } + } + + @Override + public Container getContainerAsync(ContainerId cid) { + return containerService.getContainerAsync(cid); + } + + @Override + public List listContainersAsync() { + return containerService.listContainersAsync(); + } + + @Override + public ContainerId createContainerAsync(Container container) { + return containerService.createContainerAsync(container); + } + + @Override + public void deleteContainerAsync(ContainerId cid) { + containerService.deleteContainerAsync(cid); + } + + @Override + public ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId) { + return objectService.getObjectHeadAsync(containerId, objectId); + } + + @Override + public ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId) { + return objectService.getObjectAsync(containerId, objectId); + } + + @Override + public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) { + return objectService.putObjectAsync(header, payload); + } + + @Override + public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) { + return objectService.putObjectAsync(header, payload); + } + + @Override + public void deleteObjectAsync(ContainerId containerId, ObjectId objectId) { + objectService.deleteObjectAsync(containerId, objectId); + } + + @Override + public Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters) { + return objectService.searchObjectsAsync(cid, filters); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java new file mode 100644 index 0000000..eafc40f --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java @@ -0,0 +1,42 @@ +package info.FrostFS.sdk.services.impl; + +import frostFS.netmap.NetmapServiceGrpc; +import frostFS.netmap.Service; +import info.FrostFS.sdk.Client; +import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper; + +import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.RequestSigner.sign; + +public class NetmapService { + private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceAsyncClient; + private final Client client; + + public NetmapService(NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceAsyncClient, Client client) { + this.netmapServiceAsyncClient = netmapServiceAsyncClient; + this.client = client; + } + + public NodeInfo getLocalNodeInfoAsync() { + var request = Service.LocalNodeInfoRequest.newBuilder() + .setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build()); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = netmapServiceAsyncClient.localNodeInfo(request.build()); + + return NodeInfoMapper.toModel(response.getBody()); + } + + public Service.NetworkInfoResponse getNetworkInfoAsync() { + var request = Service.NetworkInfoRequest.newBuilder() + .setBody(Service.NetworkInfoRequest.Body.newBuilder().build()); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + return netmapServiceAsyncClient.networkInfo(request.build()); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java new file mode 100644 index 0000000..8350bd7 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java @@ -0,0 +1,48 @@ +package info.FrostFS.sdk.services.impl; + +import frostFS.object.Service; +import frostFS.object.Types; +import info.FrostFS.sdk.Verifier; + +import java.util.Iterator; + +public class ObjectReader { + public Iterator call; + + public ObjectReader(Iterator call) { + this.call = call; + } + + public Types.Object readHeader() { + if (!call.hasNext()) { + throw new IllegalArgumentException("unexpected end of stream"); + } + + var response = call.next(); + Verifier.checkResponse(response); + + if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.INIT_FIELD_NUMBER) { + throw new IllegalArgumentException("unexpected message type"); + } + + return Types.Object.newBuilder() + .setObjectId(response.getBody().getInit().getObjectId()) + .setHeader(response.getBody().getInit().getHeader()) + .build(); + } + + public byte[] readChunk() { + if (!call.hasNext()) { + return null; + } + + var response = call.next(); + Verifier.checkResponse(response); + + if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.CHUNK_FIELD_NUMBER) { + throw new IllegalArgumentException("unexpected message type"); + } + + return response.getBody().getChunk().toByteArray(); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java new file mode 100644 index 0000000..f90fe84 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java @@ -0,0 +1,257 @@ +package info.FrostFS.sdk.services.impl; + +import com.google.common.collect.Iterables; +import com.google.protobuf.ByteString; +import frostFS.object.ObjectServiceGrpc; +import frostFS.object.Service; +import frostFS.refs.Types; +import info.FrostFS.sdk.Client; +import info.FrostFS.sdk.Verifier; +import info.FrostFS.sdk.jdo.*; +import info.FrostFS.sdk.mappers.*; +import info.FrostFS.sdk.services.ObjectClient; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static info.FrostFS.sdk.Helper.getSha256; +import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.RequestConstructor.addObjectSessionToken; +import static info.FrostFS.sdk.RequestSigner.sign; +import static java.util.Objects.nonNull; + +public class ObjectService implements ObjectClient { + private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; + private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; + private final SessionService sessionService; + private final Client client; + + + public ObjectService(ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceAsyncClient, + ObjectServiceGrpc.ObjectServiceStub objectServiceClient, + SessionService sessionService, + Client client) { + this.objectServiceBlockingClient = objectServiceAsyncClient; + this.objectServiceClient = objectServiceClient; + this.client = client; + this.sessionService = sessionService; + } + + @Override + public ObjectHeader getObjectHeadAsync(ContainerId cid, ObjectId oid) { + var request = Service.HeadRequest.newBuilder() + .setBody( + Service.HeadRequest.Body.newBuilder() + .setAddress( + Types.Address.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) + .build() + ).build() + ); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = objectServiceBlockingClient.head(request.build()); + Verifier.checkResponse(response); + + return ObjectHeaderMapper.toModel(response.getBody().getHeader().getHeader()); + } + + @Override + public ObjectFrostFs getObjectAsync(ContainerId cid, ObjectId oid) { + var sessionToken = sessionService.createSessionAsync(-1); + + var request = Service.GetRequest.newBuilder() + .setBody( + Service.GetRequest.Body.newBuilder() + .setAddress( + Types.Address.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) + .build() + ) + .setRaw(false) + .build() + ); + + addMetaHeader(request, null); + addObjectSessionToken( + request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid), + frostFS.session.Types.ObjectSessionContext.Verb.GET, client.getPublicKey(), client.getPrivateKey() + ); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var obj = getObject(request.build()); + + return ObjectMapper.toModel(obj); + } + + @Override + public void deleteObjectAsync(ContainerId cid, ObjectId oid) { + var request = Service.DeleteRequest.newBuilder() + .setBody( + Service.DeleteRequest.Body.newBuilder() + .setAddress( + Types.Address.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) + .build() + ) + .build()); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var response = objectServiceBlockingClient.delete(request.build()); + Verifier.checkResponse(response); + } + + @Override + public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) { + return putObject(header, payload); + } + + @Override + public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) { + return putObject(header, new ByteArrayInputStream(payload)); + } + + @Override + public Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters) { + var body = Service.SearchRequest.Body.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setVersion(1); + + for (ObjectFilter filter : filters) { + body.addFilters(ObjectFilterMapper.toGrpcMessage(filter)); + } + + var request = Service.SearchRequest.newBuilder() + .setBody(body.build()); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + var objectsIds = searchObjects(request.build()); + + return Iterables.transform(objectsIds, input -> ObjectId.fromHash(input.getValue().toByteArray())); + } + + private frostFS.object.Types.Object getObject(Service.GetRequest request) { + var iterator = getObjectInit(request); + var obj = iterator.readHeader(); + var payload = new byte[Math.toIntExact(obj.getHeader().getPayloadLength())]; + var offset = 0; + var chunk = iterator.readChunk(); + + while (nonNull(chunk)) { + System.arraycopy(chunk, 0, payload, offset, chunk.length); + offset += chunk.length; + chunk = iterator.readChunk(); + } + + return obj.toBuilder().setPayload(ByteString.copyFrom(payload)).build(); + } + + private ObjectReader getObjectInit(Service.GetRequest initRequest) { + if (initRequest.getSerializedSize() == 0) { + throw new IllegalArgumentException(initRequest.getClass().getName()); + } + + return new ObjectReader(objectServiceBlockingClient.get(initRequest)); + } + + private ObjectId putObject(ObjectHeader header, InputStream payload) { + var sessionToken = sessionService.createSessionAsync(-1); + var hdr = ObjectHeaderMapper.toGrpcMessage(header); + + hdr = hdr.toBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(client.getVersion())) + .build(); + + var oid = Types.ObjectID.newBuilder().setValue(getSha256(hdr)).build(); + + var request = Service.PutRequest.newBuilder() + .setBody( + Service.PutRequest.Body.newBuilder() + .setInit( + Service.PutRequest.Body.Init.newBuilder().setHeader(hdr).build() + ).build() + ); + + addMetaHeader(request, null); + addObjectSessionToken( + request, sessionToken, hdr.getContainerId(), oid, frostFS.session.Types.ObjectSessionContext.Verb.PUT, + client.getPublicKey(), client.getPrivateKey() + ); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + + var writer = putObjectInit(request.build()); + + var buffer = new byte[Constants.OBJECT_CHUNK_SIZE]; + int bufferLength = 0; + try { + bufferLength = payload.readNBytes(buffer, 0, Constants.OBJECT_CHUNK_SIZE); + while (bufferLength > 0) { + request.setBody( + Service.PutRequest.Body.newBuilder() + .setChunk(ByteString.copyFrom(Arrays.copyOfRange(buffer, 0, bufferLength))) + .build() + ) + .clearVerifyHeader(); + sign(request, client.getPublicKey(), client.getPrivateKey()); + writer.write(request.build()); + bufferLength = payload.readNBytes(buffer, 0, Constants.OBJECT_CHUNK_SIZE); + } + } catch ( + IOException e) { + throw new RuntimeException(e); + } + + var response = writer.complete(); + Verifier.checkResponse(response); + + return ObjectId.fromHash(response.getBody().getObjectId().getValue().toByteArray()); + } + + private ObjectWriter putObjectInit(Service.PutRequest initRequest) { + if (initRequest.getSerializedSize() == 0) { + throw new IllegalArgumentException(initRequest.getClass().getName()); + } + + ObjectWriter writer = new ObjectWriter(objectServiceClient); + writer.write(initRequest); + return writer; + } + + private Iterable searchObjects(Service.SearchRequest request) { + var reader = getSearchReader(request); + var ids = reader.read(); + List result = new ArrayList<>(); + + while (nonNull(ids) && !ids.isEmpty()) { + result.addAll(ids); + ids = reader.read(); + } + + return result; + } + + private SearchReader getSearchReader(Service.SearchRequest initRequest) { + if (initRequest.getSerializedSize() == 0) { + throw new IllegalArgumentException(initRequest.getClass().getName()); + } + + return new SearchReader(objectServiceBlockingClient.search(initRequest)); + } + +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java new file mode 100644 index 0000000..01ae85e --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java @@ -0,0 +1,59 @@ +package info.FrostFS.sdk.services.impl; + +import frostFS.object.ObjectServiceGrpc; +import frostFS.object.Service; +import io.grpc.stub.StreamObserver; + +import static java.util.Objects.isNull; + +public class ObjectWriter { + private final StreamObserver requestObserver; + private final PutResponseCallback responseObserver; + + public ObjectWriter(ObjectServiceGrpc.ObjectServiceStub objectServiceStub) { + PutResponseCallback responseObserver = new PutResponseCallback(); + + this.responseObserver = responseObserver; + this.requestObserver = objectServiceStub.put(responseObserver); + } + + public void write(Service.PutRequest request) { + if (isNull(request)) { + throw new IllegalArgumentException(); + } + + requestObserver.onNext(request); + } + + public Service.PutResponse complete() { + requestObserver.onCompleted(); + + while (isNull(responseObserver.getResponse())) { + System.out.println("Waiting response"); + } + + return responseObserver.getResponse(); + } + + private static class PutResponseCallback implements StreamObserver { + private Service.PutResponse response; + + @Override + public void onNext(Service.PutResponse putResponse) { + this.response = putResponse; + } + + @Override + public void onError(Throwable throwable) { + throw new RuntimeException(throwable); + } + + @Override + public void onCompleted() { + } + + public Service.PutResponse getResponse() { + return response; + } + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java b/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java new file mode 100644 index 0000000..b0d3620 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java @@ -0,0 +1,26 @@ +package info.FrostFS.sdk.services.impl; + +import frostFS.object.Service; +import info.FrostFS.sdk.Verifier; + +import java.util.Iterator; +import java.util.List; + +public class SearchReader { + public Iterator call; + + public SearchReader(Iterator call) { + this.call = call; + } + + public List read() { + if (!call.hasNext()) { + return null; + } + + var response = call.next(); + Verifier.checkResponse(response); + + return response.getBody().getIdListList(); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java new file mode 100644 index 0000000..832dc52 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java @@ -0,0 +1,55 @@ +package info.FrostFS.sdk.services.impl; + +import frostFS.session.Service; +import frostFS.session.SessionServiceGrpc; +import frostFS.session.Types; +import info.FrostFS.sdk.Client; +import info.FrostFS.sdk.mappers.OwnerIdMapper; + +import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.RequestSigner.sign; + +public class SessionService { + private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient; + private final Client client; + + public SessionService(SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient, Client client) { + this.sessionServiceAsyncClient = sessionServiceAsyncClient; + this.client = client; + } + + protected Types.SessionToken createSessionAsync(long expiration) { + var request = Service.CreateRequest.newBuilder() + .setBody( + Service.CreateRequest.Body.newBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())) + .setExpiration(expiration).build() + ); + + addMetaHeader(request, null); + sign(request, client.getPublicKey(), client.getPrivateKey()); + + return createSession(request.build()); + } + + private Types.SessionToken createSession(Service.CreateRequest request) { + var resp = sessionServiceAsyncClient.create(request); + + var lifetime = Types.SessionToken.Body.TokenLifetime.newBuilder() + .setExp(request.getBody().getExpiration()) + .setIat(resp.getMetaHeader().getEpoch()) + .setNbf(resp.getMetaHeader().getEpoch()) + .build(); + + var body = Types.SessionToken.Body.newBuilder() + .setId(resp.getBody().getId()) + .setSessionKey(resp.getBody().getSessionKey()) + .setOwnerId(request.getBody().getOwnerId()) + .setLifetime(lifetime) + .build(); + + return Types.SessionToken.newBuilder() + .setBody(body) + .build(); + } +} diff --git a/cryptography/pom.xml b/cryptography/pom.xml new file mode 100644 index 0000000..9af2880 --- /dev/null +++ b/cryptography/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + info.FrostFS.sdk + FrostFS-sdk-java + 0.1.0 + + + cryptography + + + 11 + 11 + UTF-8 + 3.23.0 + + + + + commons-codec + commons-codec + 1.17.0 + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + org.bouncycastle + bcprov-jdk18on + 1.78.1 + + + org.bouncycastle + bcpkix-jdk18on + 1.78.1 + + + + \ No newline at end of file diff --git a/cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java b/cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java new file mode 100644 index 0000000..5274f60 --- /dev/null +++ b/cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java @@ -0,0 +1,12 @@ +package info.FrostFS.sdk; + +public class ArrayHelper { + + public static byte[] concat(byte[] startArray, byte[] endArray) { + byte[] result = new byte[startArray.length + endArray.length]; + + System.arraycopy(startArray, 0, result, 0, startArray.length); + System.arraycopy(endArray, 0, result, startArray.length, endArray.length); + return result; + } +} diff --git a/cryptography/src/main/java/info/FrostFS/sdk/Base58.java b/cryptography/src/main/java/info/FrostFS/sdk/Base58.java new file mode 100644 index 0000000..9fe27af --- /dev/null +++ b/cryptography/src/main/java/info/FrostFS/sdk/Base58.java @@ -0,0 +1,127 @@ +package info.FrostFS.sdk; + +import java.util.Arrays; + +import static info.FrostFS.sdk.ArrayHelper.concat; +import static info.FrostFS.sdk.Helper.getSha256; +import static java.util.Objects.isNull; + +public class Base58 { + public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); + private static final char ENCODED_ZERO = ALPHABET[0]; + private static final int[] INDEXES = new int[128]; + + static { + Arrays.fill(INDEXES, -1); + for (int i = 0; i < ALPHABET.length; i++) { + INDEXES[ALPHABET[i]] = i; + } + } + + public static byte[] base58CheckDecode(String input) { + if (isNull(input) || input.isEmpty()) { + throw new IllegalArgumentException("Input value is missing"); + } + + byte[] buffer = decode(input); + if (buffer.length < 4) { + throw new IllegalArgumentException(); + } + + byte[] decode = Arrays.copyOfRange(buffer, 0, buffer.length - 4); + byte[] checksum = getSha256(getSha256(decode)); + if (!Arrays.equals( + Arrays.copyOfRange(buffer, buffer.length - 4, buffer.length), + Arrays.copyOfRange(checksum, 0, 4) + )) { + throw new IllegalArgumentException(); + } + + return decode; + } + + public static String base58CheckEncode(byte[] data) { + byte[] checksum = getSha256(getSha256(data)); + var buffer = concat(data, Arrays.copyOfRange(checksum, 0, 4)); + var ret = encode(buffer); + return ret; + } + + public static String encode(byte[] input) { + if (input.length == 0) { + return ""; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input.length && input[zeros] == 0) { + ++zeros; + } + // Convert base-256 digits to base-58 digits (plus conversion to ASCII characters) + input = Arrays.copyOf(input, input.length); // since we modify it in-place + char[] encoded = new char[input.length * 2]; // upper bound + int outputStart = encoded.length; + for (int inputStart = zeros; inputStart < input.length; ) { + encoded[--outputStart] = ALPHABET[divmod(input, inputStart, 256, 58)]; + if (input[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Preserve exactly as many leading encoded zeros in output as there were leading zeros in input. + while (outputStart < encoded.length && encoded[outputStart] == ENCODED_ZERO) { + ++outputStart; + } + while (--zeros >= 0) { + encoded[--outputStart] = ENCODED_ZERO; + } + // Return encoded string (including encoded leading zeros). + return new String(encoded, outputStart, encoded.length - outputStart); + } + + public static byte[] decode(String input) { + if (input.isEmpty()) { + return new byte[0]; + } + // Convert the base58-encoded ASCII chars to a base58 byte sequence (base58 digits). + byte[] input58 = new byte[input.length()]; + for (int i = 0; i < input.length(); ++i) { + char c = input.charAt(i); + int digit = c < 128 ? INDEXES[c] : -1; + if (digit < 0) { + throw new IllegalArgumentException(String.format("Invalid character in Base58: 0x%04x", (int) c)); + } + input58[i] = (byte) digit; + } + // Count leading zeros. + int zeros = 0; + while (zeros < input58.length && input58[zeros] == 0) { + ++zeros; + } + // Convert base-58 digits to base-256 digits. + byte[] decoded = new byte[input.length()]; + int outputStart = decoded.length; + for (int inputStart = zeros; inputStart < input58.length; ) { + decoded[--outputStart] = divmod(input58, inputStart, 58, 256); + if (input58[inputStart] == 0) { + ++inputStart; // optimization - skip leading zeros + } + } + // Ignore extra leading zeroes that were added during the calculation. + while (outputStart < decoded.length && decoded[outputStart] == 0) { + ++outputStart; + } + // Return decoded data (including original number of leading zeros). + return Arrays.copyOfRange(decoded, outputStart - zeros, decoded.length); + } + + private static byte divmod(byte[] number, int firstDigit, int base, int divisor) { + // this is just long division which accounts for the base of the input digits + int remainder = 0; + for (int i = firstDigit; i < number.length; i++) { + int digit = (int) number[i] & 0xFF; + int temp = remainder * base + digit; + number[i] = (byte) (temp / divisor); + remainder = temp % divisor; + } + return (byte) remainder; + } +} diff --git a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java b/cryptography/src/main/java/info/FrostFS/sdk/Helper.java new file mode 100644 index 0000000..e4e1460 --- /dev/null +++ b/cryptography/src/main/java/info/FrostFS/sdk/Helper.java @@ -0,0 +1,36 @@ +package info.FrostFS.sdk; + +import com.google.protobuf.AbstractMessage; +import com.google.protobuf.ByteString; +import org.bouncycastle.crypto.digests.RIPEMD160Digest; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Helper { + + public static byte[] getRIPEMD160(byte[] value) { + var hash = new byte[20]; + var digest = new RIPEMD160Digest(); + digest.update(value, 0, value.length); + digest.doFinal(hash, 0); + return hash; + } + + public static byte[] getSha256(byte[] value) { + try { + return MessageDigest.getInstance("SHA-256").digest(value); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static ByteString getSha256(AbstractMessage value) { + return ByteString.copyFrom(getSha256(value.toByteArray())); + } + + public static String пуеHexString(byte[] array) { + return String.format("%0" + (array.length << 1) + "x", new BigInteger(1, array)); + } +} diff --git a/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java b/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java new file mode 100644 index 0000000..b8c5ab6 --- /dev/null +++ b/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java @@ -0,0 +1,161 @@ +package info.FrostFS.sdk; + +import org.bouncycastle.asn1.sec.SECNamedCurves; +import org.bouncycastle.asn1.sec.SECObjectIdentifiers; +import org.bouncycastle.asn1.x9.X9ECParameters; +import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.jce.spec.ECNamedCurveSpec; +import org.bouncycastle.math.ec.ECPoint; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; + +import static info.FrostFS.sdk.Helper.getRIPEMD160; +import static info.FrostFS.sdk.Helper.getSha256; +import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; + +public class KeyExtension { + public static final byte NEO_ADDRESS_VERSION = 0x35; + private static final int COMPRESSED_PUBLIC_KEY_LENGTH = 33; + private static final int UNCOMPRESSED_PUBLIC_KEY_LENGTH = 65; + + private static final int CHECK_SIG_DESCRIPTOR = ByteBuffer + .wrap(getSha256("System.Crypto.CheckSig".getBytes(StandardCharsets.US_ASCII))) + .order(ByteOrder.LITTLE_ENDIAN).getInt(); + + + public static byte[] compress(byte[] publicKey) { + if (publicKey.length != UNCOMPRESSED_PUBLIC_KEY_LENGTH) { + throw new IllegalArgumentException( + String.format("Compress argument isn't uncompressed public key. Expected length=%s, actual=%s", + UNCOMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length) + ); + } + + var secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); + var point = secp256R1.getCurve().decodePoint(publicKey); + return point.getEncoded(true); + } + + public static byte[] getPrivateKeyFromWIF(String wif) { + var data = Base58.base58CheckDecode(wif); + return Arrays.copyOfRange(data, 1, data.length - 1); + } + + public static byte[] loadPublicKey(byte[] privateKey) { + X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); + ECDomainParameters domain = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + ECPoint q = domain.getG().multiply(new BigInteger(1, privateKey)); + ECPublicKeyParameters publicParams = new ECPublicKeyParameters(q, domain); + return publicParams.getQ().getEncoded(true); + } + + public static PrivateKey loadPrivateKey(byte[] privateKey) { + X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); + ECDomainParameters domain = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + ECPrivateKeyParameters ecParams = new ECPrivateKeyParameters(fromUnsignedByteArray(privateKey), domain); + + ECParameterSpec ecParameterSpec = new ECNamedCurveSpec( + "secp256r1", params.getCurve(), params.getG(), params.getN(), params.getH() + ); + ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(ecParams.getD(), ecParameterSpec); + try { + KeyFactory kf = KeyFactory.getInstance("EC"); + return kf.generatePrivate(privateKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new RuntimeException(e); + } + } + + public static PublicKey getPublicKeyByPublic(byte[] publicKey) { + if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { + throw new IllegalArgumentException( + String.format("Decompress argument isn't compressed public key. Expected length=%s, actual=%s", + COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length) + ); + } + + X9ECParameters secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); + ECDomainParameters domain = new ECDomainParameters(secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH()); + var ecPoint = secp256R1.getCurve().decodePoint(publicKey); + var publicParams = new ECPublicKeyParameters(ecPoint, domain); + java.security.spec.ECPoint point = new java.security.spec.ECPoint( + publicParams.getQ().getRawXCoord().toBigInteger(), publicParams.getQ().getRawYCoord().toBigInteger() + ); + ECParameterSpec ecParameterSpec = new ECNamedCurveSpec( + "secp256r1", secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH(), secp256R1.getSeed() + ); + ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(point, ecParameterSpec); + + try { + KeyFactory kf = KeyFactory.getInstance("EC"); + return kf.generatePublic(publicKeySpec); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + public static byte[] getScriptHash(byte[] publicKey) { + var script = createSignatureRedeemScript(publicKey); + + return getRIPEMD160(getSha256(script)); + } + + public static String publicKeyToAddress(byte[] publicKey) { + if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { + throw new IllegalArgumentException( + String.format("PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s", + COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length) + ); + } + + return toAddress(getScriptHash(publicKey), NEO_ADDRESS_VERSION); + } + + private static String toAddress(byte[] scriptHash, byte version) { + byte[] data = new byte[21]; + data[0] = version; + System.arraycopy(scriptHash, 0, data, 1, scriptHash.length); + return Base58.base58CheckEncode(data); + } + + private static byte[] getBytes(int value) { + byte[] buffer = new byte[4]; + + for (int i = 0; i < buffer.length; i++) { + buffer[i] = (byte) (value >> i * 8); + } + + return buffer; + } + + private static byte[] createSignatureRedeemScript(byte[] publicKey) { + if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { + throw new IllegalArgumentException( + String.format("PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s", + COMPRESSED_PUBLIC_KEY_LENGTH, publicKey.length) + ); + } + + var script = new byte[]{0x0c, COMPRESSED_PUBLIC_KEY_LENGTH}; //PUSHDATA1 33 + + script = ArrayHelper.concat(script, publicKey); + script = ArrayHelper.concat(script, new byte[]{0x41}); //SYSCALL + script = ArrayHelper.concat(script, getBytes(CHECK_SIG_DESCRIPTOR)); //Neo_Crypto_CheckSig + return script; + } +} diff --git a/modelsV2/pom.xml b/modelsV2/pom.xml new file mode 100644 index 0000000..9093e71 --- /dev/null +++ b/modelsV2/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + info.FrostFS.sdk + FrostFS-sdk-java + 0.1.0 + + + modelsV2 + + + 11 + 11 + UTF-8 + + + + + org.apache.commons + commons-lang3 + 3.14.0 + + + info.FrostFS.sdk + cryptography + 0.1.0 + + + info.FrostFS.sdk + protosV2 + 0.1.0 + + + + \ No newline at end of file diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/UUIDExtension.java b/modelsV2/src/main/java/info/FrostFS/sdk/UUIDExtension.java new file mode 100644 index 0000000..df146ec --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/UUIDExtension.java @@ -0,0 +1,21 @@ +package info.FrostFS.sdk; + +import java.nio.ByteBuffer; +import java.util.UUID; + +public class UUIDExtension { + + public static UUID asUuid(byte[] bytes) { + ByteBuffer bb = ByteBuffer.wrap(bytes); + long firstLong = bb.getLong(); + long secondLong = bb.getLong(); + return new UUID(firstLong, secondLong); + } + + public static byte[] asBytes(UUID id) { + ByteBuffer bb = ByteBuffer.allocate(16); + bb.putLong(id.getMostSignificantBits()); + bb.putLong(id.getLeastSignificantBits()); + return bb.array(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java b/modelsV2/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java new file mode 100644 index 0000000..8c435e7 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java @@ -0,0 +1,7 @@ +package info.FrostFS.sdk.constants; + +public class XHeaderConst { + public static final String RESERVED_XHEADER_PREFIX = "__SYSTEM__"; + public static final String XHEADER_NETMAP_EPOCH = RESERVED_XHEADER_PREFIX + "NETMAP_EPOCH"; + public static final String XHEADER_NETMAP_LOOKUP_DEPTH = RESERVED_XHEADER_PREFIX + "NETMAP_LOOKUP_DEPTH"; +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java b/modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java new file mode 100644 index 0000000..b454a68 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java @@ -0,0 +1,33 @@ +package info.FrostFS.sdk.enums; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum BasicAcl { + PRIVATE(0x1C8C8CCC), + PUBLIC_RO(0x1FBF8CFF), + PUBLIC_RW(0x1FBFBFFF), + PUBLIC_APPEND(0x1FBF9FFF), + ; + + private static final Map ENUM_MAP_BY_VALUE; + + static { + Map map = new HashMap<>(); + for (BasicAcl basicAcl : BasicAcl.values()) { + map.put(basicAcl.value, basicAcl); + } + ENUM_MAP_BY_VALUE = Collections.unmodifiableMap(map); + } + + public final int value; + + BasicAcl(int value) { + this.value = value; + } + + public static BasicAcl get(int value) { + return ENUM_MAP_BY_VALUE.get(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/NodeState.java b/modelsV2/src/main/java/info/FrostFS/sdk/enums/NodeState.java new file mode 100644 index 0000000..e6f1464 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/enums/NodeState.java @@ -0,0 +1,33 @@ +package info.FrostFS.sdk.enums; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum NodeState { + UNSPECIFIED(0), + ONLINE(1), + OFFLINE(2), + MAINTENANCE(3), + ; + + private static final Map ENUM_MAP_BY_VALUE; + + static { + Map map = new HashMap<>(); + for (NodeState nodeState : NodeState.values()) { + map.put(nodeState.value, nodeState); + } + ENUM_MAP_BY_VALUE = Collections.unmodifiableMap(map); + } + + public final int value; + + NodeState(int value) { + this.value = value; + } + + public static NodeState get(int value) { + return ENUM_MAP_BY_VALUE.get(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java b/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java new file mode 100644 index 0000000..385756f --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java @@ -0,0 +1,16 @@ +package info.FrostFS.sdk.enums; + +public enum ObjectMatchType { + UNSPECIFIED(0), + EQUALS(1), + NOT_EQUALS(2), + KEY_ABSENT(3), + STARTS_WITH(4), + ; + + public final int value; + + ObjectMatchType(int value) { + this.value = value; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectType.java b/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectType.java new file mode 100644 index 0000000..feb545f --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectType.java @@ -0,0 +1,32 @@ +package info.FrostFS.sdk.enums; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum ObjectType { + REGULAR(0), + TOMBSTONE(1), + LOCK(3), + ; + + private static final Map ENUM_MAP_BY_VALUE; + + static { + Map map = new HashMap<>(); + for (ObjectType objectType : ObjectType.values()) { + map.put(objectType.value, objectType); + } + ENUM_MAP_BY_VALUE = Collections.unmodifiableMap(map); + } + + public final int value; + + ObjectType(int value) { + this.value = value; + } + + public static ObjectType get(int value) { + return ENUM_MAP_BY_VALUE.get(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/StatusCode.java b/modelsV2/src/main/java/info/FrostFS/sdk/enums/StatusCode.java new file mode 100644 index 0000000..4e44421 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/enums/StatusCode.java @@ -0,0 +1,46 @@ +package info.FrostFS.sdk.enums; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public enum StatusCode { + SUCCESS(0), + INTERNAL(1024), + WRONG_MAGIC_NUMBER(1025), + SIGNATURE_VERIFICATION_FAILURE(1026), + NODE_UNDER_MAINTENANCE(1027), + OBJECT_ACCESS_DENIED(2048), + OBJECT_NOT_FOUND(2049), + OBJECT_LOCKED(2050), + LOCK_NOT_REGULAR_OBJECT(2051), + OBJECT_ALREADY_REMOVED(2052), + OUT_OF_RANGE(2053), + CONTAINER_NOT_FOUND(3072), + E_ACL_NOT_FOUND(3073), + CONTAINER_ACCESS_DENIED(3074), + TOKEN_NOT_FOUND(4096), + TOKEN_EXPIRED(4097), + APE_MANAGER_ACCESS_DENIED(5120), + ; + + private static final Map ENUM_MAP_BY_VALUE; + + static { + Map map = new HashMap<>(); + for (StatusCode statusCode : StatusCode.values()) { + map.put(statusCode.value, statusCode); + } + ENUM_MAP_BY_VALUE = Collections.unmodifiableMap(map); + } + + public final int value; + + StatusCode(int value) { + this.value = value; + } + + public static StatusCode get(int value) { + return ENUM_MAP_BY_VALUE.get(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java new file mode 100644 index 0000000..2c01d9e --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java @@ -0,0 +1,6 @@ +package info.FrostFS.sdk.jdo; + +public class Constants { + public static final int OBJECT_CHUNK_SIZE = 3 * (1 << 20); + public static final int SHA256_HASH_LENGTH = 32; +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java new file mode 100644 index 0000000..38df197 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java @@ -0,0 +1,58 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.enums.BasicAcl; +import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; + +import java.util.UUID; + +public class Container { + public UUID nonce; + public BasicAcl basicAcl; + public PlacementPolicy placementPolicy; + public Version version; + + public UUID getNonce() { + return nonce; + } + + public void setNonce(UUID nonce) { + this.nonce = nonce; + } + + public BasicAcl getBasicAcl() { + return basicAcl; + } + + public void setBasicAcl(BasicAcl basicAcl) { + this.basicAcl = basicAcl; + } + + public PlacementPolicy getPlacementPolicy() { + return placementPolicy; + } + + public void setPlacementPolicy(PlacementPolicy placementPolicy) { + this.placementPolicy = placementPolicy; + } + + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } + + public Container(BasicAcl basicAcl, PlacementPolicy placementPolicy) { + nonce = UUID.randomUUID(); + this.basicAcl = basicAcl; + this.placementPolicy = placementPolicy; + } + + public Container(BasicAcl basicAcl, PlacementPolicy placementPolicy, UUID nonce, Version version) { + this.nonce = nonce; + this.basicAcl = basicAcl; + this.placementPolicy = placementPolicy; + this.version = version; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java new file mode 100644 index 0000000..309f25b --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java @@ -0,0 +1,35 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.Base58; + +public class ContainerId { + public String value; + + public ContainerId(String value) { + this.value = value; + } + + public static ContainerId fromHash(byte[] hash) { + if (hash.length != Constants.SHA256_HASH_LENGTH) { + throw new IllegalArgumentException("ContainerID must be a sha256 hash."); + } + return new ContainerId(Base58.encode(hash)); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + + public byte[] toHash() { + return Base58.decode(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java new file mode 100644 index 0000000..5f428b4 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java @@ -0,0 +1,41 @@ +package info.FrostFS.sdk.jdo; + +public class MetaHeader { + public Version version; + public int epoch; + public int ttl; + + public MetaHeader(Version version, int epoch, int ttl) { + this.version = version; + this.epoch = epoch; + this.ttl = ttl; + } + + public static MetaHeader getDefault() { + return new MetaHeader(new Version(2, 13), 0, 2); + } + + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } + + public int getEpoch() { + return epoch; + } + + public void setEpoch(int epoch) { + this.epoch = epoch; + } + + public int getTtl() { + return ttl; + } + + public void setTtl(int ttl) { + this.ttl = ttl; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java new file mode 100644 index 0000000..1a122f4 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java @@ -0,0 +1,27 @@ +package info.FrostFS.sdk.jdo; + +public class ObjectAttribute { + public String key; + public String value; + + public ObjectAttribute(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java new file mode 100644 index 0000000..0fb1db3 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java @@ -0,0 +1,58 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.enums.ObjectMatchType; + +public class ObjectFilter { + private static final String HEADER_PREFIX = "Object:"; + + public ObjectMatchType matchType; + public String key; + public String value; + + + public ObjectFilter(ObjectMatchType matchType, String key, String value) { + this.matchType = matchType; + this.key = key; + this.value = value; + } + + public static ObjectFilter ObjectIdFilter(ObjectMatchType matchType, ObjectId objectId) { + return new ObjectFilter(matchType, HEADER_PREFIX + "objectID", objectId.value); + } + + public static ObjectFilter OwnerFilter(ObjectMatchType matchType, OwnerId ownerId) { + return new ObjectFilter(matchType, HEADER_PREFIX + "ownerID", ownerId.getValue()); + } + + public static ObjectFilter RootFilter() { + return new ObjectFilter(ObjectMatchType.UNSPECIFIED, HEADER_PREFIX + "ROOT", ""); + } + + public static ObjectFilter VersionFilter(ObjectMatchType matchType, Version version) { + return new ObjectFilter(matchType, HEADER_PREFIX + "version", version.toString()); + } + + public ObjectMatchType getMatchType() { + return matchType; + } + + public void setMatchType(ObjectMatchType matchType) { + this.matchType = matchType; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java new file mode 100644 index 0000000..c7cc689 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java @@ -0,0 +1,37 @@ +package info.FrostFS.sdk.jdo; + +public class ObjectFrostFs { + public ObjectHeader header; + public ObjectId objectId; + public byte[] payload; + + public ObjectFrostFs(ObjectHeader header, ObjectId objectId, byte[] payload) { + this.header = header; + this.objectId = objectId; + this.payload = payload; + } + + public ObjectHeader getHeader() { + return header; + } + + public void setHeader(ObjectHeader header) { + this.header = header; + } + + public ObjectId getObjectId() { + return objectId; + } + + public void setObjectId(ObjectId objectId) { + this.objectId = objectId; + } + + public byte[] getPayload() { + return payload; + } + + public void setPayload(byte[] payload) { + this.payload = payload; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java new file mode 100644 index 0000000..7dc795c --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java @@ -0,0 +1,71 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.enums.ObjectType; + +public class ObjectHeader { + public ObjectAttribute[] attributes; + public ContainerId containerId; + public long size; + public ObjectType objectType; + public Version version; + + public ObjectHeader(ContainerId containerId, ObjectType objectType, ObjectAttribute[] attributes, long size, Version version) { + this.attributes = attributes; + this.containerId = containerId; + this.size = size; + this.objectType = objectType; + this.version = version; + } + + public ObjectHeader(ContainerId containerId, ObjectType type, ObjectAttribute[] attributes) { + this.attributes = attributes; + this.containerId = containerId; + this.objectType = type; + } + + public ObjectHeader(ContainerId containerId, ObjectAttribute[] attributes) { + this.attributes = attributes; + this.containerId = containerId; + this.objectType = ObjectType.REGULAR; + } + + public ObjectAttribute[] getAttributes() { + return attributes; + } + + public void setAttributes(ObjectAttribute[] attributes) { + this.attributes = attributes; + } + + public ContainerId getContainerId() { + return containerId; + } + + public void setContainerId(ContainerId containerId) { + this.containerId = containerId; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public ObjectType getObjectType() { + return objectType; + } + + public void setObjectType(ObjectType objectType) { + this.objectType = objectType; + } + + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java new file mode 100644 index 0000000..438d027 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java @@ -0,0 +1,31 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.Base58; + +public class ObjectId { + public String value; + + public ObjectId(String id) { + this.value = id; + } + + public static ObjectId fromHash(byte[] hash) { + if (hash.length != Constants.SHA256_HASH_LENGTH) { + throw new IllegalArgumentException("ObjectId must be a sha256 hash."); + } + return new ObjectId(Base58.encode(hash)); + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return value; + } + + public byte[] toHash() { + return Base58.decode(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java new file mode 100644 index 0000000..723e234 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java @@ -0,0 +1,25 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.Base58; + +import static info.FrostFS.sdk.KeyExtension.publicKeyToAddress; + +public class OwnerId { + private final String value; + + public OwnerId(String value) { + this.value = value; + } + + public static OwnerId fromKey(byte[] publicKey) { + return new OwnerId(publicKeyToAddress(publicKey)); + } + + public String getValue() { + return value; + } + + public byte[] toHash() { + return Base58.decode(value); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java new file mode 100644 index 0000000..bcb6f08 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java @@ -0,0 +1,45 @@ +package info.FrostFS.sdk.jdo; + +import info.FrostFS.sdk.enums.StatusCode; + +import java.util.Optional; + +public class Status { + public StatusCode code; + public String message; + + public Status(StatusCode code, String message) { + this.code = code; + this.message = Optional.ofNullable(message).orElse(""); + } + + public Status(StatusCode code) { + this.code = code; + this.message = ""; + } + + public StatusCode getCode() { + return code; + } + + public void setCode(StatusCode code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "Response status: " + code + ". Message: " + message + "."; + } + + public boolean isSuccess() { + return StatusCode.SUCCESS.equals(code); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java new file mode 100644 index 0000000..22cd8c7 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java @@ -0,0 +1,36 @@ +package info.FrostFS.sdk.jdo; + +public class Version { + public int major; + public int minor; + + public int getMajor() { + return major; + } + + public void setMajor(int major) { + this.major = major; + } + + public int getMinor() { + return minor; + } + + public void setMinor(int minor) { + this.minor = minor; + } + + @Override + public String toString() { + return "v" + major + "." + minor; + } + + public Version(int major, int minor) { + this.major = major; + this.minor = minor; + } + + public boolean isSupported(Version version) { + return major == version.getMajor(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java new file mode 100644 index 0000000..fe65459 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java @@ -0,0 +1,30 @@ +package info.FrostFS.sdk.jdo.netmap; + +import info.FrostFS.sdk.jdo.Version; +import info.FrostFS.sdk.enums.NodeState; + +public class NodeInfo { + public NodeState state; + public Version version; + + public NodeState getState() { + return state; + } + + public void setState(NodeState state) { + this.state = state; + } + + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } + + public NodeInfo(NodeState state, Version version) { + this.state = state; + this.version = version; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java new file mode 100644 index 0000000..d32b585 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java @@ -0,0 +1,27 @@ +package info.FrostFS.sdk.jdo.netmap; + +public class PlacementPolicy { + public Replica[] replicas; + public boolean unique; + + public PlacementPolicy(boolean unique, Replica[] replicas) { + this.replicas = replicas; + this.unique = unique; + } + + public Replica[] getReplicas() { + return replicas; + } + + public void setReplicas(Replica[] replicas) { + this.replicas = replicas; + } + + public boolean isUnique() { + return unique; + } + + public void setUnique(boolean unique) { + this.unique = unique; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java new file mode 100644 index 0000000..80d1e89 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java @@ -0,0 +1,34 @@ +package info.FrostFS.sdk.jdo.netmap; + +import java.util.Optional; + +public class Replica { + public int count; + public String selector; + + public Replica(int count, String selector) { + this.count = count; + this.selector = Optional.ofNullable(selector).orElse(""); + } + + public Replica(int count) { + this.count = count; + this.selector = ""; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public String getSelector() { + return selector; + } + + public void setSelector(String selector) { + this.selector = selector; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java new file mode 100644 index 0000000..bab5b61 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java @@ -0,0 +1,16 @@ +package info.FrostFS.sdk.mappers; + +import com.google.protobuf.ByteString; +import frostFS.refs.Types; +import info.FrostFS.sdk.jdo.ContainerId; + +public class ContainerIdMapper { + + public static Types.ContainerID toGrpcMessage(ContainerId containerId) { + var test = containerId.toHash(); + + return Types.ContainerID.newBuilder() + .setValue(ByteString.copyFrom(containerId.toHash())) + .build(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java new file mode 100644 index 0000000..4f1d886 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java @@ -0,0 +1,39 @@ +package info.FrostFS.sdk.mappers; + + +import com.google.protobuf.ByteString; +import frostFS.container.Types; +import info.FrostFS.sdk.enums.BasicAcl; +import info.FrostFS.sdk.jdo.Container; +import info.FrostFS.sdk.mappers.netmap.PlacementPolicyMapper; + +import static info.FrostFS.sdk.UUIDExtension.asBytes; +import static info.FrostFS.sdk.UUIDExtension.asUuid; +import static java.util.Objects.isNull; + +public class ContainerMapper { + + public static Types.Container toGrpcMessage(Container container) { + return Types.Container.newBuilder() + .setBasicAcl(container.getBasicAcl().value) + .setPlacementPolicy(PlacementPolicyMapper.toGrpcMessage(container.getPlacementPolicy())) + .setNonce(ByteString.copyFrom(asBytes(container.getNonce()))) + .build(); + } + + public static Container toModel(Types.Container container) { + var basicAcl = BasicAcl.get(container.getBasicAcl()); + if (isNull(basicAcl)) { + throw new IllegalArgumentException( + String.format("Unknown BasicACL rule. Value: %s.", container.getBasicAcl()) + ); + } + + return new Container( + basicAcl, + PlacementPolicyMapper.toModel(container.getPlacementPolicy()), + asUuid(container.getNonce().toByteArray()), + VersionMapper.toModel(container.getVersion()) + ); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java new file mode 100644 index 0000000..2d493c4 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java @@ -0,0 +1,15 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.session.Types; +import info.FrostFS.sdk.jdo.MetaHeader; + +public class MetaHeaderMapper { + + public static Types.RequestMetaHeader toGrpcMessage(MetaHeader metaHeader) { + return Types.RequestMetaHeader.newBuilder() + .setVersion(VersionMapper.toGrpcMessage(metaHeader.getVersion())) + .setEpoch(metaHeader.getEpoch()) + .setTtl(metaHeader.getTtl()) + .build(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java new file mode 100644 index 0000000..45489a5 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java @@ -0,0 +1,17 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.object.Types; +import info.FrostFS.sdk.jdo.ObjectAttribute; + +public class ObjectAttributeMapper { + public static Types.Header.Attribute toGrpcMessage(ObjectAttribute attribute) { + return Types.Header.Attribute.newBuilder() + .setKey(attribute.getKey()) + .setValue(attribute.getValue()) + .build(); + } + + public static ObjectAttribute toModel(Types.Header.Attribute attribute) { + return new ObjectAttribute(attribute.getKey(), attribute.getValue()); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java new file mode 100644 index 0000000..328de81 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java @@ -0,0 +1,25 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.object.Service; +import frostFS.object.Types; +import info.FrostFS.sdk.jdo.ObjectFilter; +import org.apache.commons.lang3.EnumUtils; + +import static java.util.Objects.isNull; + +public class ObjectFilterMapper { + public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter filter) { + var objectMatchType = Types.MatchType.forNumber(filter.getMatchType().value); + if (isNull(objectMatchType)) { + throw new IllegalArgumentException( + String.format("Unknown MatchType. Value: %s.", filter.getMatchType().name()) + ); + } + + return Service.SearchRequest.Body.Filter.newBuilder() + .setMatchType(objectMatchType) + .setKey(filter.getKey()) + .setValue(filter.getValue()) + .build(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java new file mode 100644 index 0000000..ba38b14 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java @@ -0,0 +1,48 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.object.Types; +import info.FrostFS.sdk.enums.ObjectType; +import info.FrostFS.sdk.jdo.ContainerId; +import info.FrostFS.sdk.jdo.ObjectAttribute; +import info.FrostFS.sdk.jdo.ObjectHeader; +import org.apache.commons.lang3.EnumUtils; + +import static java.util.Objects.isNull; + +public class ObjectHeaderMapper { + public static Types.Header toGrpcMessage(ObjectHeader header) { + var objectType = EnumUtils.getEnum(Types.ObjectType.class, header.getObjectType().name()); + if (isNull(objectType)) { + throw new IllegalArgumentException( + String.format("Unknown ObjectType. Value: %s.", header.getObjectType().name()) + ); + } + + var head = Types.Header.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(header.getContainerId())) + .setObjectType(objectType); + + for (ObjectAttribute objectAttribute : header.getAttributes()) { + head.addAttributes(ObjectAttributeMapper.toGrpcMessage(objectAttribute)); + } + + return head.build(); + } + + public static ObjectHeader toModel(Types.Header header) { + var objectType = ObjectType.get(header.getObjectTypeValue()); + if (isNull(objectType)) { + throw new IllegalArgumentException( + String.format("Unknown ObjectType. Value: %s.", header.getObjectType()) + ); + } + + return new ObjectHeader( + ContainerId.fromHash(header.getContainerId().getValue().toByteArray()), + objectType, + header.getAttributesList().stream().map(ObjectAttributeMapper::toModel).toArray(ObjectAttribute[]::new), + header.getPayloadLength(), + VersionMapper.toModel(header.getVersion()) + ); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java new file mode 100644 index 0000000..42200e2 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java @@ -0,0 +1,13 @@ +package info.FrostFS.sdk.mappers; + +import com.google.protobuf.ByteString; +import frostFS.refs.Types; +import info.FrostFS.sdk.jdo.ObjectId; + +public class ObjectIdMapper { + public static Types.ObjectID toGrpcMessage(ObjectId objectId) { + return Types.ObjectID.newBuilder() + .setValue(ByteString.copyFrom(objectId.toHash())) + .build(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java new file mode 100644 index 0000000..b970456 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java @@ -0,0 +1,15 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.object.Types; +import info.FrostFS.sdk.jdo.ObjectFrostFs; +import info.FrostFS.sdk.jdo.ObjectId; + +public class ObjectMapper { + public static ObjectFrostFs toModel(Types.Object obj) { + return new ObjectFrostFs( + ObjectHeaderMapper.toModel(obj.getHeader()), + ObjectId.fromHash(obj.getObjectId().getValue().toByteArray()), + obj.getPayload().toByteArray() + ); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java new file mode 100644 index 0000000..bc7027c --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java @@ -0,0 +1,13 @@ +package info.FrostFS.sdk.mappers; + +import com.google.protobuf.ByteString; +import frostFS.refs.Types; +import info.FrostFS.sdk.jdo.OwnerId; + +public class OwnerIdMapper { + public static Types.OwnerID toGrpcMessage(OwnerId ownerId) { + return Types.OwnerID.newBuilder() + .setValue(ByteString.copyFrom(ownerId.toHash())) + .build(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java new file mode 100644 index 0000000..6cb68d7 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java @@ -0,0 +1,23 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.status.Types; +import info.FrostFS.sdk.enums.StatusCode; +import info.FrostFS.sdk.jdo.Status; + +import static java.util.Objects.isNull; + +public class StatusMapper { + public static Status toModel(Types.Status status) { + if (isNull(status)) return new Status(StatusCode.SUCCESS); + + var statusCode = StatusCode.get(status.getCode()); + if (isNull(statusCode)) { + throw new IllegalArgumentException( + String.format("Unknown StatusCode. Value: %s.", status.getCode()) + ); + + } + + return new Status(statusCode, status.getMessage()); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java new file mode 100644 index 0000000..339746a --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java @@ -0,0 +1,18 @@ +package info.FrostFS.sdk.mappers; + +import frostFS.refs.Types; +import info.FrostFS.sdk.jdo.Version; + +public class VersionMapper { + + public static Types.Version toGrpcMessage(Version version) { + return Types.Version.newBuilder() + .setMajor(version.getMajor()) + .setMinor(version.getMinor()) + .build(); + } + + public static Version toModel(Types.Version version) { + return new Version(version.getMajor(), version.getMinor()); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java new file mode 100644 index 0000000..934d60f --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java @@ -0,0 +1,21 @@ +package info.FrostFS.sdk.mappers.netmap; + +import frostFS.netmap.Service; +import info.FrostFS.sdk.enums.NodeState; +import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.mappers.VersionMapper; + +import static java.util.Objects.isNull; + +public class NodeInfoMapper { + public static NodeInfo toModel(Service.LocalNodeInfoResponse.Body nodeInfo) { + var nodeState = NodeState.get(nodeInfo.getNodeInfo().getState().getNumber()); + if (isNull(nodeState)) { + throw new IllegalArgumentException( + String.format("Unknown NodeState. Value: %s.", nodeInfo.getNodeInfo().getState()) + ); + } + + return new NodeInfo(nodeState, VersionMapper.toModel(nodeInfo.getVersion())); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java new file mode 100644 index 0000000..871dfcb --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java @@ -0,0 +1,25 @@ +package info.FrostFS.sdk.mappers.netmap; + +import frostFS.netmap.Types; +import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; +import info.FrostFS.sdk.jdo.netmap.Replica; + +public class PlacementPolicyMapper { + public static Types.PlacementPolicy toGrpcMessage(PlacementPolicy placementPolicy) { + var pp = Types.PlacementPolicy.newBuilder() + .setUnique(placementPolicy.isUnique()); + + for (Replica replica : placementPolicy.getReplicas()) { + pp.addReplicas(ReplicaMapper.toGrpcMessage(replica)); + } + + return pp.build(); + } + + public static PlacementPolicy toModel(Types.PlacementPolicy placementPolicy) { + return new PlacementPolicy( + placementPolicy.getUnique(), + placementPolicy.getReplicasList().stream().map(ReplicaMapper::toModel).toArray(Replica[]::new) + ); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java new file mode 100644 index 0000000..93735ff --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java @@ -0,0 +1,17 @@ +package info.FrostFS.sdk.mappers.netmap; + +import frostFS.netmap.Types; +import info.FrostFS.sdk.jdo.netmap.Replica; + +public class ReplicaMapper { + public static Types.Replica toGrpcMessage(Replica replica) { + return Types.Replica.newBuilder() + .setCount(replica.getCount()) + .setSelector(replica.getSelector()) + .build(); + } + + public static Replica toModel(Types.Replica replica) { + return new Replica(replica.getCount(), replica.getSelector()); + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5c16e71 --- /dev/null +++ b/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + info.FrostFS.sdk + FrostFS-sdk-java + 0.1.0 + pom + + protosV2 + client + cryptography + modelsV2 + + + + 11 + 11 + UTF-8 + + \ No newline at end of file diff --git a/protosV2/pom.xml b/protosV2/pom.xml new file mode 100644 index 0000000..d7d8630 --- /dev/null +++ b/protosV2/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + + info.FrostFS.sdk + FrostFS-sdk-java + 0.1.0 + + + protosV2 + + + 11 + 11 + 3.23.0 + 1.62.2 + UTF-8 + + + + + io.grpc + grpc-netty + ${grpc.version} + + + io.grpc + grpc-protobuf + ${grpc.version} + + + io.grpc + grpc-stub + ${grpc.version} + + + io.grpc + grpc-services + ${grpc.version} + runtime + + + javax.annotation + javax.annotation-api + 1.3.2 + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + + + + + io.grpc + grpc-bom + ${grpc.version} + pom + import + + + + + + + + kr.motd.maven + os-maven-plugin + 1.6.2 + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.6.1 + + + com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier} + + grpc-java + + io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + + + + + + compile + compile-custom + + test-compile + test-compile-custom + + + + + + + + \ No newline at end of file diff --git a/protosV2/src/main/proto/accounting/service.proto b/protosV2/src/main/proto/accounting/service.proto new file mode 100644 index 0000000..c225c58 --- /dev/null +++ b/protosV2/src/main/proto/accounting/service.proto @@ -0,0 +1,71 @@ +syntax = "proto3"; + +package neo.fs.v2.accounting; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc;accounting"; +option java_package = "frostFS.accounting"; + +import "accounting/types.proto"; +import "refs/types.proto"; +import "session/types.proto"; + +// Accounting service provides methods for interaction with NeoFS sidechain via +// other NeoFS nodes to get information about the account balance. Deposit and +// Withdraw operations can't be implemented here, as they require Mainnet NeoFS +// smart contract invocation. Transfer operations between internal NeoFS +// accounts are possible if both use the same token type. +service AccountingService { + // Returns the amount of funds in GAS token for the requested NeoFS account. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // balance has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + rpc Balance(BalanceRequest) returns (BalanceResponse); +} + +// BalanceRequest message +message BalanceRequest { + // To indicate the account for which the balance is requested, its identifier + // is used. It can be any existing account in NeoFS sidechain `Balance` smart + // contract. If omitted, client implementation MUST set it to the request's + // signer `OwnerID`. + message Body { + // Valid user identifier in `OwnerID` format for which the balance is + // requested. Required field. + neo.fs.v2.refs.OwnerID owner_id = 1; + } + // Body of the balance request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// BalanceResponse message +message BalanceResponse { + // The amount of funds in GAS token for the `OwnerID`'s account requested. + // Balance is given in the `Decimal` format to avoid precision issues with + // rounding. + message Body { + // Amount of funds in GAS token for the requested account. + Decimal balance = 1; + } + // Body of the balance response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} diff --git a/protosV2/src/main/proto/accounting/types.proto b/protosV2/src/main/proto/accounting/types.proto new file mode 100644 index 0000000..57229d9 --- /dev/null +++ b/protosV2/src/main/proto/accounting/types.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package neo.fs.v2.accounting; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc;accounting"; +option java_package = "frostFS.accounting"; + +// Standard floating point data type can't be used in NeoFS due to inexactness +// of the result when doing lots of small number operations. To solve the lost +// precision issue, special `Decimal` format is used for monetary computations. +// +// Please see [The General Decimal Arithmetic +// Specification](http://speleotrove.com/decimal/) for detailed problem +// description. +message Decimal { + // Number in the smallest Token fractions. + int64 value = 1 [ json_name = "value" ]; + + // Precision value indicating how many smallest fractions can be in one + // integer. + uint32 precision = 2 [ json_name = "precision" ]; +} diff --git a/protosV2/src/main/proto/acl/types.proto b/protosV2/src/main/proto/acl/types.proto new file mode 100644 index 0000000..86a9311 --- /dev/null +++ b/protosV2/src/main/proto/acl/types.proto @@ -0,0 +1,227 @@ +syntax = "proto3"; + +package neo.fs.v2.acl; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc;acl"; +option java_package = "frostFS.acl"; + +import "refs/types.proto"; + +// Target role of the access control rule in access control list. +enum Role { + // Unspecified role, default value + ROLE_UNSPECIFIED = 0; + + // User target rule is applied if sender is the owner of the container + USER = 1; + + // System target rule is applied if sender is a storage node within the + // container or an inner ring node + SYSTEM = 2; + + // Others target rule is applied if sender is neither a user nor a system + // target + OTHERS = 3; +} + +// MatchType is an enumeration of match types. +enum MatchType { + // Unspecified match type, default value. + MATCH_TYPE_UNSPECIFIED = 0; + + // Return true if strings are equal + STRING_EQUAL = 1; + + // Return true if strings are different + STRING_NOT_EQUAL = 2; +} + +// Request's operation type to match if the rule is applicable to a particular +// request. +enum Operation { + // Unspecified operation, default value + OPERATION_UNSPECIFIED = 0; + + // Get + GET = 1; + + // Head + HEAD = 2; + + // Put + PUT = 3; + + // Delete + DELETE = 4; + + // Search + SEARCH = 5; + + // GetRange + GETRANGE = 6; + + // GetRangeHash + GETRANGEHASH = 7; +} + +// Rule execution result action. Either allows or denies access if the rule's +// filters match. +enum Action { + // Unspecified action, default value + ACTION_UNSPECIFIED = 0; + + // Allow action + ALLOW = 1; + + // Deny action + DENY = 2; +} + +// Enumeration of possible sources of Headers to apply filters. +enum HeaderType { + // Unspecified header, default value. + HEADER_UNSPECIFIED = 0; + + // Filter request headers + REQUEST = 1; + + // Filter object headers + OBJECT = 2; + + // Filter service headers. These are not processed by NeoFS nodes and + // exist for service use only. + SERVICE = 3; +} + +// Describes a single eACL rule. +message EACLRecord { + // NeoFS request Verb to match + Operation operation = 1 [ json_name = "operation" ]; + + // Rule execution result. Either allows or denies access if filters match. + Action action = 2 [ json_name = "action" ]; + + // Filter to check particular properties of the request or the object. + // + // By default `key` field refers to the corresponding object's `Attribute`. + // Some Object's header fields can also be accessed by adding `$Object:` + // prefix to the name. Here is the list of fields available via this prefix: + // + // * $Object:version \ + // version + // * $Object:objectID \ + // object_id + // * $Object:containerID \ + // container_id + // * $Object:ownerID \ + // owner_id + // * $Object:creationEpoch \ + // creation_epoch + // * $Object:payloadLength \ + // payload_length + // * $Object:payloadHash \ + // payload_hash + // * $Object:objectType \ + // object_type + // * $Object:homomorphicHash \ + // homomorphic_hash + // + // Please note, that if request or response does not have object's headers of + // full object (Range, RangeHash, Search, Delete), it will not be possible to + // filter by object header fields or user attributes. From the well-known list + // only `$Object:objectID` and `$Object:containerID` will be available, as + // it's possible to take that information from the requested address. + message Filter { + // Define if Object or Request header will be used + HeaderType header_type = 1 [ json_name = "headerType" ]; + + // Match operation type + MatchType match_type = 2 [ json_name = "matchType" ]; + + // Name of the Header to use + string key = 3 [ json_name = "key" ]; + + // Expected Header Value or pattern to match + string value = 4 [ json_name = "value" ]; + } + + // List of filters to match and see if rule is applicable + repeated Filter filters = 3 [ json_name = "filters" ]; + + // Target to apply ACL rule. Can be a subject's role class or a list of public + // keys to match. + message Target { + // Target subject's role class + Role role = 1 [ json_name = "role" ]; + + // List of public keys to identify target subject + repeated bytes keys = 2 [ json_name = "keys" ]; + } + // List of target subjects to apply ACL rule to + repeated Target targets = 4 [ json_name = "targets" ]; +} + +// Extended ACL rules table. A list of ACL rules defined additionally to Basic +// ACL. Extended ACL rules can be attached to a container and can be updated +// or may be defined in `BearerToken` structure. Please see the corresponding +// NeoFS Technical Specification section for detailed description. +message EACLTable { + // eACL format version. Effectively, the version of API library used to create + // eACL Table. + neo.fs.v2.refs.Version version = 1 [ json_name = "version" ]; + + // Identifier of the container that should use given access control rules + neo.fs.v2.refs.ContainerID container_id = 2 [ json_name = "containerID" ]; + + // List of Extended ACL rules + repeated EACLRecord records = 3 [ json_name = "records" ]; +} + +// BearerToken allows to attach signed Extended ACL rules to the request in +// `RequestMetaHeader`. If container's Basic ACL rules allow, the attached rule +// set will be checked instead of one attached to the container itself. Just +// like [JWT](https://jwt.io), it has a limited lifetime and scope, hence can be +// used in the similar use cases, like providing authorisation to externally +// authenticated party. +// +// BearerToken can be issued only by the container's owner and must be signed +// using the key associated with the container's `OwnerID`. +message BearerToken { + // Bearer Token body structure contains Extended ACL table issued by the + // container owner with additional information preventing token abuse. + message Body { + // Table of Extended ACL rules to use instead of the ones attached to the + // container. If it contains `container_id` field, bearer token is only + // valid for this specific container. Otherwise, any container of the same + // owner is allowed. + EACLTable eacl_table = 1 [ json_name = "eaclTable" ]; + + // `OwnerID` defines to whom the token was issued. It must match the request + // originator's `OwnerID`. If empty, any token bearer will be accepted. + neo.fs.v2.refs.OwnerID owner_id = 2 [ json_name = "ownerID" ]; + + // Lifetime parameters of the token. Field names taken from + // [rfc7519](https://tools.ietf.org/html/rfc7519). + message TokenLifetime { + // Expiration Epoch + uint64 exp = 1 [ json_name = "exp" ]; + + // Not valid before Epoch + uint64 nbf = 2 [ json_name = "nbf" ]; + + // Issued at Epoch + uint64 iat = 3 [ json_name = "iat" ]; + } + // Token expiration and valid time period parameters + TokenLifetime lifetime = 3 [ json_name = "lifetime" ]; + + // AllowImpersonate flag to consider token signer as request owner. + // If this field is true extended ACL table in token body isn't processed. + bool allow_impersonate = 4 [ json_name = "allowImpersonate" ]; + } + // Bearer Token body + Body body = 1 [ json_name = "body" ]; + + // Signature of BearerToken body + neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ]; +} diff --git a/protosV2/src/main/proto/apemanager/service.proto b/protosV2/src/main/proto/apemanager/service.proto new file mode 100644 index 0000000..da0da48 --- /dev/null +++ b/protosV2/src/main/proto/apemanager/service.proto @@ -0,0 +1,172 @@ +syntax = "proto3"; + +package frostfs.v2.apemanager; + +import "apemanager/types.proto"; +import "session/types.proto"; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc;apemanager"; +option java_package = "frostFS.apemanager"; + +// `APEManagerService` provides API to manage rule chains within sidechain's +// `Policy` smart contract. +service APEManagerService { + // Add a rule chain for a specific target to `Policy` smart contract. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // the chain has been successfully added; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. + rpc AddChain(AddChainRequest) returns (AddChainResponse); + + // Remove a rule chain for a specific target from `Policy` smart contract. + // RemoveChain is an idempotent operation: removal of non-existing rule chain + // also means success. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // the chain has been successfully removed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. + rpc RemoveChain(RemoveChainRequest) returns (RemoveChainResponse); + + // List chains defined for a specific target from `Policy` smart contract. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // chains have been successfully listed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container (as target) not found; + // - **APE_MANAGER_ACCESS_DENIED** (5120, SECTION_APE_MANAGER): \ + // the operation is denied by the service. + rpc ListChains(ListChainsRequest) returns (ListChainsResponse); +} + +message AddChainRequest { + message Body { + // A target for which a rule chain is added. + ChainTarget target = 1; + + // The chain to set for the target. + Chain chain = 2; + } + + // The request's body. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +message AddChainResponse { + message Body { + // Chain ID assigned for the added rule chain. + // If chain ID is left empty in the request, then + // it will be generated. + bytes chain_id = 1; + } + + // The response's body. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +message RemoveChainRequest { + message Body { + // Target for which a rule chain is removed. + ChainTarget target = 1; + + // Chain ID assigned for the rule chain. + bytes chain_id = 2; + } + + // The request's body. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +message RemoveChainResponse { + // Since RemoveChain is an idempotent operation, then the only indicator that + // operation could not be performed is an error returning to a client. + message Body {} + + // The response's body. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +message ListChainsRequest { + message Body { + // Target for which rule chains are listed. + ChainTarget target = 1; + } + + // The request's body. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +message ListChainsResponse { + message Body { + // The list of chains defined for the reqeusted target. + repeated Chain chains = 1; + } + + // The response's body. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} \ No newline at end of file diff --git a/protosV2/src/main/proto/apemanager/types.proto b/protosV2/src/main/proto/apemanager/types.proto new file mode 100644 index 0000000..644a8b5 --- /dev/null +++ b/protosV2/src/main/proto/apemanager/types.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +package frostfs.v2.apemanager; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc;apemanager"; +option java_package = "frostFS.apemanager"; + +// TargetType is a type target to which a rule chain is defined. +enum TargetType { + UNDEFINED = 0; + + NAMESPACE = 1; + + CONTAINER = 2; + + USER = 3; + + GROUP = 4; +} + +// ChainTarget is an object to which a rule chain is defined. +message ChainTarget { + TargetType type = 1; + + string name = 2; +} + +// Chain is a chain of rules defined for a specific target. +message Chain { + oneof kind { + // Raw representation of a serizalized rule chain. + bytes raw = 1; + } +} diff --git a/protosV2/src/main/proto/container/service.proto b/protosV2/src/main/proto/container/service.proto new file mode 100644 index 0000000..ce7634a --- /dev/null +++ b/protosV2/src/main/proto/container/service.proto @@ -0,0 +1,431 @@ +syntax = "proto3"; + +package neo.fs.v2.container; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc;container"; +option java_package = "frostFS.container"; + +import "acl/types.proto"; +import "container/types.proto"; +import "refs/types.proto"; +import "session/types.proto"; + +// `ContainerService` provides API to interact with `Container` smart contract +// in NeoFS sidechain via other NeoFS nodes. All of those actions can be done +// equivalently by directly issuing transactions and RPC calls to sidechain +// nodes. +service ContainerService { + // `Put` invokes `Container` smart contract's `Put` method and returns + // response immediately. After a new block is issued in sidechain, request is + // verified by Inner Ring nodes. After one more block in sidechain, the + // container is added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to save the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container create access denied. + rpc Put(PutRequest) returns (PutResponse); + + // `Delete` invokes `Container` smart contract's `Delete` method and returns + // response immediately. After a new block is issued in sidechain, request is + // verified by Inner Ring nodes. After one more block in sidechain, the + // container is added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to remove the container has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container delete access denied. + rpc Delete(DeleteRequest) returns (DeleteResponse); + + // Returns container structure from `Container` smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // requested container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied. + rpc Get(GetRequest) returns (GetResponse); + + // Returns all owner's containers from 'Container` smart contract' storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container list has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // container list access denied. + rpc List(ListRequest) returns (ListResponse); + + // Invokes 'SetEACL' method of 'Container` smart contract and returns response + // immediately. After one more block in sidechain, changes in an Extended ACL + // are added into smart contract storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // request to save container eACL has been sent to the sidechain; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // set container eACL access denied. + rpc SetExtendedACL(SetExtendedACLRequest) returns (SetExtendedACLResponse); + + // Returns Extended ACL table and signature from `Container` smart contract + // storage. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // container eACL has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // container not found; + // - **EACL_NOT_FOUND** (3073, SECTION_CONTAINER): \ + // eACL table not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container eACL is denied. + rpc GetExtendedACL(GetExtendedACLRequest) returns (GetExtendedACLResponse); + + // Announces the space values used by the container for P2P synchronization. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // estimation of used space has been successfully announced; + // - Common failures (SECTION_FAILURE_COMMON). + rpc AnnounceUsedSpace(AnnounceUsedSpaceRequest) + returns (AnnounceUsedSpaceResponse); +} + +// New NeoFS Container creation request +message PutRequest { + // Container creation request has container structure's signature as a + // separate field. It's not stored in sidechain, just verified on container + // creation by `Container` smart contract. `ContainerID` is a SHA256 hash of + // the stable-marshalled container strucutre, hence there is no need for + // additional signature checks. + message Body { + // Container structure to register in NeoFS + container.Container container = 1; + + // Signature of a stable-marshalled container according to RFC-6979. + neo.fs.v2.refs.SignatureRFC6979 signature = 2; + } + // Body of container put request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// New NeoFS Container creation response +message PutResponse { + // Container put response body contains information about the newly registered + // container as seen by `Container` smart contract. `ContainerID` can be + // calculated beforehand from the container structure and compared to the one + // returned here to make sure everything has been done as expected. + message Body { + // Unique identifier of the newly created container + neo.fs.v2.refs.ContainerID container_id = 1; + } + // Body of container put response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Container removal request +message DeleteRequest { + // Container removal request body has signed `ContainerID` as a proof of + // the container owner's intent. The signature will be verified by `Container` + // smart contract, so signing algorithm must be supported by NeoVM. + message Body { + // Identifier of the container to delete from NeoFS + neo.fs.v2.refs.ContainerID container_id = 1; + + // `ContainerID` signed with the container owner's key according to + // RFC-6979. + neo.fs.v2.refs.SignatureRFC6979 signature = 2; + } + // Body of container delete request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// `DeleteResponse` has an empty body because delete operation is asynchronous +// and done via consensus in Inner Ring nodes. +message DeleteResponse { + // `DeleteResponse` has an empty body because delete operation is asynchronous + // and done via consensus in Inner Ring nodes. + message Body {} + // Body of container delete response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Get container structure +message GetRequest { + // Get container structure request body. + message Body { + // Identifier of the container to get + neo.fs.v2.refs.ContainerID container_id = 1; + } + // Body of container get request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Get container structure +message GetResponse { + // Get container response body does not have container structure signature. It + // has been already verified upon container creation. + message Body { + // Requested container structure + Container container = 1; + + // Signature of a stable-marshalled container according to RFC-6979. + neo.fs.v2.refs.SignatureRFC6979 signature = 2; + + // Session token if the container has been created within the session + neo.fs.v2.session.SessionToken session_token = 3; + } + // Body of container get response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// List containers +message ListRequest { + // List containers request body. + message Body { + // Identifier of the container owner + neo.fs.v2.refs.OwnerID owner_id = 1; + } + // Body of list containers request message + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// List containers +message ListResponse { + // List containers response body. + message Body { + // List of `ContainerID`s belonging to the requested `OwnerID` + repeated refs.ContainerID container_ids = 1; + } + + // Body of list containers response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Set Extended ACL +message SetExtendedACLRequest { + // Set Extended ACL request body does not have separate `ContainerID` + // reference. It will be taken from `EACLTable.container_id` field. + message Body { + // Extended ACL table to set for the container + neo.fs.v2.acl.EACLTable eacl = 1; + + // Signature of stable-marshalled Extended ACL table according to RFC-6979. + neo.fs.v2.refs.SignatureRFC6979 signature = 2; + } + // Body of set extended acl request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Set Extended ACL +message SetExtendedACLResponse { + // `SetExtendedACLResponse` has an empty body because the operation is + // asynchronous and the update should be reflected in `Container` smart + // contract's storage after next block is issued in sidechain. + message Body {} + + // Body of set extended acl response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Get Extended ACL +message GetExtendedACLRequest { + // Get Extended ACL request body + message Body { + // Identifier of the container having Extended ACL + neo.fs.v2.refs.ContainerID container_id = 1; + } + + // Body of get extended acl request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Get Extended ACL +message GetExtendedACLResponse { + // Get Extended ACL Response body can be empty if the requested container does + // not have Extended ACL Table attached or Extended ACL has not been allowed + // at the time of container creation. + message Body { + // Extended ACL requested, if available + neo.fs.v2.acl.EACLTable eacl = 1; + + // Signature of stable-marshalled Extended ACL according to RFC-6979. + neo.fs.v2.refs.SignatureRFC6979 signature = 2; + + // Session token if Extended ACL was set within a session + neo.fs.v2.session.SessionToken session_token = 3; + } + // Body of get extended acl response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Announce container used space +message AnnounceUsedSpaceRequest { + // Container used space announcement body. + message Body { + // Announcement contains used space information for a single container. + message Announcement { + // Epoch number for which the container size estimation was produced. + uint64 epoch = 1; + + // Identifier of the container. + neo.fs.v2.refs.ContainerID container_id = 2; + + // Used space is a sum of object payload sizes of a specified + // container, stored in the node. It must not include inhumed objects. + uint64 used_space = 3; + } + + // List of announcements. If nodes share several containers, + // announcements are transferred in a batch. + repeated Announcement announcements = 1; + } + + // Body of announce used space request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Announce container used space +message AnnounceUsedSpaceResponse { + // `AnnounceUsedSpaceResponse` has an empty body because announcements are + // one way communication. + message Body {} + + // Body of announce used space response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} diff --git a/protosV2/src/main/proto/container/types.proto b/protosV2/src/main/proto/container/types.proto new file mode 100644 index 0000000..128a0bd --- /dev/null +++ b/protosV2/src/main/proto/container/types.proto @@ -0,0 +1,76 @@ +syntax = "proto3"; + +package neo.fs.v2.container; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc;container"; +option java_package = "frostFS.container"; + +import "netmap/types.proto"; +import "refs/types.proto"; + +// Container is a structure that defines object placement behaviour. Objects can +// be stored only within containers. They define placement rule, attributes and +// access control information. An ID of a container is a 32 byte long SHA256 +// hash of stable-marshalled container message. +message Container { + // Container format version. Effectively, the version of API library used to + // create the container. + neo.fs.v2.refs.Version version = 1 [ json_name = "version" ]; + + // Identifier of the container owner + neo.fs.v2.refs.OwnerID owner_id = 2 [ json_name = "ownerID" ]; + + // Nonce is a 16 byte UUIDv4, used to avoid collisions of `ContainerID`s + bytes nonce = 3 [ json_name = "nonce" ]; + + // `BasicACL` contains access control rules for the owner, system and others + // groups, as well as permission bits for `BearerToken` and `Extended ACL` + uint32 basic_acl = 4 [ json_name = "basicACL" ]; + + // `Attribute` is a user-defined Key-Value metadata pair attached to the + // container. Container attributes are immutable. They are set at the moment + // of container creation and can never be added or updated. + // + // Key name must be a container-unique valid UTF-8 string. Value can't be + // empty. Containers with duplicated attribute names or attributes with empty + // values will be considered invalid. + // + // There are some "well-known" attributes affecting system behaviour: + // + // * [ __SYSTEM__NAME ] \ + // (`__NEOFS__NAME` is deprecated) \ + // String of a human-friendly container name registered as a domain in + // NNS contract. + // * [ __SYSTEM__ZONE ] \ + // (`__NEOFS__ZONE` is deprecated) \ + // String of a zone for `__SYSTEM__NAME` (`__NEOFS__NAME` is deprecated). + // Used as a TLD of a domain name in NNS contract. If no zone is specified, + // use default zone: `container`. + // * [ __SYSTEM__DISABLE_HOMOMORPHIC_HASHING ] \ + // (`__NEOFS__DISABLE_HOMOMORPHIC_HASHING` is deprecated) \ + // Disables homomorphic hashing for the container if the value equals "true" + // string. Any other values are interpreted as missing attribute. Container + // could be accepted in a NeoFS network only if the global network hashing + // configuration value corresponds with that attribute's value. After + // container inclusion, network setting is ignored. + // + // And some well-known attributes used by applications only: + // + // * Name \ + // Human-friendly name + // * Timestamp \ + // User-defined local time of container creation in Unix Timestamp format + message Attribute { + // Attribute name key + string key = 1 [ json_name = "key" ]; + + // Attribute value + string value = 2 [ json_name = "value" ]; + } + // Attributes represent immutable container's meta data + repeated Attribute attributes = 5 [ json_name = "attributes" ]; + + // Placement policy for the object inside the container + neo.fs.v2.netmap.PlacementPolicy placement_policy = 6 + [ json_name = "placementPolicy" ]; +} diff --git a/protosV2/src/main/proto/lock/types.proto b/protosV2/src/main/proto/lock/types.proto new file mode 100644 index 0000000..85766db --- /dev/null +++ b/protosV2/src/main/proto/lock/types.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package neo.fs.v2.lock; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/lock/grpc;lock"; +option java_package = "frostFS.lock"; + +import "refs/types.proto"; + +// Lock objects protects a list of objects from being deleted. The lifetime of a +// lock object is limited similar to regular objects in +// `__SYSTEM__EXPIRATION_EPOCH` (`__NEOFS__EXPIRATION_EPOCH` is deprecated) +// attribute. Lock object MUST have expiration epoch. It is impossible to delete +// a lock object via ObjectService.Delete RPC call. +message Lock { + // List of objects to lock. Must not be empty or carry empty IDs. + // All members must be of the `REGULAR` type. + repeated neo.fs.v2.refs.ObjectID members = 1 [ json_name = "members" ]; +} diff --git a/protosV2/src/main/proto/netmap/service.proto b/protosV2/src/main/proto/netmap/service.proto new file mode 100644 index 0000000..ac4f4cc --- /dev/null +++ b/protosV2/src/main/proto/netmap/service.proto @@ -0,0 +1,162 @@ +syntax = "proto3"; + +package neo.fs.v2.netmap; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc;netmap"; +option java_package = "frostFS.netmap"; + +import "netmap/types.proto"; +import "refs/types.proto"; +import "session/types.proto"; + +// `NetmapService` provides methods to work with `Network Map` and the +// information required to build it. The resulting `Network Map` is stored in +// sidechain `Netmap` smart contract, while related information can be obtained +// from other NeoFS nodes. +service NetmapService { + // Get NodeInfo structure from the particular node directly. + // Node information can be taken from `Netmap` smart contract. In some cases, + // though, one may want to get recent information directly or to talk to the + // node not yet present in the `Network Map` to find out what API version can + // be used for further communication. This can be also used to check if a node + // is up and running. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the server has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + rpc LocalNodeInfo(LocalNodeInfoRequest) returns (LocalNodeInfoResponse); + + // Read recent information about the NeoFS network. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the current network state has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + rpc NetworkInfo(NetworkInfoRequest) returns (NetworkInfoResponse); + + // Returns network map snapshot of the current NeoFS epoch. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // information about the current network map has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON). + rpc NetmapSnapshot(NetmapSnapshotRequest) returns (NetmapSnapshotResponse); +} + +// Get NodeInfo structure directly from a particular node +message LocalNodeInfoRequest { + // LocalNodeInfo request body is empty. + message Body {} + // Body of the LocalNodeInfo request message + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Local Node Info, including API Version in use +message LocalNodeInfoResponse { + // Local Node Info, including API Version in use. + message Body { + // Latest NeoFS API version in use + neo.fs.v2.refs.Version version = 1; + + // NodeInfo structure with recent information from node itself + NodeInfo node_info = 2; + } + // Body of the balance response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect response execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Get NetworkInfo structure with the network view from a particular node. +message NetworkInfoRequest { + // NetworkInfo request body is empty. + message Body {} + // Body of the NetworkInfo request message + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Response with NetworkInfo structure including current epoch and +// sidechain magic number. +message NetworkInfoResponse { + // Information about the network. + message Body { + // NetworkInfo structure with recent information. + NetworkInfo network_info = 1; + } + // Body of the NetworkInfo response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect response execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Get netmap snapshot request +message NetmapSnapshotRequest { + // Get netmap snapshot request body. + message Body {} + + // Body of get netmap snapshot request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Response with current netmap snapshot +message NetmapSnapshotResponse { + // Get netmap snapshot response body + message Body { + // Structure of the requested network map. + Netmap netmap = 1 [ json_name = "netmap" ]; + } + + // Body of get netmap snapshot response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect response execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} diff --git a/protosV2/src/main/proto/netmap/types.proto b/protosV2/src/main/proto/netmap/types.proto new file mode 100644 index 0000000..1ff2e9e --- /dev/null +++ b/protosV2/src/main/proto/netmap/types.proto @@ -0,0 +1,323 @@ +syntax = "proto3"; + +package neo.fs.v2.netmap; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc;netmap"; +option java_package = "frostFS.netmap"; + +// Operations on filters +enum Operation { + // No Operation defined + OPERATION_UNSPECIFIED = 0; + + // Equal + EQ = 1; + + // Not Equal + NE = 2; + + // Greater then + GT = 3; + + // Greater or equal + GE = 4; + + // Less then + LT = 5; + + // Less or equal + LE = 6; + + // Logical OR + OR = 7; + + // Logical AND + AND = 8; + + // Logical negation + NOT = 9; +} + +// Selector modifier shows how the node set will be formed. By default selector +// just groups nodes into a bucket by attribute, selecting nodes only by their +// hash distance. +enum Clause { + // No modifier defined. Nodes will be selected from the bucket randomly + CLAUSE_UNSPECIFIED = 0; + + // SAME will select only nodes having the same value of bucket attribute + SAME = 1; + + // DISTINCT will select nodes having different values of bucket attribute + DISTINCT = 2; +} + +// This filter will return the subset of nodes from `NetworkMap` or another +// filter's results that will satisfy filter's conditions. +message Filter { + // Name of the filter or a reference to a named filter. '*' means + // application to the whole unfiltered NetworkMap. At top level it's used as a + // filter name. At lower levels it's considered to be a reference to another + // named filter + string name = 1 [ json_name = "name" ]; + + // Key to filter + string key = 2 [ json_name = "key" ]; + + // Filtering operation + Operation op = 3 [ json_name = "op" ]; + + // Value to match + string value = 4 [ json_name = "value" ]; + + // List of inner filters. Top level operation will be applied to the whole + // list. + repeated Filter filters = 5 [ json_name = "filters" ]; +} + +// Selector chooses a number of nodes from the bucket taking the nearest nodes +// to the provided `ContainerID` by hash distance. +message Selector { + // Selector name to reference in object placement section + string name = 1 [ json_name = "name" ]; + + // How many nodes to select from the bucket + uint32 count = 2 [ json_name = "count" ]; + + // Selector modifier showing how to form a bucket + Clause clause = 3 [ json_name = "clause" ]; + + // Bucket attribute to select from + string attribute = 4 [ json_name = "attribute" ]; + + // Filter reference to select from + string filter = 5 [ json_name = "filter" ]; +} + +// Number of object replicas in a set of nodes from the defined selector. If no +// selector set, the root bucket containing all possible nodes will be used by +// default. +message Replica { + // How many object replicas to put + uint32 count = 1 [ json_name = "count" ]; + + // Named selector bucket to put replicas + string selector = 2 [ json_name = "selector" ]; + + // Data shards count + uint32 ec_data_count = 3 [ json_name = "ecDataCount" ]; + + // Parity shards count + uint32 ec_parity_count = 4 [ json_name = "ecParityCount" ]; +} + +// Set of rules to select a subset of nodes from `NetworkMap` able to store +// container's objects. The format is simple enough to transpile from different +// storage policy definition languages. +message PlacementPolicy { + // Rules to set number of object replicas and place each one into a named + // bucket + repeated Replica replicas = 1 [ json_name = "replicas" ]; + + // Container backup factor controls how deep NeoFS will search for nodes + // alternatives to include into container's nodes subset + uint32 container_backup_factor = 2 [ json_name = "containerBackupFactor" ]; + + // Set of Selectors to form the container's nodes subset + repeated Selector selectors = 3 [ json_name = "selectors" ]; + + // List of named filters to reference in selectors + repeated Filter filters = 4 [ json_name = "filters" ]; + + // Unique flag defines non-overlapping application for replicas + bool unique = 5 [ json_name = "unique" ]; +} + +// NeoFS node description +message NodeInfo { + // Public key of the NeoFS node in a binary format + bytes public_key = 1 [ json_name = "publicKey" ]; + + // Ways to connect to a node + repeated string addresses = 2 [ json_name = "addresses" ]; + + // Administrator-defined Attributes of the NeoFS Storage Node. + // + // `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 + // string. Value can't be empty. + // + // Attributes can be constructed into a chain of attributes: any attribute can + // have a parent attribute and a child attribute (except the first and the + // last one). A string representation of the chain of attributes in NeoFS + // Storage Node configuration uses ":" and "/" symbols, e.g.: + // + // `NEOFS_NODE_ATTRIBUTE_1=key1:val1/key2:val2` + // + // Therefore the string attribute representation in the Node configuration + // must use "\:", "\/" and "\\" escaped symbols if any of them appears in an + // attribute's key or value. + // + // Node's attributes are mostly used during Storage Policy evaluation to + // calculate object's placement and find a set of nodes satisfying policy + // requirements. There are some "well-known" node attributes common to all the + // Storage Nodes in the network and used implicitly with default values if not + // explicitly set: + // + // * Capacity \ + // Total available disk space in Gigabytes. + // * Price \ + // Price in GAS tokens for storing one GB of data during one Epoch. In node + // attributes it's a string presenting floating point number with comma or + // point delimiter for decimal part. In the Network Map it will be saved as + // 64-bit unsigned integer representing number of minimal token fractions. + // * UN-LOCODE \ + // Node's geographic location in + // [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html) + // format approximated to the nearest point defined in the standard. + // * CountryCode \ + // Country code in + // [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) + // format. Calculated automatically from `UN-LOCODE` attribute. + // * Country \ + // Country short name in English, as defined in + // [ISO-3166](https://www.iso.org/obp/ui/#search). Calculated automatically + // from `UN-LOCODE` attribute. + // * Location \ + // Place names are given, whenever possible, in their national language + // versions as expressed in the Roman alphabet using the 26 characters of + // the character set adopted for international trade data interchange, + // written without diacritics . Calculated automatically from `UN-LOCODE` + // attribute. + // * SubDivCode \ + // Country's administrative subdivision where node is located. Calculated + // automatically from `UN-LOCODE` attribute based on `SubDiv` field. + // Presented in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) + // format. + // * SubDiv \ + // Country's administrative subdivision name, as defined in + // [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). Calculated + // automatically from `UN-LOCODE` attribute. + // * Continent \ + // Node's continent name according to the [Seven-Continent model] + // (https://en.wikipedia.org/wiki/Continent#Number). Calculated + // automatically from `UN-LOCODE` attribute. + // * ExternalAddr + // Node's preferred way for communications with external clients. + // Clients SHOULD use these addresses if possible. + // Must contain a comma-separated list of multi-addresses. + // + // For detailed description of each well-known attribute please see the + // corresponding section in NeoFS Technical Specification. + message Attribute { + // Key of the node attribute + string key = 1 [ json_name = "key" ]; + + // Value of the node attribute + string value = 2 [ json_name = "value" ]; + + // Parent keys, if any. For example for `City` it could be `Region` and + // `Country`. + repeated string parents = 3 [ json_name = "parents" ]; + } + // Carries list of the NeoFS node attributes in a key-value form. Key name + // must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo + // structures with duplicated attribute names or attributes with empty values + // will be considered invalid. + repeated Attribute attributes = 3 [ json_name = "attributes" ]; + + // Represents the enumeration of various states of the NeoFS node. + enum State { + // Unknown state + UNSPECIFIED = 0; + + // Active state in the network + ONLINE = 1; + + // Network unavailable state + OFFLINE = 2; + + // Maintenance state + MAINTENANCE = 3; + } + + // Carries state of the NeoFS node + State state = 4 [ json_name = "state" ]; +} + +// Network map structure +message Netmap { + // Network map revision number. + uint64 epoch = 1 [ json_name = "epoch" ]; + + // Nodes presented in network. + repeated NodeInfo nodes = 2 [ json_name = "nodes" ]; +} + +// NeoFS network configuration +message NetworkConfig { + // Single configuration parameter. Key MUST be network-unique. + // + // System parameters: + // - **AuditFee** \ + // Fee paid by the storage group owner to the Inner Ring member. + // Value: little-endian integer. Default: 0. + // - **BasicIncomeRate** \ + // Cost of storing one gigabyte of data for a period of one epoch. Paid by + // container owner to container nodes. + // Value: little-endian integer. Default: 0. + // - **ContainerAliasFee** \ + // Fee paid for named container's creation by the container owner. + // Value: little-endian integer. Default: 0. + // - **ContainerFee** \ + // Fee paid for container creation by the container owner. + // Value: little-endian integer. Default: 0. + // - **EpochDuration** \ + // NeoFS epoch duration measured in Sidechain blocks. + // Value: little-endian integer. Default: 0. + // - **HomomorphicHashingDisabled** \ + // Flag of disabling the homomorphic hashing of objects' payload. + // Value: true if any byte != 0. Default: false. + // - **InnerRingCandidateFee** \ + // Fee for entrance to the Inner Ring paid by the candidate. + // Value: little-endian integer. Default: 0. + // - **MaintenanceModeAllowed** \ + // Flag allowing setting the MAINTENANCE state to storage nodes. + // Value: true if any byte != 0. Default: false. + // - **MaxObjectSize** \ + // Maximum size of physically stored NeoFS object measured in bytes. + // Value: little-endian integer. Default: 0. + // - **WithdrawFee** \ + // Fee paid for withdrawal of funds paid by the account owner. + // Value: little-endian integer. Default: 0. + // - **MaxECDataCount** \ + // Maximum number of data shards for EC placement policy. + // Value: little-endian integer. Default: 0. + // - **MaxECParityCount** \ + // Maximum number of parity shards for EC placement policy. + // Value: little-endian integer. Default: 0. + message Parameter { + // Parameter key. UTF-8 encoded string + bytes key = 1 [ json_name = "key" ]; + + // Parameter value + bytes value = 2 [ json_name = "value" ]; + } + // List of parameter values + repeated Parameter parameters = 1 [ json_name = "parameters" ]; +} + +// Information about NeoFS network +message NetworkInfo { + // Number of the current epoch in the NeoFS network + uint64 current_epoch = 1 [ json_name = "currentEpoch" ]; + + // Magic number of the sidechain of the NeoFS network + uint64 magic_number = 2 [ json_name = "magicNumber" ]; + + // MillisecondsPerBlock network parameter of the sidechain of the NeoFS + // network + int64 ms_per_block = 3 [ json_name = "msPerBlock" ]; + + // NeoFS network configuration + NetworkConfig network_config = 4 [ json_name = "networkConfig" ]; +} diff --git a/protosV2/src/main/proto/object/service.proto b/protosV2/src/main/proto/object/service.proto new file mode 100644 index 0000000..98ce6f0 --- /dev/null +++ b/protosV2/src/main/proto/object/service.proto @@ -0,0 +1,816 @@ +syntax = "proto3"; + +package neo.fs.v2.object; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc;object"; +option java_package = "frostFS.object"; + +import "object/types.proto"; +import "refs/types.proto"; +import "session/types.proto"; + +// `ObjectService` provides API for manipulating objects. Object operations do +// not affect the sidechain and are only served by nodes in p2p style. +service ObjectService { + // Receive full object structure, including Headers and payload. Response uses + // gRPC stream. First response message carries the object with the requested + // address. Chunk messages are parts of the object's payload if it is needed. + // All messages, except the first one, carry payload chunks. The requested + // object can be restored by concatenation of object message payload and all + // chunks keeping the receiving order. + // + // Extended headers can change `Get` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions (starting from `__SYSTEM__NETMAP_EPOCH` + // (`__NEOFS__NETMAP_EPOCH` is deprecated) if specified or the latest one + // otherwise) of Network Map to find an object until the depth limit is + // reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // read access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc Get(GetRequest) returns (stream GetResponse); + + // Put the object into container. Request uses gRPC stream. First message + // SHOULD be of PutHeader type. `ContainerID` and `OwnerID` of an object + // SHOULD be set. Session token SHOULD be obtained before `PUT` operation (see + // session package). Chunk messages are considered by server as a part of an + // object payload. All messages, except first one, SHOULD be payload chunks. + // Chunk messages SHOULD be sent in the direct order of fragmentation. + // + // Extended headers can change `Put` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requsted version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc Put(stream PutRequest) returns (PutResponse); + + // Delete the object from a container. There is no immediate removal + // guarantee. Object will be marked for removal and deleted eventually. + // + // Extended headers can change `Delete` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully marked to be removed from the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // delete access to the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // the object could not be deleted because it has not been \ + // found within the container; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // deleting a locked object is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc Delete(DeleteRequest) returns (DeleteResponse); + + // Returns the object Headers without data payload. By default full header is + // returned. If `main_only` request field is set, the short header with only + // the very minimal information will be returned instead. + // + // Extended headers can change `Head` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object header has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation HEAD of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc Head(HeadRequest) returns (HeadResponse); + + // Search objects in container. Search query allows to match by Object + // Header's filed values. Please see the corresponding NeoFS Technical + // Specification section for more details. + // + // Extended headers can change `Search` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // objects have been successfully selected; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation SEARCH of the object is denied; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // search container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc Search(SearchRequest) returns (stream SearchResponse); + + // Get byte range of data payload. Range is set as an (offset, length) tuple. + // Like in `Get` method, the response uses gRPC stream. Requested range can be + // restored by concatenation of all received payload chunks keeping the + // receiving order. + // + // Extended headers can change `GetRange` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully read; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGE of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OBJECT_ALREADY_REMOVED** (2052, SECTION_OBJECT): \ + // the requested object has been marked as deleted. + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc GetRange(GetRangeRequest) returns (stream GetRangeResponse); + + // Returns homomorphic or regular hash of object's payload range after + // applying XOR operation with the provided `salt`. Ranges are set of (offset, + // length) tuples. Hashes order in response corresponds to the ranges order in + // the request. Note that hash is calculated for XORed data. + // + // Extended headers can change `GetRangeHash` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH ] \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ + // (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ + // Will try older versions of Network Map to find an object until the depth + // limit is reached. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // data range of the object payload has been successfully hashed; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // access to operation RANGEHASH of the object is denied; + // - **OBJECT_NOT_FOUND** (2049, SECTION_OBJECT): \ + // object not found in container; + // - **OUT_OF_RANGE** (2053, SECTION_OBJECT): \ + // the requested range is out of bounds; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc GetRangeHash(GetRangeHashRequest) returns (GetRangeHashResponse); + + // Put the prepared object into container. + // `ContainerID`, `ObjectID`, `OwnerID`, `PayloadHash` and `PayloadLength` of + // an object MUST be set. + // + // Extended headers can change `Put` behaviour: + // * [ __SYSTEM__NETMAP_EPOCH \ + // (`__NEOFS__NETMAP_EPOCH` is deprecated) \ + // Will use the requested version of Network Map for object placement + // calculation. + // + // Please refer to detailed `XHeader` description. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): \ + // object has been successfully saved in the container; + // - Common failures (SECTION_FAILURE_COMMON); + // - **ACCESS_DENIED** (2048, SECTION_OBJECT): \ + // write access to the container is denied; + // - **LOCKED** (2050, SECTION_OBJECT): \ + // placement of an object of type TOMBSTONE that includes at least one + // locked object is prohibited; + // - **LOCK_NON_REGULAR_OBJECT** (2051, SECTION_OBJECT): \ + // placement of an object of type LOCK that includes at least one object of + // type other than REGULAR is prohibited; + // - **CONTAINER_NOT_FOUND** (3072, SECTION_CONTAINER): \ + // object storage container not found; + // - **CONTAINER_ACCESS_DENIED** (3074, SECTION_CONTAINER): \ + // access to container is denied; + // - **TOKEN_NOT_FOUND** (4096, SECTION_SESSION): \ + // (for trusted object preparation) session private key does not exist or + // has + // been deleted; + // - **TOKEN_EXPIRED** (4097, SECTION_SESSION): \ + // provided session token has expired. + rpc PutSingle(PutSingleRequest) returns (PutSingleResponse); +} + +// GET object request +message GetRequest { + // GET Object request body + message Body { + // Address of the requested object + neo.fs.v2.refs.Address address = 1; + + // If `raw` flag is set, request will work only with objects that are + // physically stored on the peer node + bool raw = 2; + } + // Body of get object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// GET object response +message GetResponse { + // GET Object Response body + message Body { + // Initial part of the `Object` structure stream. Technically it's a + // set of all `Object` structure's fields except `payload`. + message Init { + // Object's unique identifier. + neo.fs.v2.refs.ObjectID object_id = 1; + + // Signed `ObjectID` + neo.fs.v2.refs.Signature signature = 2; + + // Object metadata headers + Header header = 3; + } + // Single message in the response stream. + oneof object_part { + // Initial part of the object stream + Init init = 1; + + // Chunked object payload + bytes chunk = 2; + + // Meta information of split hierarchy for object assembly. + SplitInfo split_info = 3; + + // Meta information for EC object assembly. + ECInfo ec_info = 4; + } + } + // Body of get object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// PUT object request +message PutRequest { + // PUT request body + message Body { + // Newly created object structure parameters. If some optional parameters + // are not set, they will be calculated by a peer node. + message Init { + // ObjectID if available. + neo.fs.v2.refs.ObjectID object_id = 1; + + // Object signature if available + neo.fs.v2.refs.Signature signature = 2; + + // Object's Header + Header header = 3; + + // Number of copies of the object to store within the RPC call. By + // default, object is processed according to the container's placement + // policy. Can be one of: + // 1. A single number; applied to the whole request and is treated as + // a minimal number of nodes that must store an object to complete the + // request successfully. + // 2. An ordered array; every number is treated as a minimal number of + // nodes in a corresponding placement vector that must store an object + // to complete the request successfully. The length MUST equal the + // placement vectors number, otherwise request is considered malformed. + repeated uint32 copies_number = 4; + } + // Single message in the request stream. + oneof object_part { + // Initial part of the object stream + Init init = 1; + + // Chunked object payload + bytes chunk = 2; + } + } + // Body of put object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// PUT Object response +message PutResponse { + // PUT Object response body + message Body { + // Identifier of the saved object + neo.fs.v2.refs.ObjectID object_id = 1; + } + // Body of put object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Object DELETE request +message DeleteRequest { + // Object DELETE request body + message Body { + // Address of the object to be deleted + neo.fs.v2.refs.Address address = 1; + } + // Body of delete object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// DeleteResponse body is empty because we cannot guarantee permanent object +// removal in distributed system. +message DeleteResponse { + // Object DELETE Response has an empty body. + message Body { + // Address of the tombstone created for the deleted object + neo.fs.v2.refs.Address tombstone = 1; + } + + // Body of delete object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Object HEAD request +message HeadRequest { + // Object HEAD request body + message Body { + // Address of the object with the requested Header + neo.fs.v2.refs.Address address = 1; + + // Return only minimal header subset + bool main_only = 2; + + // If `raw` flag is set, request will work only with objects that are + // physically stored on the peer node + bool raw = 3; + } + // Body of head object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Tuple of a full object header and signature of an `ObjectID`. \ +// Signed `ObjectID` is present to verify full header's authenticity through the +// following steps: +// +// 1. Calculate `SHA-256` of the marshalled `Header` structure +// 2. Check if the resulting hash matches `ObjectID` +// 3. Check if `ObjectID` signature in `signature` field is correct +message HeaderWithSignature { + // Full object header + Header header = 1 [ json_name = "header" ]; + + // Signed `ObjectID` to verify full header's authenticity + neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ]; +} + +// Object HEAD response +message HeadResponse { + // Object HEAD response body + message Body { + // Requested object header, it's part or meta information about split + // object. + oneof head { + // Full object's `Header` with `ObjectID` signature + HeaderWithSignature header = 1; + + // Short object header + ShortHeader short_header = 2; + + // Meta information of split hierarchy. + SplitInfo split_info = 3; + + // Meta information for EC object assembly. + ECInfo ec_info = 4; + } + } + // Body of head object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Object Search request +message SearchRequest { + // Object Search request body + message Body { + // Container identifier were to search + neo.fs.v2.refs.ContainerID container_id = 1; + + // Version of the Query Language used + uint32 version = 2; + // Filter structure checks if the object header field or the attribute + // content matches a value. + // + // If no filters are set, search request will return all objects of the + // container, including Regular object and Tombstone + // objects. Most human users expect to get only object they can directly + // work with. In that case, `$Object:ROOT` filter should be used. + // + // By default `key` field refers to the corresponding object's `Attribute`. + // Some Object's header fields can also be accessed by adding `$Object:` + // prefix to the name. Here is the list of fields available via this prefix: + // + // * $Object:version \ + // version + // * $Object:objectID \ + // object_id + // * $Object:containerID \ + // container_id + // * $Object:ownerID \ + // owner_id + // * $Object:creationEpoch \ + // creation_epoch + // * $Object:payloadLength \ + // payload_length + // * $Object:payloadHash \ + // payload_hash + // * $Object:objectType \ + // object_type + // * $Object:homomorphicHash \ + // homomorphic_hash + // * $Object:split.parent \ + // object_id of parent + // * $Object:split.splitID \ + // 16 byte UUIDv4 used to identify the split object hierarchy parts + // + // There are some well-known filter aliases to match objects by certain + // properties: + // + // * $Object:ROOT \ + // Returns only `REGULAR` type objects that are not split or that are the + // top level root objects in a split hierarchy. This includes objects not + // present physically, like large objects split into smaller objects + // without a separate top-level root object. Objects of other types like + // Locks and Tombstones will not be shown. This filter may be + // useful for listing objects like `ls` command of some virtual file + // system. This filter is activated if the `key` exists, disregarding the + // value and matcher type. + // * $Object:PHY \ + // Returns only objects physically stored in the system. This filter is + // activated if the `key` exists, disregarding the value and matcher type. + // + // Note: using filters with a key with prefix `$Object:` and match type + // `NOT_PRESENT `is not recommended since this is not a cross-version + // approach. Behavior when processing this kind of filters is undefined. + message Filter { + // Match type to use + MatchType match_type = 1 [ json_name = "matchType" ]; + + // Attribute or Header fields to match + string key = 2 [ json_name = "key" ]; + + // Value to match + string value = 3 [ json_name = "value" ]; + } + // List of search expressions + repeated Filter filters = 3; + } + // Body of search object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Search response +message SearchResponse { + // Object Search response body + message Body { + // List of `ObjectID`s that match the search query + repeated neo.fs.v2.refs.ObjectID id_list = 1; + } + // Body of search object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Object payload range.Ranges of zero length SHOULD be considered as invalid. +message Range { + // Offset of the range from the object payload start + uint64 offset = 1; + + // Length in bytes of the object payload range + uint64 length = 2; +} + +// Request part of object's payload +message GetRangeRequest { + // Byte range of object's payload request body + message Body { + // Address of the object containing the requested payload range + neo.fs.v2.refs.Address address = 1; + + // Requested payload range + Range range = 2; + + // If `raw` flag is set, request will work only with objects that are + // physically stored on the peer node. + bool raw = 3; + } + + // Body of get range object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Get part of object's payload +message GetRangeResponse { + // Get Range response body uses streams to transfer the response. Because + // object payload considered a byte sequence, there is no need to have some + // initial preamble message. The requested byte range is sent as a series + // chunks. + message Body { + // Requested object range or meta information about split object. + oneof range_part { + // Chunked object payload's range. + bytes chunk = 1; + + // Meta information of split hierarchy. + SplitInfo split_info = 2; + + // Meta information for EC object assembly. + ECInfo ec_info = 3; + } + } + + // Body of get range object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Get hash of object's payload part +message GetRangeHashRequest { + // Get hash of object's payload part request body. + message Body { + // Address of the object that containing the requested payload range + neo.fs.v2.refs.Address address = 1; + + // List of object's payload ranges to calculate homomorphic hash + repeated Range ranges = 2; + + // Binary salt to XOR object's payload ranges before hash calculation + bytes salt = 3; + + // Checksum algorithm type + neo.fs.v2.refs.ChecksumType type = 4; + } + // Body of get range hash object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Get hash of object's payload part +message GetRangeHashResponse { + // Get hash of object's payload part response body. + message Body { + // Checksum algorithm type + neo.fs.v2.refs.ChecksumType type = 1; + + // List of range hashes in a binary format + repeated bytes hash_list = 2; + } + // Body of get range hash object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} + +// Object PUT Single request +message PutSingleRequest { + // PUT Single request body + message Body { + // Prepared object with payload. + Object object = 1; + // Number of copies of the object to store within the RPC call. By default, + // object is processed according to the container's placement policy. + // Every number is treated as a minimal number of + // nodes in a corresponding placement vector that must store an object + // to complete the request successfully. The length MUST equal the placement + // vectors number, otherwise request is considered malformed. + repeated uint32 copies_number = 2; + } + // Body of put single object request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Object PUT Single response +message PutSingleResponse { + // PUT Single Object response body + message Body {} + // Body of put single object response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} \ No newline at end of file diff --git a/protosV2/src/main/proto/object/types.proto b/protosV2/src/main/proto/object/types.proto new file mode 100644 index 0000000..3162270 --- /dev/null +++ b/protosV2/src/main/proto/object/types.proto @@ -0,0 +1,266 @@ +syntax = "proto3"; + +package neo.fs.v2.object; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc;object"; +option java_package = "frostFS.object"; + +import "refs/types.proto"; +import "session/types.proto"; + +// Type of the object payload content. Only `REGULAR` type objects can be split, +// hence `TOMBSTONE` and `LOCK` payload is limited by the +// maximum object size. +// +// String presentation of object type is the same as definition: +// * REGULAR +// * TOMBSTONE +// * LOCK +enum ObjectType { + // Just a normal object + REGULAR = 0; + + // Used internally to identify deleted objects + TOMBSTONE = 1; + + // Unused (previously storageGroup information) + // _ = 2; + + // Object lock + LOCK = 3; +} + +// Type of match expression +enum MatchType { + // Unknown. Not used + MATCH_TYPE_UNSPECIFIED = 0; + + // Full string match + STRING_EQUAL = 1; + + // Full string mismatch + STRING_NOT_EQUAL = 2; + + // Lack of key + NOT_PRESENT = 3; + + // String prefix match + COMMON_PREFIX = 4; +} + +// Short header fields +message ShortHeader { + // Object format version. Effectively, the version of API library used to + // create particular object. + neo.fs.v2.refs.Version version = 1 [ json_name = "version" ]; + + // Epoch when the object was created + uint64 creation_epoch = 2 [ json_name = "creationEpoch" ]; + + // Object's owner + neo.fs.v2.refs.OwnerID owner_id = 3 [ json_name = "ownerID" ]; + + // Type of the object payload content + ObjectType object_type = 4 [ json_name = "objectType" ]; + + // Size of payload in bytes. + // `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown + uint64 payload_length = 5 [ json_name = "payloadLength" ]; + + // Hash of payload bytes + neo.fs.v2.refs.Checksum payload_hash = 6 [ json_name = "payloadHash" ]; + + // Homomorphic hash of the object payload + neo.fs.v2.refs.Checksum homomorphic_hash = 7 + [ json_name = "homomorphicHash" ]; +} + +// Object Header +message Header { + // Object format version. Effectively, the version of API library used to + // create particular object + neo.fs.v2.refs.Version version = 1 [ json_name = "version" ]; + + // Object's container + neo.fs.v2.refs.ContainerID container_id = 2 [ json_name = "containerID" ]; + + // Object's owner + neo.fs.v2.refs.OwnerID owner_id = 3 [ json_name = "ownerID" ]; + + // Object creation Epoch + uint64 creation_epoch = 4 [ json_name = "creationEpoch" ]; + + // Size of payload in bytes. + // `0xFFFFFFFFFFFFFFFF` means `payload_length` is unknown. + uint64 payload_length = 5 [ json_name = "payloadLength" ]; + + // Hash of payload bytes + neo.fs.v2.refs.Checksum payload_hash = 6 [ json_name = "payloadHash" ]; + + // Type of the object payload content + ObjectType object_type = 7 [ json_name = "objectType" ]; + + // Homomorphic hash of the object payload + neo.fs.v2.refs.Checksum homomorphic_hash = 8 + [ json_name = "homomorphicHash" ]; + + // Session token, if it was used during Object creation. Need it to verify + // integrity and authenticity out of Request scope. + neo.fs.v2.session.SessionToken session_token = 9 + [ json_name = "sessionToken" ]; + + // `Attribute` is a user-defined Key-Value metadata pair attached to an + // object. + // + // Key name must be an object-unique valid UTF-8 string. Value can't be empty. + // Objects with duplicated attribute names or attributes with empty values + // will be considered invalid. + // + // There are some "well-known" attributes starting with `__SYSTEM__` + // (`__NEOFS__` is deprecated) prefix that affect system behaviour: + // + // * [ __SYSTEM__UPLOAD_ID ] \ + // (`__NEOFS__UPLOAD_ID` is deprecated) \ + // Marks smaller parts of a split bigger object + // * [ __SYSTEM__EXPIRATION_EPOCH ] \ + // (`__NEOFS__EXPIRATION_EPOCH` is deprecated) \ + // The epoch after which object with no LOCKs on it becomes unavailable. + // Locked object continues to be available until each of the LOCKs expire. + // * [ __SYSTEM__TICK_EPOCH ] \ + // (`__NEOFS__TICK_EPOCH` is deprecated) \ + // Decimal number that defines what epoch must produce + // object notification with UTF-8 object address in a + // body (`0` value produces notification right after + // object put) + // * [ __SYSTEM__TICK_TOPIC ] \ + // (`__NEOFS__TICK_TOPIC` is deprecated) \ + // UTF-8 string topic ID that is used for object notification + // + // And some well-known attributes used by applications only: + // + // * Name \ + // Human-friendly name + // * FileName \ + // File name to be associated with the object on saving + // * FilePath \ + // Full path to be associated with the object on saving. Should start with a + // '/' and use '/' as a delimiting symbol. Trailing '/' should be + // interpreted as a virtual directory marker. If an object has conflicting + // FilePath and FileName, FilePath should have higher priority, because it + // is used to construct the directory tree. FilePath with trailing '/' and + // non-empty FileName attribute should not be used together. + // * Timestamp \ + // User-defined local time of object creation in Unix Timestamp format + // * Content-Type \ + // MIME Content Type of object's payload + // + // For detailed description of each well-known attribute please see the + // corresponding section in NeoFS Technical Specification. + message Attribute { + // string key to the object attribute + string key = 1 [ json_name = "key" ]; + // string value of the object attribute + string value = 2 [ json_name = "value" ]; + } + // User-defined object attributes + repeated Attribute attributes = 10 [ json_name = "attributes" ]; + + // Bigger objects can be split into a chain of smaller objects. Information + // about inter-dependencies between spawned objects and how to re-construct + // the original one is in the `Split` headers. Parent and children objects + // must be within the same container. + message Split { + // Identifier of the origin object. Known only to the minor child. + neo.fs.v2.refs.ObjectID parent = 1 [ json_name = "parent" ]; + + // Identifier of the left split neighbor + neo.fs.v2.refs.ObjectID previous = 2 [ json_name = "previous" ]; + + // `signature` field of the parent object. Used to reconstruct parent. + neo.fs.v2.refs.Signature parent_signature = 3 + [ json_name = "parentSignature" ]; + + // `header` field of the parent object. Used to reconstruct parent. + Header parent_header = 4 [ json_name = "parentHeader" ]; + + // List of identifiers of the objects generated by splitting current one. + repeated neo.fs.v2.refs.ObjectID children = 5 [ json_name = "children" ]; + + // 16 byte UUIDv4 used to identify the split object hierarchy parts. Must be + // unique inside container. All objects participating in the split must have + // the same `split_id` value. + bytes split_id = 6 [ json_name = "splitID" ]; + } + // Position of the object in the split hierarchy + Split split = 11 [ json_name = "split" ]; + + // Erasure code can be applied to any object. + // Information about encoded object structure is stored in `EC` header. + // All objects belonging to a single EC group have the same `parent` field. + message EC { + // Identifier of the origin object. Known to all chunks. + neo.fs.v2.refs.ObjectID parent = 1 [ json_name = "parent" ]; + // Index of this chunk. + uint32 index = 2 [ json_name = "index" ]; + // Total number of chunks in this split. + uint32 total = 3 [ json_name = "total" ]; + // Total length of a parent header. Used to trim padding zeroes. + uint32 header_length = 4 [ json_name = "headerLength" ]; + // Chunk of a parent header. + bytes header = 5 [ json_name = "header" ]; + } + // Erasure code chunk information. + EC ec = 12 [ json_name = "ec" ]; +} + +// Object structure. Object is immutable and content-addressed. It means +// `ObjectID` will change if the header or the payload changes. It's calculated +// as a hash of header field which contains hash of the object's payload. +// +// For non-regular object types payload format depends on object type specified +// in the header. +message Object { + // Object's unique identifier. + neo.fs.v2.refs.ObjectID object_id = 1 [ json_name = "objectID" ]; + + // Signed object_id + neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ]; + + // Object metadata headers + Header header = 3 [ json_name = "header" ]; + + // Payload bytes + bytes payload = 4 [ json_name = "payload" ]; +} + +// Meta information of split hierarchy for object assembly. With the last part +// one can traverse linked list of split hierarchy back to the first part and +// assemble the original object. With a linking object one can assemble an +// object right from the object parts. +message SplitInfo { + // 16 byte UUID used to identify the split object hierarchy parts. + bytes split_id = 1; + + // The identifier of the last object in split hierarchy parts. It contains + // split header with the original object header. + neo.fs.v2.refs.ObjectID last_part = 2; + + // The identifier of a linking object for split hierarchy parts. It contains + // split header with the original object header and a sorted list of + // object parts. + neo.fs.v2.refs.ObjectID link = 3; +} + +// Meta information for the erasure-encoded object. +message ECInfo { + message Chunk { + // Object ID of the chunk. + neo.fs.v2.refs.ObjectID id = 1; + // Index of the chunk. + uint32 index = 2; + // Total number of chunks in this split. + uint32 total = 3; + } + // Chunk stored on the node. + repeated Chunk chunks = 1; +} \ No newline at end of file diff --git a/protosV2/src/main/proto/refs/types.proto b/protosV2/src/main/proto/refs/types.proto new file mode 100644 index 0000000..30cb552 --- /dev/null +++ b/protosV2/src/main/proto/refs/types.proto @@ -0,0 +1,150 @@ +syntax = "proto3"; + +package neo.fs.v2.refs; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc;refs"; +option java_package = "frostFS.refs"; + +// Objects in NeoFS are addressed by their ContainerID and ObjectID. +// +// String presentation of `Address` is a concatenation of string encoded +// `ContainerID` and `ObjectID` delimited by '/' character. +message Address { + // Container identifier + ContainerID container_id = 1 [ json_name = "containerID" ]; + // Object identifier + ObjectID object_id = 2 [ json_name = "objectID" ]; +} + +// NeoFS Object unique identifier. Objects are immutable and content-addressed. +// It means `ObjectID` will change if the `header` or the `payload` changes. +// +// `ObjectID` is a 32 byte long +// [SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of +// the object's `header` field, which, in it's turn, contains the hash of the +// object's payload. +// +// String presentation is a +// [base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string. +// +// JSON value will be data encoded as a string using standard base64 +// encoding with paddings. Either +// [standard](https://tools.ietf.org/html/rfc4648#section-4) or +// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding +// with/without paddings are accepted. +message ObjectID { + // Object identifier in a binary format + bytes value = 1 [ json_name = "value" ]; +} + +// NeoFS container identifier. Container structures are immutable and +// content-addressed. +// +// `ContainerID` is a 32 byte long +// [SHA256](https://csrc.nist.gov/publications/detail/fips/180/4/final) hash of +// stable-marshalled container message. +// +// String presentation is a +// [base58](https://tools.ietf.org/html/draft-msporny-base58-02) encoded string. +// +// JSON value will be data encoded as a string using standard base64 +// encoding with paddings. Either +// [standard](https://tools.ietf.org/html/rfc4648#section-4) or +// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding +// with/without paddings are accepted. +message ContainerID { + // Container identifier in a binary format. + bytes value = 1 [ json_name = "value" ]; +} + +// `OwnerID` is a derivative of a user's main public key. The transformation +// algorithm is the same as for Neo3 wallet addresses. Neo3 wallet address can +// be directly used as `OwnerID`. +// +// `OwnerID` is a 25 bytes sequence starting with Neo version prefix byte +// followed by 20 bytes of ScrptHash and 4 bytes of checksum. +// +// String presentation is a [Base58 +// Check](https://en.bitcoin.it/wiki/Base58Check_encoding) Encoded string. +// +// JSON value will be data encoded as a string using standard base64 +// encoding with paddings. Either +// [standard](https://tools.ietf.org/html/rfc4648#section-4) or +// [URL-safe](https://tools.ietf.org/html/rfc4648#section-5) base64 encoding +// with/without paddings are accepted. +message OwnerID { + // Identifier of the container owner in a binary format + bytes value = 1 [ json_name = "value" ]; +} + +// API version used by a node. +// +// String presentation is a Semantic Versioning 2.0.0 compatible version string +// with 'v' prefix. i.e. `vX.Y`, where `X` is the major number, `Y` is the minor +// number. +message Version { + // Major API version + uint32 major = 1 [ json_name = "major" ]; + + // Minor API version + uint32 minor = 2 [ json_name = "minor" ]; +} + +// Signature of something in NeoFS. +message Signature { + // Public key used for signing + bytes key = 1 [ json_name = "key" ]; + // Signature + bytes sign = 2 [ json_name = "signature" ]; + // Scheme contains digital signature scheme identifier + SignatureScheme scheme = 3 [ json_name = "scheme" ]; +} + +// Signature scheme describes digital signing scheme used for (key, signature) +// pair. +enum SignatureScheme { + // ECDSA with SHA-512 hashing (FIPS 186-3) + ECDSA_SHA512 = 0; + + // Deterministic ECDSA with SHA-256 hashing (RFC 6979) + ECDSA_RFC6979_SHA256 = 1; + + // Deterministic ECDSA with SHA-256 hashing using WalletConnect API. + // Here the algorithm is the same, but the message format differs. + ECDSA_RFC6979_SHA256_WALLET_CONNECT = 2; +} + +// RFC 6979 signature. +message SignatureRFC6979 { + // Public key used for signing + bytes key = 1 [ json_name = "key" ]; + // Deterministic ECDSA with SHA-256 hashing + bytes sign = 2 [ json_name = "signature" ]; +} + +// Checksum algorithm type. +enum ChecksumType { + // Unknown. Not used + CHECKSUM_TYPE_UNSPECIFIED = 0; + + // Tillich-Zemor homomorphic hash function + TZ = 1; + + // SHA-256 + SHA256 = 2; +} + +// Checksum message. +// Depending on checksum algorithm type, the string presentation may vary: +// +// * TZ \ +// Hex encoded string without `0x` prefix +// * SHA256 \ +// Hex encoded string without `0x` prefix +message Checksum { + // Checksum algorithm type + ChecksumType type = 1 [ json_name = "type" ]; + + // Checksum itself + bytes sum = 2 [ json_name = "sum" ]; +} diff --git a/protosV2/src/main/proto/session/service.proto b/protosV2/src/main/proto/session/service.proto new file mode 100644 index 0000000..84cbff4 --- /dev/null +++ b/protosV2/src/main/proto/session/service.proto @@ -0,0 +1,69 @@ +syntax = "proto3"; + +package neo.fs.v2.session; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc;session"; +option java_package = "frostFS.session"; + +import "refs/types.proto"; +import "session/types.proto"; + +// `SessionService` allows to establish a temporary trust relationship between +// two peer nodes and generate a `SessionToken` as the proof of trust to be +// attached in requests for further verification. Please see corresponding +// section of NeoFS Technical Specification for details. +service SessionService { + // Open a new session between two peers. + // + // Statuses: + // - **OK** (0, SECTION_SUCCESS): + // session has been successfully opened; + // - Common failures (SECTION_FAILURE_COMMON). + rpc Create(CreateRequest) returns (CreateResponse); +} + +// Information necessary for opening a session. +message CreateRequest { + // Session creation request body + message Body { + // Session initiating user's or node's key derived `OwnerID` + neo.fs.v2.refs.OwnerID owner_id = 1; + // Session expiration `Epoch` + uint64 expiration = 2; + } + // Body of a create session token request message. + Body body = 1; + + // Carries request meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.RequestMetaHeader meta_header = 2; + + // Carries request verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.RequestVerificationHeader verify_header = 3; +} + +// Information about the opened session. +message CreateResponse { + // Session creation response body + message Body { + // Identifier of a newly created session + bytes id = 1; + + // Public key used for session + bytes session_key = 2; + } + + // Body of create session token response message. + Body body = 1; + + // Carries response meta information. Header data is used only to regulate + // message transport and does not affect request execution. + neo.fs.v2.session.ResponseMetaHeader meta_header = 2; + + // Carries response verification information. This header is used to + // authenticate the nodes of the message route and check the correctness of + // transmission. + neo.fs.v2.session.ResponseVerificationHeader verify_header = 3; +} diff --git a/protosV2/src/main/proto/session/types.proto b/protosV2/src/main/proto/session/types.proto new file mode 100644 index 0000000..2b33386 --- /dev/null +++ b/protosV2/src/main/proto/session/types.proto @@ -0,0 +1,238 @@ +syntax = "proto3"; + +package neo.fs.v2.session; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc;session"; +option java_package = "frostFS.session"; + +import "refs/types.proto"; +import "acl/types.proto"; +import "status/types.proto"; + +// Context information for Session Tokens related to ObjectService requests +message ObjectSessionContext { + // Object request verbs + enum Verb { + // Unknown verb + VERB_UNSPECIFIED = 0; + + // Refers to object.Put RPC call + PUT = 1; + + // Refers to object.Get RPC call + GET = 2; + + // Refers to object.Head RPC call + HEAD = 3; + + // Refers to object.Search RPC call + SEARCH = 4; + + // Refers to object.Delete RPC call + DELETE = 5; + + // Refers to object.GetRange RPC call + RANGE = 6; + + // Refers to object.GetRangeHash RPC call + RANGEHASH = 7; + } + // Type of request for which the token is issued + Verb verb = 1 [ json_name = "verb" ]; + + // Carries objects involved in the object session. + message Target { + // Indicates which container the session is spread to. Field MUST be set + // and correct. + refs.ContainerID container = 1 [ json_name = "container" ]; + + // Indicates which objects the session is spread to. Objects are expected + // to be stored in the NeoFS container referenced by `container` field. + // Each element MUST have correct format. + repeated refs.ObjectID objects = 2 [ json_name = "objects" ]; + } + // Object session target. MUST be correctly formed and set. If `objects` + // field is not empty, then the session applies only to these elements, + // otherwise, to all objects from the specified container. + Target target = 2 [ json_name = "target" ]; +} + +// Context information for Session Tokens related to ContainerService requests. +message ContainerSessionContext { + // Container request verbs + enum Verb { + // Unknown verb + VERB_UNSPECIFIED = 0; + + // Refers to container.Put RPC call + PUT = 1; + + // Refers to container.Delete RPC call + DELETE = 2; + + // Refers to container.SetExtendedACL RPC call + SETEACL = 3; + } + // Type of request for which the token is issued + Verb verb = 1 [ json_name = "verb" ]; + + // Spreads the action to all owner containers. + // If set, container_id field is ignored. + bool wildcard = 2 [ json_name = "wildcard" ]; + + // Particular container to which the action applies. + // Ignored if wildcard flag is set. + refs.ContainerID container_id = 3 [ json_name = "containerID" ]; +} + +// NeoFS Session Token. +message SessionToken { + // Session Token body + message Body { + // Token identifier is a valid UUIDv4 in binary form + bytes id = 1 [ json_name = "id" ]; + + // Identifier of the session initiator + neo.fs.v2.refs.OwnerID owner_id = 2 [ json_name = "ownerID" ]; + + // Lifetime parameters of the token. Field names taken from rfc7519. + message TokenLifetime { + // Expiration Epoch + uint64 exp = 1 [ json_name = "exp" ]; + + // Not valid before Epoch + uint64 nbf = 2 [ json_name = "nbf" ]; + + // Issued at Epoch + uint64 iat = 3 [ json_name = "iat" ]; + } + // Lifetime of the session + TokenLifetime lifetime = 3 [ json_name = "lifetime" ]; + + // Public key used in session + bytes session_key = 4 [ json_name = "sessionKey" ]; + + // Session Context information + oneof context { + // ObjectService session context + ObjectSessionContext object = 5 [ json_name = "object" ]; + + // ContainerService session context + ContainerSessionContext container = 6 [ json_name = "container" ]; + } + } + // Session Token contains the proof of trust between peers to be attached in + // requests for further verification. Please see corresponding section of + // NeoFS Technical Specification for details. + Body body = 1 [ json_name = "body" ]; + + // Signature of `SessionToken` information + neo.fs.v2.refs.Signature signature = 2 [ json_name = "signature" ]; +} + +// Extended headers for Request/Response. They may contain any user-defined +// headers to be interpreted on application level. +// +// Key name must be a unique valid UTF-8 string. Value can't be empty. Requests +// or Responses with duplicated header names or headers with empty values will +// be considered invalid. +// +// There are some "well-known" headers starting with `__SYSTEM__` (`__NEOFS__` +// is deprecated) prefix that affect system behaviour: +// +// * [ __SYSTEM__NETMAP_EPOCH ] \ +// (`__NEOFS__NETMAP_EPOCH` is deprecated) \ +// Netmap epoch to use for object placement calculation. The `value` is string +// encoded `uint64` in decimal presentation. If set to '0' or not set, the +// current epoch only will be used. +// * [ __SYSTEM__NETMAP_LOOKUP_DEPTH ] \ +// (`__NEOFS__NETMAP_LOOKUP_DEPTH` is deprecated) \ +// If object can't be found using current epoch's netmap, this header limits +// how many past epochs the node can look up through. The `value` is string +// encoded `uint64` in decimal presentation. If set to '0' or not set, only +// the current epoch will be used. +message XHeader { + // Key of the X-Header + string key = 1 [ json_name = "key" ]; + + // Value of the X-Header + string value = 2 [ json_name = "value" ]; +} + +// Meta information attached to the request. When forwarded between peers, +// request meta headers are folded in matryoshka style. +message RequestMetaHeader { + // Peer's API version used + neo.fs.v2.refs.Version version = 1 [ json_name = "version" ]; + + // Peer's local epoch number. Set to 0 if unknown. + uint64 epoch = 2 [ json_name = "epoch" ]; + + // Maximum number of intermediate nodes in the request route + uint32 ttl = 3 [ json_name = "ttl" ]; + + // Request X-Headers + repeated XHeader x_headers = 4 [ json_name = "xHeaders" ]; + + // Session token within which the request is sent + SessionToken session_token = 5 [ json_name = "sessionToken" ]; + + // `BearerToken` with eACL overrides for the request + neo.fs.v2.acl.BearerToken bearer_token = 6 [ json_name = "bearerToken" ]; + + // `RequestMetaHeader` of the origin request + RequestMetaHeader origin = 7 [ json_name = "origin" ]; + + // NeoFS network magic. Must match the value for the network + // that the server belongs to. + uint64 magic_number = 8 [ json_name = "magicNumber" ]; +} + +// Information about the response +message ResponseMetaHeader { + // Peer's API version used + neo.fs.v2.refs.Version version = 1 [ json_name = "version" ]; + + // Peer's local epoch number + uint64 epoch = 2 [ json_name = "epoch" ]; + + // Maximum number of intermediate nodes in the request route + uint32 ttl = 3 [ json_name = "ttl" ]; + + // Response X-Headers + repeated XHeader x_headers = 4 [ json_name = "xHeaders" ]; + + // `ResponseMetaHeader` of the origin request + ResponseMetaHeader origin = 5 [ json_name = "origin" ]; + + // Status return + neo.fs.v2.status.Status status = 6 [ json_name = "status" ]; +} + +// Verification info for the request signed by all intermediate nodes. +message RequestVerificationHeader { + // Request Body signature. Should be generated once by the request initiator. + neo.fs.v2.refs.Signature body_signature = 1 [ json_name = "bodySignature" ]; + // Request Meta signature is added and signed by each intermediate node + neo.fs.v2.refs.Signature meta_signature = 2 [ json_name = "metaSignature" ]; + // Signature of previous hops + neo.fs.v2.refs.Signature origin_signature = 3 + [ json_name = "originSignature" ]; + + // Chain of previous hops signatures + RequestVerificationHeader origin = 4 [ json_name = "origin" ]; +} + +// Verification info for the response signed by all intermediate nodes +message ResponseVerificationHeader { + // Response Body signature. Should be generated once by an answering node. + neo.fs.v2.refs.Signature body_signature = 1 [ json_name = "bodySignature" ]; + // Response Meta signature is added and signed by each intermediate node + neo.fs.v2.refs.Signature meta_signature = 2 [ json_name = "metaSignature" ]; + // Signature of previous hops + neo.fs.v2.refs.Signature origin_signature = 3 + [ json_name = "originSignature" ]; + + // Chain of previous hops signatures + ResponseVerificationHeader origin = 4 [ json_name = "origin" ]; +} diff --git a/protosV2/src/main/proto/status/types.proto b/protosV2/src/main/proto/status/types.proto new file mode 100644 index 0000000..b7be372 --- /dev/null +++ b/protosV2/src/main/proto/status/types.proto @@ -0,0 +1,157 @@ +syntax = "proto3"; + +package neo.fs.v2.status; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc;status"; +option java_package = "frostFS.status"; + +// Declares the general format of the status returns of the NeoFS RPC protocol. +// Status is present in all response messages. Each RPC of NeoFS protocol +// describes the possible outcomes and details of the operation. +// +// Each status is assigned a one-to-one numeric code. Any unique result of an +// operation in NeoFS is unambiguously associated with the code value. +// +// Numerical set of codes is split into 1024-element sections. An enumeration +// is defined for each section. Values can be referred to in the following ways: +// +// * numerical value ranging from 0 to 4,294,967,295 (global code); +// +// * values from enumeration (local code). The formula for the ratio of the +// local code (`L`) of a defined section (`S`) to the global one (`G`): +// `G = 1024 * S + L`. +// +// All outcomes are divided into successful and failed, which corresponds +// to the success or failure of the operation. The definition of success +// follows the semantics of RPC and the description of its purpose. +// The server must not attach code that is the opposite of the outcome type. +// +// See the set of return codes in the description for calls. +// +// Each status can carry a developer-facing error message. It should be a human +// readable text in English. The server should not transmit (and the client +// should not expect) useful information in the message. Field `details` +// should make the return more detailed. +message Status { + // The status code + uint32 code = 1; + + // Developer-facing error message + string message = 2; + + // Return detail. It contains additional information that can be used to + // analyze the response. Each code defines a set of details that can be + // attached to a status. Client should not handle details that are not + // covered by the code. + message Detail { + // Detail ID. The identifier is required to determine the binary format + // of the detail and how to decode it. + uint32 id = 1; + + // Binary status detail. Must follow the format associated with ID. + // The possibility of missing a value must be explicitly allowed. + bytes value = 2; + } + + // Data detailing the outcome of the operation. Must be unique by ID. + repeated Detail details = 3; +} + +// Section identifiers. +enum Section { + // Successful return codes. + SECTION_SUCCESS = 0; + + // Failure codes regardless of the operation. + SECTION_FAILURE_COMMON = 1; + + // Object service-specific errors. + SECTION_OBJECT = 2; + + // Container service-specific errors. + SECTION_CONTAINER = 3; + + // Session service-specific errors. + SECTION_SESSION = 4; + + // Session service-specific errors. + SECTION_APE_MANAGER = 5; +} + +// Section of NeoFS successful return codes. +enum Success { + // [**0**] Default success. Not detailed. + // If the server cannot match successful outcome to the code, it should + // use this code. + OK = 0; +} + +// Section of failed statuses independent of the operation. +enum CommonFail { + // [**1024**] Internal server error, default failure. Not detailed. + // If the server cannot match failed outcome to the code, it should + // use this code. + INTERNAL = 0; + + // [**1025**] Wrong magic of the NeoFS network. + // Details: + // - [**0**] Magic number of the served NeoFS network (big-endian 64-bit + // unsigned integer). + WRONG_MAGIC_NUMBER = 1; + + // [**1026**] Signature verification failure. + SIGNATURE_VERIFICATION_FAIL = 2; + + // [**1027**] Node is under maintenance. + NODE_UNDER_MAINTENANCE = 3; +} + +// Section of statuses for object-related operations. +enum Object { + // [**2048**] Access denied by ACL. + // Details: + // - [**0**] Human-readable description (UTF-8 encoded string). + ACCESS_DENIED = 0; + + // [**2049**] Object not found. + OBJECT_NOT_FOUND = 1; + + // [**2050**] Operation rejected by the object lock. + LOCKED = 2; + + // [**2051**] Locking an object with a non-REGULAR type rejected. + LOCK_NON_REGULAR_OBJECT = 3; + + // [**2052**] Object has been marked deleted. + OBJECT_ALREADY_REMOVED = 4; + + // [**2053**] Invalid range has been requested for an object. + OUT_OF_RANGE = 5; +} + +// Section of statuses for container-related operations. +enum Container { + // [**3072**] Container not found. + CONTAINER_NOT_FOUND = 0; + + // [**3073**] eACL table not found. + EACL_NOT_FOUND = 1; + + // [**3074**] Container access denied. + CONTAINER_ACCESS_DENIED = 2; +} + +// Section of statuses for session-related operations. +enum Session { + // [**4096**] Token not found. + TOKEN_NOT_FOUND = 0; + + // [**4097**] Token has expired. + TOKEN_EXPIRED = 1; +} + +// Section of status for APE manager related operations. +enum APEManager { + // [**5120**] The operation is denied by APE manager. + APE_MANAGER_ACCESS_DENIED = 0; +} \ No newline at end of file diff --git a/protosV2/src/main/proto/tombstone/types.proto b/protosV2/src/main/proto/tombstone/types.proto new file mode 100644 index 0000000..3e821c1 --- /dev/null +++ b/protosV2/src/main/proto/tombstone/types.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package neo.fs.v2.tombstone; + +option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/tombstone/grpc;tombstone"; +option java_package = "frostFS.tombstone"; + +import "refs/types.proto"; + +// Tombstone keeps record of deleted objects for a few epochs until they are +// purged from the NeoFS network. +message Tombstone { + // Last NeoFS epoch number of the tombstone lifetime. It's set by the + // tombstone creator depending on the current NeoFS network settings. A + // tombstone object must have the same expiration epoch value in + // `__SYSTEM__EXPIRATION_EPOCH` (`__NEOFS__EXPIRATION_EPOCH` is deprecated) + // attribute. Otherwise, the tombstone will be rejected by a storage node. + uint64 expiration_epoch = 1 [ json_name = "expirationEpoch" ]; + + // 16 byte UUID used to identify the split object hierarchy parts. Must be + // unique inside a container. All objects participating in the split must + // have the same `split_id` value. + bytes split_id = 2 [ json_name = "splitID" ]; + + // List of objects to be deleted. + repeated neo.fs.v2.refs.ObjectID members = 3 [ json_name = "members" ]; +} -- 2.45.2 From dc0eef770c922b6b81b199afbfc14238cfb56cff Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Tue, 16 Jul 2024 15:00:17 +0300 Subject: [PATCH 2/7] [#1] Refactor client structure add session logic add network logic Signed-off-by: Ori Bruk --- README.md | 4 +- client/pom.xml | 15 -- .../main/java/info/FrostFS/sdk/Client.java | 36 ----- .../java/info/FrostFS/sdk/ClientSettings.java | 57 +++++++ .../java/info/FrostFS/sdk/GrpcClient.java | 81 ++-------- .../src/main/java/info/FrostFS/sdk/Main.java | 54 +++++++ .../java/info/FrostFS/sdk/RequestSigner.java | 27 +++- .../main/java/info/FrostFS/sdk/Verifier.java | 14 +- .../FrostFS/sdk/services/ContextAccessor.java | 19 +++ .../FrostFS/sdk/services/FrostFSClient.java | 134 ++++++++++++++++ .../FrostFS/sdk/services/NetmapClient.java | 14 ++ .../FrostFS/sdk/services/SessionClient.java | 8 + .../FrostFS/sdk/services/ToolsClient.java | 8 + .../sdk/services/impl/ContainerService.java | 48 +++--- .../sdk/services/impl/FrostFSClient.java | 85 ----------- .../sdk/services/impl/NetmapService.java | 139 +++++++++++++++-- .../sdk/services/impl/ObjectService.java | 54 +++---- .../sdk/services/impl/SessionService.java | 30 ++-- .../FrostFS/sdk/tools/ClientEnvironment.java | 60 ++++++++ .../FrostFS/sdk/tools/NetworkSettings.java | 143 ++++++++++++++++++ .../info/FrostFS/sdk/jdo/SessionToken.java | 19 +++ .../sdk/jdo/netmap/NetmapSnapshot.java | 21 +++ .../info/FrostFS/sdk/jdo/netmap/NodeInfo.java | 30 +++- .../FrostFS/sdk/mappers/SessionMapper.java | 31 ++++ .../mappers/netmap/NetmapSnapshotMapper.java | 18 +++ .../sdk/mappers/netmap/NodeInfoMapper.java | 21 ++- 26 files changed, 868 insertions(+), 302 deletions(-) delete mode 100644 client/src/main/java/info/FrostFS/sdk/Client.java create mode 100644 client/src/main/java/info/FrostFS/sdk/ClientSettings.java create mode 100644 client/src/main/java/info/FrostFS/sdk/Main.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/SessionClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java delete mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java create mode 100644 client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java create mode 100644 client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java create mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java diff --git a/README.md b/README.md index 26697ca..2883006 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ import info.FrostFS.sdk.enums.BasicAcl; import info.FrostFS.sdk.jdo.Container; import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; import info.FrostFS.sdk.jdo.netmap.Replica; -import info.FrostFS.sdk.services.impl.FrostFSClient; +import info.FrostFS.sdk.services.FrostFSClient; public class ContainerExample { @@ -58,7 +58,7 @@ import info.FrostFS.sdk.jdo.ContainerId; import info.FrostFS.sdk.jdo.ObjectAttribute; import info.FrostFS.sdk.jdo.ObjectFilter; import info.FrostFS.sdk.jdo.ObjectHeader; -import info.FrostFS.sdk.services.impl.FrostFSClient; +import info.FrostFS.sdk.services.FrostFSClient; import java.io.FileInputStream; import java.io.IOException; diff --git a/client/pom.xml b/client/pom.xml index f748035..b416ee4 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -23,26 +23,11 @@ cryptography 0.1.0 - - info.FrostFS.sdk - protosV2 - 0.1.0 - info.FrostFS.sdk modelsV2 0.1.0 - - org.apache.logging.log4j - log4j-api - 2.7 - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.7 - \ No newline at end of file diff --git a/client/src/main/java/info/FrostFS/sdk/Client.java b/client/src/main/java/info/FrostFS/sdk/Client.java deleted file mode 100644 index 2d254b9..0000000 --- a/client/src/main/java/info/FrostFS/sdk/Client.java +++ /dev/null @@ -1,36 +0,0 @@ -package info.FrostFS.sdk; - -import info.FrostFS.sdk.jdo.OwnerId; -import info.FrostFS.sdk.jdo.Version; - -import static info.FrostFS.sdk.KeyExtension.getPrivateKeyFromWIF; -import static info.FrostFS.sdk.KeyExtension.loadPublicKey; - -public class Client { - private final OwnerId ownerId; - private final Version version = new Version(2, 13); - private final byte[] privateKey; - private final byte[] publicKey; - - public Client(String key) { - this.privateKey = getPrivateKeyFromWIF(key); - this.publicKey = loadPublicKey(privateKey); - this.ownerId = OwnerId.fromKey(publicKey); - } - - public OwnerId getOwnerId() { - return ownerId; - } - - public Version getVersion() { - return version; - } - - public byte[] getPrivateKey() { - return privateKey; - } - - public byte[] getPublicKey() { - return publicKey; - } -} diff --git a/client/src/main/java/info/FrostFS/sdk/ClientSettings.java b/client/src/main/java/info/FrostFS/sdk/ClientSettings.java new file mode 100644 index 0000000..3b09497 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/ClientSettings.java @@ -0,0 +1,57 @@ +package info.FrostFS.sdk; + +import io.grpc.ChannelCredentials; +import org.apache.commons.lang3.StringUtils; + +public class ClientSettings { + private static final String ERROR_TEMPLATE = "%s is required parameter."; + + public String key; + public String host; + public ChannelCredentials creds; + + public ClientSettings(String key, String host) { + this.key = key; + this.host = host; + } + + public ChannelCredentials getCreds() { + return creds; + } + + public void setCreds(ChannelCredentials creds) { + this.creds = creds; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public void validate() { + StringBuilder errorMessage = new StringBuilder(); + + if (StringUtils.isEmpty(key)) { + errorMessage.append(String.format(ERROR_TEMPLATE, "Key")).append(System.lineSeparator()); + } + + if (StringUtils.isEmpty(host)) { + errorMessage.append(String.format(ERROR_TEMPLATE, "Host")).append(System.lineSeparator()); + } + + if (errorMessage.length() != 0) { + throw new IllegalArgumentException(errorMessage.toString()); + } + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/GrpcClient.java b/client/src/main/java/info/FrostFS/sdk/GrpcClient.java index 0b32277..9062017 100644 --- a/client/src/main/java/info/FrostFS/sdk/GrpcClient.java +++ b/client/src/main/java/info/FrostFS/sdk/GrpcClient.java @@ -1,89 +1,26 @@ package info.FrostFS.sdk; -import frostFS.container.ContainerServiceGrpc; -import frostFS.netmap.NetmapServiceGrpc; -import frostFS.object.ObjectServiceGrpc; -import frostFS.session.SessionServiceGrpc; import io.grpc.Channel; -import io.grpc.netty.GrpcSslContexts; +import io.grpc.ChannelCredentials; import io.grpc.netty.NettyChannelBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import javax.net.ssl.SSLException; import java.net.URI; import java.net.URISyntaxException; +import static java.util.Objects.isNull; + public class GrpcClient { - private static final Logger log = LoggerFactory.getLogger(GrpcClient.class); - private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceBlockingClient; - private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceBlockingClient; - private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; - private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; - private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceBlockingClient; - - public GrpcClient(String host) { - Channel channel = initGrpcChannel(host); - this.containerServiceBlockingClient = ContainerServiceGrpc.newBlockingStub(channel); - this.netmapServiceBlockingClient = NetmapServiceGrpc.newBlockingStub(channel); - this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(channel); - this.objectServiceClient = ObjectServiceGrpc.newStub(channel); - this.sessionServiceBlockingClient = SessionServiceGrpc.newBlockingStub(channel); - } - - public static Channel initGrpcChannel(String host) { - URI uri; + public static Channel initGrpcChannel(String host, ChannelCredentials creds) { try { - uri = new URI(host); + URI uri = new URI(host); + var channelBuilder = isNull(creds) ? NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()) + : NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort(), creds); + + return channelBuilder.usePlaintext().build(); } catch (URISyntaxException exp) { var message = String.format("Host %s has invalid format. Error: %s", host, exp.getMessage()); - log.error(message); throw new IllegalArgumentException(message); } - - var channelBuilder = NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()) - .usePlaintext(); - - switch (uri.getScheme()) { - case "https": - try { - channelBuilder.sslContext( - GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build() - ); - } catch (SSLException e) { - throw new RuntimeException(e); - } - break; - case "http": - break; - default: - var message = String.format("Host %s has invalid URI scheme: %s", host, uri.getScheme()); - log.error(message); - throw new IllegalArgumentException(message); - } - - return channelBuilder.build(); - } - - public ContainerServiceGrpc.ContainerServiceBlockingStub getContainerServiceBlockingClient() { - return containerServiceBlockingClient; - } - - public NetmapServiceGrpc.NetmapServiceBlockingStub getNetmapServiceBlockingClient() { - return netmapServiceBlockingClient; - } - - public ObjectServiceGrpc.ObjectServiceBlockingStub getObjectServiceBlockingClient() { - return objectServiceBlockingClient; - } - - public ObjectServiceGrpc.ObjectServiceStub getObjectServiceClient() { - return objectServiceClient; - } - - public SessionServiceGrpc.SessionServiceBlockingStub getSessionServiceBlockingClient() { - return sessionServiceBlockingClient; } } diff --git a/client/src/main/java/info/FrostFS/sdk/Main.java b/client/src/main/java/info/FrostFS/sdk/Main.java new file mode 100644 index 0000000..d16f06e --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/Main.java @@ -0,0 +1,54 @@ +package info.FrostFS.sdk; + +import info.FrostFS.sdk.enums.BasicAcl; +import info.FrostFS.sdk.enums.ObjectType; +import info.FrostFS.sdk.jdo.*; +import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; +import info.FrostFS.sdk.jdo.netmap.Replica; +import info.FrostFS.sdk.services.FrostFSClient; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.List; + +public class Main { + public static void main(String[] args) throws Exception { + ClientSettings clientSettings = new ClientSettings("KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq", "http://localhost:8080"); + FrostFSClient frostFSClient = new FrostFSClient(clientSettings); +/* + var res2 = frostFSClient.searchObjectsAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); +*/ + + ObjectFrostFs res3 = frostFSClient + .getObjectAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"), new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww")); + + + var ttttt = frostFSClient.getNetworkSettingsAsync(); + Container container2 = frostFSClient.getContainerAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); + + + var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)}); + var containerId = frostFSClient.createContainerAsync(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); + Thread.sleep(1000); + + FileInputStream file = null; + try { + file = new FileInputStream("/home/ori/Desktop/cat.jpg"); + var cat = new ObjectHeader(containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")}); + frostFSClient.putObjectAsync(cat, file); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + + var res = frostFSClient.searchObjectsAsync(containerId); + + + Container container = frostFSClient.getContainerAsync(containerId); + List containerIds = frostFSClient.listContainersAsync(); +/* + frostFSClient.deleteContainerAsync(containerId); +*/ + containerIds = frostFSClient.listContainersAsync(); + System.out.println(); + } +} \ No newline at end of file diff --git a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java b/client/src/main/java/info/FrostFS/sdk/RequestSigner.java index 264d52a..962a421 100644 --- a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java +++ b/client/src/main/java/info/FrostFS/sdk/RequestSigner.java @@ -62,21 +62,27 @@ public class RequestSigner { return signature; } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, byte[] privateKey, AbstractMessage message) { + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, + byte[] privateKey, + AbstractMessage message) { return frostFS.refs.Types.SignatureRFC6979.newBuilder() .setKey(ByteString.copyFrom(publicKey)) .setSign(ByteString.copyFrom(signRFC6979(privateKey, message.toByteArray()))) .build(); } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, byte[] privateKey, ByteString data) { + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, + byte[] privateKey, + ByteString data) { return frostFS.refs.Types.SignatureRFC6979.newBuilder() .setKey(ByteString.copyFrom(publicKey)) .setSign(ByteString.copyFrom(signRFC6979(privateKey, data.toByteArray()))) .build(); } - public static frostFS.refs.Types.Signature signMessagePart(byte[] publicKey, byte[] privateKey, AbstractMessage data) { + public static frostFS.refs.Types.Signature signMessagePart(byte[] publicKey, + byte[] privateKey, + AbstractMessage data) { var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); return frostFS.refs.Types.Signature.newBuilder() @@ -101,13 +107,22 @@ public class RequestSigner { var verifyOrigin = (AbstractMessage) verify.getField(verify.getDescriptorForType().findFieldByName("origin")); if (verifyOrigin.getSerializedSize() == 0) { - verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("body_signature"), signMessagePart(publicKey, privateKey, body)); + verifyBuilder.setField( + verifyBuilder.getDescriptorForType().findFieldByName("body_signature"), + signMessagePart(publicKey, privateKey, body) + ); } else { verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin); } - verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"), signMessagePart(publicKey, privateKey, meta)); - verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"), signMessagePart(publicKey, privateKey, verifyOrigin)); + verifyBuilder.setField( + verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"), + signMessagePart(publicKey, privateKey, meta) + ); + verifyBuilder.setField( + verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"), + signMessagePart(publicKey, privateKey, verifyOrigin) + ); request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build()); } diff --git a/client/src/main/java/info/FrostFS/sdk/Verifier.java b/client/src/main/java/info/FrostFS/sdk/Verifier.java index 657be82..7a1b136 100644 --- a/client/src/main/java/info/FrostFS/sdk/Verifier.java +++ b/client/src/main/java/info/FrostFS/sdk/Verifier.java @@ -22,10 +22,12 @@ import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; public class Verifier { - public static final int RFC6979_SIGNATURE_SIZE = 64; + public static final int RFC6979_SIG_SIZE = 64; public static boolean verifyRFC6979(Types.SignatureRFC6979 signature, AbstractMessage message) { - return verifyRFC6979(signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray()); + return verifyRFC6979( + signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray() + ); } public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) { @@ -45,17 +47,17 @@ public class Verifier { } private static BigInteger[] decodeSignature(byte[] sig) { - if (sig.length != RFC6979_SIGNATURE_SIZE) { + if (sig.length != RFC6979_SIG_SIZE) { throw new IllegalArgumentException( String.format("Wrong signature size. Expected length=%s, actual=%s", - RFC6979_SIGNATURE_SIZE, sig.length) + RFC6979_SIG_SIZE, sig.length) ); } var rs = new BigInteger[2]; - rs[0] = fromUnsignedByteArray(Arrays.copyOfRange(sig, 0, (RFC6979_SIGNATURE_SIZE / 2) - 1)); - rs[1] = fromUnsignedByteArray(Arrays.copyOfRange(sig, RFC6979_SIGNATURE_SIZE / 2, RFC6979_SIGNATURE_SIZE - 1)); + rs[0] = fromUnsignedByteArray(Arrays.copyOfRange(sig, 0, (RFC6979_SIG_SIZE / 2) - 1)); + rs[1] = fromUnsignedByteArray(Arrays.copyOfRange(sig, RFC6979_SIG_SIZE / 2, RFC6979_SIG_SIZE - 1)); return rs; } diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java b/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java new file mode 100644 index 0000000..6985310 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java @@ -0,0 +1,19 @@ +package info.FrostFS.sdk.services; + +import info.FrostFS.sdk.tools.ClientEnvironment; + +public class ContextAccessor { + protected ClientEnvironment context; + + public ContextAccessor(ClientEnvironment context) { + this.context = context; + } + + public ClientEnvironment getContext() { + return context; + } + + public void setContext(ClientEnvironment context) { + this.context = context; + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java b/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java new file mode 100644 index 0000000..44a0388 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java @@ -0,0 +1,134 @@ +package info.FrostFS.sdk.services; + +import frostFS.session.Types; +import info.FrostFS.sdk.ClientSettings; +import info.FrostFS.sdk.jdo.*; +import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; +import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.services.impl.ContainerService; +import info.FrostFS.sdk.services.impl.NetmapService; +import info.FrostFS.sdk.services.impl.ObjectService; +import info.FrostFS.sdk.services.impl.SessionService; +import info.FrostFS.sdk.tools.ClientEnvironment; +import info.FrostFS.sdk.tools.NetworkSettings; +import io.grpc.Channel; + +import java.io.FileInputStream; +import java.util.List; + +import static info.FrostFS.sdk.GrpcClient.initGrpcChannel; +import static java.util.Objects.isNull; + +public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient { + private final ContainerService containerService; + private final NetmapService netmapService; + private final ObjectService objectService; + private final SessionService sessionService; + private final ClientEnvironment clientEnvironment; + + public FrostFSClient(ClientSettings clientSettings) { + if (isNull(clientSettings)) { + throw new IllegalArgumentException("Options must be initialized"); + } + + clientSettings.validate(); + Channel channel = initGrpcChannel(clientSettings.getHost(), clientSettings.getCreds()); + + this.clientEnvironment = + new ClientEnvironment(clientSettings.getKey(), channel, new Version(2, 13), this); + + this.containerService = new ContainerService(clientEnvironment); + this.netmapService = new NetmapService(clientEnvironment); + this.sessionService = new SessionService(clientEnvironment); + this.objectService = new ObjectService(clientEnvironment); + checkFrostFsVersionSupport(clientEnvironment.getVersion()); + } + + private void checkFrostFsVersionSupport(Version version) { + var localNodeInfo = netmapService.getLocalNodeInfoAsync(); + if (!localNodeInfo.getVersion().isSupported(version)) { + var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion()); + System.out.println(msg); + throw new IllegalArgumentException(msg); + } + } + + @Override + public Container getContainerAsync(ContainerId cid) { + return containerService.getContainerAsync(cid); + } + + @Override + public List listContainersAsync() { + return containerService.listContainersAsync(); + } + + @Override + public ContainerId createContainerAsync(Container container) { + return containerService.createContainerAsync(container); + } + + @Override + public void deleteContainerAsync(ContainerId cid) { + containerService.deleteContainerAsync(cid); + } + + @Override + public ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId) { + return objectService.getObjectHeadAsync(containerId, objectId); + } + + @Override + public ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId) { + return objectService.getObjectAsync(containerId, objectId); + } + + @Override + public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) { + return objectService.putObjectAsync(header, payload); + } + + @Override + public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) { + return objectService.putObjectAsync(header, payload); + } + + @Override + public void deleteObjectAsync(ContainerId containerId, ObjectId objectId) { + objectService.deleteObjectAsync(containerId, objectId); + } + + @Override + public Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters) { + return objectService.searchObjectsAsync(cid, filters); + } + + @Override + public NetmapSnapshot getNetmapSnapshotAsync() { + return netmapService.getNetmapSnapshotAsync(); + } + + @Override + public NodeInfo getLocalNodeInfoAsync() { + return netmapService.getLocalNodeInfoAsync(); + } + + @Override + public NetworkSettings getNetworkSettingsAsync() { + return netmapService.getNetworkSettingsAsync(); + } + + @Override + public SessionToken createSessionAsync(long expiration) { + return sessionService.createSessionAsync(expiration); + } + + public Types.SessionToken createSessionInternalAsync(long expiration) { + return sessionService.createSessionInternalAsync(expiration); + } + + @Override + public ObjectId CalculateObjectId(ObjectHeader header) { + return null; + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java new file mode 100644 index 0000000..f6e9401 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java @@ -0,0 +1,14 @@ +package info.FrostFS.sdk.services; + +import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; +import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.tools.NetworkSettings; + +public interface NetmapClient { + + NetmapSnapshot getNetmapSnapshotAsync(); + + NodeInfo getLocalNodeInfoAsync(); + + NetworkSettings getNetworkSettingsAsync(); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java b/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java new file mode 100644 index 0000000..ffd1f0a --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java @@ -0,0 +1,8 @@ +package info.FrostFS.sdk.services; + +import info.FrostFS.sdk.jdo.SessionToken; + +public interface SessionClient { + + SessionToken createSessionAsync(long expiration); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java b/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java new file mode 100644 index 0000000..62dffc2 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java @@ -0,0 +1,8 @@ +package info.FrostFS.sdk.services; + +import info.FrostFS.sdk.jdo.ObjectHeader; +import info.FrostFS.sdk.jdo.ObjectId; + +public interface ToolsClient { + ObjectId CalculateObjectId(ObjectHeader header); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java index 782c218..824f967 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java @@ -2,7 +2,6 @@ package info.FrostFS.sdk.services.impl; import frostFS.container.ContainerServiceGrpc; import frostFS.container.Service; -import info.FrostFS.sdk.Client; import info.FrostFS.sdk.Verifier; import info.FrostFS.sdk.jdo.Container; import info.FrostFS.sdk.jdo.ContainerId; @@ -11,6 +10,8 @@ import info.FrostFS.sdk.mappers.ContainerMapper; import info.FrostFS.sdk.mappers.OwnerIdMapper; import info.FrostFS.sdk.mappers.VersionMapper; import info.FrostFS.sdk.services.ContainerClient; +import info.FrostFS.sdk.services.ContextAccessor; +import info.FrostFS.sdk.tools.ClientEnvironment; import java.util.List; import java.util.stream.Collectors; @@ -19,23 +20,24 @@ import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; import static info.FrostFS.sdk.RequestSigner.sign; import static info.FrostFS.sdk.RequestSigner.signRFC6979; -public class ContainerService implements ContainerClient { +public class ContainerService extends ContextAccessor implements ContainerClient { private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient; - private final Client client; - public ContainerService(ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient, Client client) { - this.containerServiceAsyncClient = containerServiceAsyncClient; - this.client = client; + public ContainerService(ClientEnvironment clientEnvironment) { + super(clientEnvironment); + this.containerServiceAsyncClient = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel()); } public Container getContainerAsync(ContainerId cid) { var request = Service.GetRequest.newBuilder() .setBody( - Service.GetRequest.Body.newBuilder().setContainerId(ContainerIdMapper.toGrpcMessage(cid)).build() + Service.GetRequest.Body.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .build() ); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var response = containerServiceAsyncClient.get(request.build()); @@ -46,11 +48,13 @@ public class ContainerService implements ContainerClient { public List listContainersAsync() { var request = Service.ListRequest.newBuilder() .setBody( - Service.ListRequest.Body.newBuilder().setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())).build() + Service.ListRequest.Body.newBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) + .build() ); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var response = containerServiceAsyncClient.list(request.build()); @@ -65,20 +69,22 @@ public class ContainerService implements ContainerClient { var grpcContainer = ContainerMapper.toGrpcMessage(container); grpcContainer = grpcContainer.toBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())) - .setVersion(VersionMapper.toGrpcMessage(client.getVersion())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(context.getVersion())) .build(); var request = Service.PutRequest.newBuilder() .setBody( Service.PutRequest.Body.newBuilder() .setContainer(grpcContainer) - .setSignature(signRFC6979(client.getPublicKey(), client.getPrivateKey(), grpcContainer)) + .setSignature( + signRFC6979(context.getPublicKey(), context.getPrivateKey(), grpcContainer) + ) .build() ); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var response = containerServiceAsyncClient.put(request.build()); @@ -93,12 +99,14 @@ public class ContainerService implements ContainerClient { .setBody( Service.DeleteRequest.Body.newBuilder() .setContainerId(grpcContainerId) - .setSignature(signRFC6979(client.getPublicKey(), client.getPrivateKey(), grpcContainerId.getValue())) + .setSignature(signRFC6979( + context.getPublicKey(), context.getPrivateKey(), grpcContainerId.getValue() + )) .build() ); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var response = containerServiceAsyncClient.delete(request.build()); diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java b/client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java deleted file mode 100644 index a720d4c..0000000 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/FrostFSClient.java +++ /dev/null @@ -1,85 +0,0 @@ -package info.FrostFS.sdk.services.impl; - -import info.FrostFS.sdk.Client; -import info.FrostFS.sdk.GrpcClient; -import info.FrostFS.sdk.jdo.*; -import info.FrostFS.sdk.services.ContainerClient; -import info.FrostFS.sdk.services.ObjectClient; - -import java.io.FileInputStream; -import java.util.List; - -public class FrostFSClient implements ContainerClient, ObjectClient { - private final ContainerService containerService; - private final NetmapService netmapService; - private final ObjectService objectService; - - public FrostFSClient(GrpcClient grpcClient, Client client) { - this.containerService = new ContainerService(grpcClient.getContainerServiceBlockingClient(), client); - this.netmapService = new NetmapService(grpcClient.getNetmapServiceBlockingClient(), client); - SessionService sessionService = new SessionService(grpcClient.getSessionServiceBlockingClient(), client); - this.objectService = new ObjectService( - grpcClient.getObjectServiceBlockingClient(), grpcClient.getObjectServiceClient(), sessionService, client - ); - checkFrostFsVersionSupport(client); - } - - private void checkFrostFsVersionSupport(Client client) { - var localNodeInfo = netmapService.getLocalNodeInfoAsync(); - if (!localNodeInfo.getVersion().isSupported(client.getVersion())) { - var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion()); - System.out.println(msg); - throw new IllegalArgumentException(msg); - } - } - - @Override - public Container getContainerAsync(ContainerId cid) { - return containerService.getContainerAsync(cid); - } - - @Override - public List listContainersAsync() { - return containerService.listContainersAsync(); - } - - @Override - public ContainerId createContainerAsync(Container container) { - return containerService.createContainerAsync(container); - } - - @Override - public void deleteContainerAsync(ContainerId cid) { - containerService.deleteContainerAsync(cid); - } - - @Override - public ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId) { - return objectService.getObjectHeadAsync(containerId, objectId); - } - - @Override - public ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId) { - return objectService.getObjectAsync(containerId, objectId); - } - - @Override - public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) { - return objectService.putObjectAsync(header, payload); - } - - @Override - public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) { - return objectService.putObjectAsync(header, payload); - } - - @Override - public void deleteObjectAsync(ContainerId containerId, ObjectId objectId) { - objectService.deleteObjectAsync(containerId, objectId); - } - - @Override - public Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters) { - return objectService.searchObjectsAsync(cid, filters); - } -} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java index eafc40f..b2ccf23 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java @@ -2,30 +2,124 @@ package info.FrostFS.sdk.services.impl; import frostFS.netmap.NetmapServiceGrpc; import frostFS.netmap.Service; -import info.FrostFS.sdk.Client; +import frostFS.netmap.Types; +import info.FrostFS.sdk.Verifier; +import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper; import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper; +import info.FrostFS.sdk.services.ContextAccessor; +import info.FrostFS.sdk.services.NetmapClient; +import info.FrostFS.sdk.tools.ClientEnvironment; +import info.FrostFS.sdk.tools.NetworkSettings; + +import java.nio.charset.StandardCharsets; import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; import static info.FrostFS.sdk.RequestSigner.sign; +import static java.util.Objects.nonNull; -public class NetmapService { - private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceAsyncClient; - private final Client client; +public class NetmapService extends ContextAccessor implements NetmapClient { + private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceClient; - public NetmapService(NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceAsyncClient, Client client) { - this.netmapServiceAsyncClient = netmapServiceAsyncClient; - this.client = client; + public NetmapService(ClientEnvironment clientEnvironment) { + super(clientEnvironment); + this.netmapServiceClient = NetmapServiceGrpc.newBlockingStub(context.getChannel()); } + private static boolean getBoolValue(byte[] bytes) { + for (var byteValue : bytes) { + if (byteValue != 0) return true; + } + + return false; + } + + private static long getLongValue(byte[] bytes) { + long val = 0; + for (var i = bytes.length - 1; i >= 0; i--) { + val = (val << 8) + bytes[i]; + } + + return val; + } + + private static void setNetworksParam(Types.NetworkConfig.Parameter param, NetworkSettings settings) { + var key = new String(param.getKey().toByteArray(), StandardCharsets.UTF_8); + + var valueBytes = param.getValue().toByteArray(); + switch (key) { + case "AuditFee": + settings.setAuditFee(getLongValue(valueBytes)); + break; + case "BasicIncomeRate": + settings.setBasicIncomeRate(getLongValue(valueBytes)); + break; + case "ContainerFee": + settings.setContainerFee(getLongValue(valueBytes)); + break; + case "ContainerAliasFee": + settings.setContainerAliasFee(getLongValue(valueBytes)); + break; + case "EpochDuration": + settings.setEpochDuration(getLongValue(valueBytes)); + break; + case "InnerRingCandidateFee": + settings.setiRCandidateFee(getLongValue(valueBytes)); + break; + case "MaxECDataCount": + settings.setMaxECDataCount(getLongValue(valueBytes)); + break; + case "MaxECParityCount": + settings.setMaxECParityCount(getLongValue(valueBytes)); + break; + case "MaxObjectSize": + settings.setMaxObjectSize(getLongValue(valueBytes)); + break; + case "WithdrawFee": + settings.setWithdrawalFee(getLongValue(valueBytes)); + break; + case "HomomorphicHashingDisabled": + settings.setHomomorphicHashingDisabled(getBoolValue(valueBytes)); + break; + case "MaintenanceModeAllowed": + settings.setMaintenanceModeAllowed(getBoolValue(valueBytes)); + break; + default: + settings.getUnnamedSettings().put(key, valueBytes); + break; + } + } + + @Override + public NetworkSettings getNetworkSettingsAsync() { + if (nonNull(context.getNetworkSettings())) { + return context.getNetworkSettings(); + } + + var info = getNetworkInfoAsync(); + + var settings = new NetworkSettings(); + + for (var param : info.getBody().getNetworkInfo().getNetworkConfig().getParametersList()) { + setNetworksParam(param, settings); + } + + context.setNetworkSettings(settings); + + return settings; + } + + @Override public NodeInfo getLocalNodeInfoAsync() { var request = Service.LocalNodeInfoRequest.newBuilder() .setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build()); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); - var response = netmapServiceAsyncClient.localNodeInfo(request.build()); + var response = netmapServiceClient.localNodeInfo(request.build()); + Verifier.checkResponse(response); return NodeInfoMapper.toModel(response.getBody()); } @@ -34,9 +128,28 @@ public class NetmapService { var request = Service.NetworkInfoRequest.newBuilder() .setBody(Service.NetworkInfoRequest.Body.newBuilder().build()); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); - return netmapServiceAsyncClient.networkInfo(request.build()); + var response = netmapServiceClient.networkInfo(request.build()); + + Verifier.checkResponse(response); + + return response; + } + + @Override + public NetmapSnapshot getNetmapSnapshotAsync() { + var request = Service.NetmapSnapshotRequest.newBuilder() + .setBody(Service.NetmapSnapshotRequest.Body.newBuilder().build()); + + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); + + var response = netmapServiceClient.netmapSnapshot(request.build()); + + Verifier.checkResponse(response); + + return NetmapSnapshotMapper.toModel(response); } } diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java index f90fe84..9ef6a6d 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java @@ -5,11 +5,12 @@ import com.google.protobuf.ByteString; import frostFS.object.ObjectServiceGrpc; import frostFS.object.Service; import frostFS.refs.Types; -import info.FrostFS.sdk.Client; import info.FrostFS.sdk.Verifier; import info.FrostFS.sdk.jdo.*; import info.FrostFS.sdk.mappers.*; +import info.FrostFS.sdk.services.ContextAccessor; import info.FrostFS.sdk.services.ObjectClient; +import info.FrostFS.sdk.tools.ClientEnvironment; import java.io.ByteArrayInputStream; import java.io.FileInputStream; @@ -25,21 +26,14 @@ import static info.FrostFS.sdk.RequestConstructor.addObjectSessionToken; import static info.FrostFS.sdk.RequestSigner.sign; import static java.util.Objects.nonNull; -public class ObjectService implements ObjectClient { +public class ObjectService extends ContextAccessor implements ObjectClient { private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; - private final SessionService sessionService; - private final Client client; - - public ObjectService(ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceAsyncClient, - ObjectServiceGrpc.ObjectServiceStub objectServiceClient, - SessionService sessionService, - Client client) { - this.objectServiceBlockingClient = objectServiceAsyncClient; - this.objectServiceClient = objectServiceClient; - this.client = client; - this.sessionService = sessionService; + public ObjectService(ClientEnvironment clientEnvironment) { + super(clientEnvironment); + this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(context.getChannel()); + this.objectServiceClient = ObjectServiceGrpc.newStub(context.getChannel()); } @Override @@ -55,8 +49,8 @@ public class ObjectService implements ObjectClient { ).build() ); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var response = objectServiceBlockingClient.head(request.build()); Verifier.checkResponse(response); @@ -66,7 +60,7 @@ public class ObjectService implements ObjectClient { @Override public ObjectFrostFs getObjectAsync(ContainerId cid, ObjectId oid) { - var sessionToken = sessionService.createSessionAsync(-1); + var sessionToken = context.getFrostFSClient().createSessionInternalAsync(-1); var request = Service.GetRequest.newBuilder() .setBody( @@ -81,12 +75,12 @@ public class ObjectService implements ObjectClient { .build() ); - addMetaHeader(request, null); + addMetaHeader(request); addObjectSessionToken( request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid), - frostFS.session.Types.ObjectSessionContext.Verb.GET, client.getPublicKey(), client.getPrivateKey() + frostFS.session.Types.ObjectSessionContext.Verb.GET, context.getPublicKey(), context.getPrivateKey() ); - sign(request, client.getPublicKey(), client.getPrivateKey()); + sign(request, context.getPublicKey(), context.getPrivateKey()); var obj = getObject(request.build()); @@ -106,8 +100,8 @@ public class ObjectService implements ObjectClient { ) .build()); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var response = objectServiceBlockingClient.delete(request.build()); Verifier.checkResponse(response); @@ -136,8 +130,8 @@ public class ObjectService implements ObjectClient { var request = Service.SearchRequest.newBuilder() .setBody(body.build()); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); var objectsIds = searchObjects(request.build()); @@ -169,12 +163,12 @@ public class ObjectService implements ObjectClient { } private ObjectId putObject(ObjectHeader header, InputStream payload) { - var sessionToken = sessionService.createSessionAsync(-1); + var sessionToken = context.getFrostFSClient().createSessionInternalAsync(-1); var hdr = ObjectHeaderMapper.toGrpcMessage(header); hdr = hdr.toBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())) - .setVersion(VersionMapper.toGrpcMessage(client.getVersion())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(context.getVersion())) .build(); var oid = Types.ObjectID.newBuilder().setValue(getSha256(hdr)).build(); @@ -187,12 +181,12 @@ public class ObjectService implements ObjectClient { ).build() ); - addMetaHeader(request, null); + addMetaHeader(request); addObjectSessionToken( request, sessionToken, hdr.getContainerId(), oid, frostFS.session.Types.ObjectSessionContext.Verb.PUT, - client.getPublicKey(), client.getPrivateKey() + context.getPublicKey(), context.getPrivateKey() ); - sign(request, client.getPublicKey(), client.getPrivateKey()); + sign(request, context.getPublicKey(), context.getPrivateKey()); var writer = putObjectInit(request.build()); @@ -208,7 +202,7 @@ public class ObjectService implements ObjectClient { .build() ) .clearVerifyHeader(); - sign(request, client.getPublicKey(), client.getPrivateKey()); + sign(request, context.getPublicKey(), context.getPrivateKey()); writer.write(request.build()); bufferLength = payload.readNBytes(buffer, 0, Constants.OBJECT_CHUNK_SIZE); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java index 832dc52..3406acf 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java @@ -3,31 +3,41 @@ package info.FrostFS.sdk.services.impl; import frostFS.session.Service; import frostFS.session.SessionServiceGrpc; import frostFS.session.Types; -import info.FrostFS.sdk.Client; +import info.FrostFS.sdk.jdo.SessionToken; import info.FrostFS.sdk.mappers.OwnerIdMapper; +import info.FrostFS.sdk.mappers.SessionMapper; +import info.FrostFS.sdk.services.ContextAccessor; +import info.FrostFS.sdk.services.SessionClient; +import info.FrostFS.sdk.tools.ClientEnvironment; import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; import static info.FrostFS.sdk.RequestSigner.sign; -public class SessionService { +public class SessionService extends ContextAccessor implements SessionClient { private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient; - private final Client client; - public SessionService(SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient, Client client) { - this.sessionServiceAsyncClient = sessionServiceAsyncClient; - this.client = client; + public SessionService(ClientEnvironment clientEnvironment) { + super(clientEnvironment); + this.sessionServiceAsyncClient = SessionServiceGrpc.newBlockingStub(context.getChannel()); } - protected Types.SessionToken createSessionAsync(long expiration) { + @Override + public SessionToken createSessionAsync(long expiration) { + var sessionToken = createSessionInternalAsync(expiration); + var token = SessionMapper.serialize(sessionToken); + return new SessionToken(new byte[]{}, token); + } + + public Types.SessionToken createSessionInternalAsync(long expiration) { var request = Service.CreateRequest.newBuilder() .setBody( Service.CreateRequest.Body.newBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(client.getOwnerId())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) .setExpiration(expiration).build() ); - addMetaHeader(request, null); - sign(request, client.getPublicKey(), client.getPrivateKey()); + addMetaHeader(request); + sign(request, context.getPublicKey(), context.getPrivateKey()); return createSession(request.build()); } diff --git a/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java b/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java new file mode 100644 index 0000000..93019ca --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java @@ -0,0 +1,60 @@ +package info.FrostFS.sdk.tools; + +import info.FrostFS.sdk.jdo.OwnerId; +import info.FrostFS.sdk.jdo.Version; +import info.FrostFS.sdk.services.FrostFSClient; +import io.grpc.Channel; + +import static info.FrostFS.sdk.KeyExtension.getPrivateKeyFromWIF; +import static info.FrostFS.sdk.KeyExtension.loadPublicKey; + +public class ClientEnvironment { + private final OwnerId ownerId; + private final Version version; + private final byte[] privateKey; + private final byte[] publicKey; + private final Channel channel; + private final FrostFSClient frostFSClient; + private NetworkSettings networkSettings; + + public ClientEnvironment(String key, Channel channel, Version version, FrostFSClient frostFSClient) { + this.privateKey = getPrivateKeyFromWIF(key); + this.publicKey = loadPublicKey(privateKey); + this.ownerId = OwnerId.fromKey(publicKey); + this.version = version; + this.channel = channel; + this.frostFSClient = frostFSClient; + } + + public Channel getChannel() { + return channel; + } + + public NetworkSettings getNetworkSettings() { + return networkSettings; + } + + public void setNetworkSettings(NetworkSettings networkSettings) { + this.networkSettings = networkSettings; + } + + public FrostFSClient getFrostFSClient() { + return frostFSClient; + } + + public OwnerId getOwnerId() { + return ownerId; + } + + public Version getVersion() { + return version; + } + + public byte[] getPrivateKey() { + return privateKey; + } + + public byte[] getPublicKey() { + return publicKey; + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java b/client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java new file mode 100644 index 0000000..d6971b3 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java @@ -0,0 +1,143 @@ +package info.FrostFS.sdk.tools; + +import java.util.HashMap; +import java.util.Map; + +public class NetworkSettings { + + public Long auditFee; + public Long basicIncomeRate; + public Long containerFee; + public Long containerAliasFee; + public Long innerRingCandidateFee; + public Long withdrawFee; + public Long epochDuration; + public Long iRCandidateFee; + public Long maxObjectSize; + public Long maxECDataCount; + public Long maxECParityCount; + public Long withdrawalFee; + public Boolean homomorphicHashingDisabled; + public Boolean maintenanceModeAllowed; + public Map unnamedSettings = new HashMap<>(); + + public Long getAuditFee() { + return auditFee; + } + + public void setAuditFee(Long auditFee) { + this.auditFee = auditFee; + } + + public Long getBasicIncomeRate() { + return basicIncomeRate; + } + + public void setBasicIncomeRate(Long basicIncomeRate) { + this.basicIncomeRate = basicIncomeRate; + } + + public long getContainerFee() { + return containerFee; + } + + public void setContainerFee(long containerFee) { + this.containerFee = containerFee; + } + + public long getContainerAliasFee() { + return containerAliasFee; + } + + public void setContainerAliasFee(long containerAliasFee) { + this.containerAliasFee = containerAliasFee; + } + + public long getInnerRingCandidateFee() { + return innerRingCandidateFee; + } + + public void setInnerRingCandidateFee(long innerRingCandidateFee) { + this.innerRingCandidateFee = innerRingCandidateFee; + } + + public long getWithdrawFee() { + return withdrawFee; + } + + public void setWithdrawFee(long withdrawFee) { + this.withdrawFee = withdrawFee; + } + + public long getEpochDuration() { + return epochDuration; + } + + public void setEpochDuration(long epochDuration) { + this.epochDuration = epochDuration; + } + + public long getiRCandidateFee() { + return iRCandidateFee; + } + + public void setiRCandidateFee(long iRCandidateFee) { + this.iRCandidateFee = iRCandidateFee; + } + + public long getMaxObjectSize() { + return maxObjectSize; + } + + public void setMaxObjectSize(long maxObjectSize) { + this.maxObjectSize = maxObjectSize; + } + + public long getMaxECDataCount() { + return maxECDataCount; + } + + public void setMaxECDataCount(long maxECDataCount) { + this.maxECDataCount = maxECDataCount; + } + + public long getMaxECParityCount() { + return maxECParityCount; + } + + public void setMaxECParityCount(long maxECParityCount) { + this.maxECParityCount = maxECParityCount; + } + + public long getWithdrawalFee() { + return withdrawalFee; + } + + public void setWithdrawalFee(long withdrawalFee) { + this.withdrawalFee = withdrawalFee; + } + + public boolean isHomomorphicHashingDisabled() { + return homomorphicHashingDisabled; + } + + public void setHomomorphicHashingDisabled(boolean homomorphicHashingDisabled) { + this.homomorphicHashingDisabled = homomorphicHashingDisabled; + } + + public boolean isMaintenanceModeAllowed() { + return maintenanceModeAllowed; + } + + public void setMaintenanceModeAllowed(boolean maintenanceModeAllowed) { + this.maintenanceModeAllowed = maintenanceModeAllowed; + } + + public Map getUnnamedSettings() { + return unnamedSettings; + } + + public void setUnnamedSettings(Map unnamedSettings) { + this.unnamedSettings = unnamedSettings; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java new file mode 100644 index 0000000..bd4f7b0 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java @@ -0,0 +1,19 @@ +package info.FrostFS.sdk.jdo; + +public class SessionToken { + public byte[] id; + public byte[] sessionKey; + + public SessionToken(byte[] id, byte[] sessionKey) { + this.id = id; + this.sessionKey = sessionKey; + } + + public byte[] getId() { + return id; + } + + public byte[] getSessionKey() { + return sessionKey; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java new file mode 100644 index 0000000..7fd344e --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java @@ -0,0 +1,21 @@ +package info.FrostFS.sdk.jdo.netmap; + +import java.util.List; + +public class NetmapSnapshot { + public Long epoch; + public List nodeInfoCollection; + + public NetmapSnapshot(Long epoch, List nodeInfoCollection) { + this.epoch = epoch; + this.nodeInfoCollection = nodeInfoCollection; + } + + public Long getEpoch() { + return epoch; + } + + public List getNodeInfoCollection() { + return nodeInfoCollection; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java index fe65459..5b060f1 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java +++ b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java @@ -1,11 +1,26 @@ package info.FrostFS.sdk.jdo.netmap; -import info.FrostFS.sdk.jdo.Version; import info.FrostFS.sdk.enums.NodeState; +import info.FrostFS.sdk.jdo.Version; + +import java.util.List; +import java.util.Map; public class NodeInfo { public NodeState state; public Version version; + public List addresses; + public Map attributes; + public byte[] publicKey; + + public NodeInfo(NodeState state, Version version, List addresses, + Map attributes, byte[] publicKey) { + this.state = state; + this.version = version; + this.addresses = addresses; + this.attributes = attributes; + this.publicKey = publicKey; + } public NodeState getState() { return state; @@ -23,8 +38,15 @@ public class NodeInfo { this.version = version; } - public NodeInfo(NodeState state, Version version) { - this.state = state; - this.version = version; + public byte[] getPublicKey() { + return publicKey; + } + + public Map getAttributes() { + return attributes; + } + + public List getAddresses() { + return addresses; } } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java new file mode 100644 index 0000000..f9d7ecd --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java @@ -0,0 +1,31 @@ +package info.FrostFS.sdk.mappers; + +import com.google.protobuf.CodedOutputStream; +import com.google.protobuf.InvalidProtocolBufferException; +import frostFS.session.Types; + +import java.io.IOException; + +public class SessionMapper { + + public static byte[] serialize(Types.SessionToken token) + { + try { + byte[] bytes = new byte[token.getSerializedSize()]; + CodedOutputStream stream = CodedOutputStream.newInstance(bytes); + token.writeTo(stream); + return bytes; + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + public static Types.SessionToken deserializeSessionToken(byte[] bytes) + { + try { + return Types.SessionToken.newBuilder().mergeFrom(bytes).build(); + } catch (InvalidProtocolBufferException exp) { + throw new IllegalArgumentException(); + } + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java new file mode 100644 index 0000000..9d9eb27 --- /dev/null +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java @@ -0,0 +1,18 @@ +package info.FrostFS.sdk.mappers.netmap; + +import frostFS.netmap.Service; +import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; + +import java.util.stream.Collectors; + +public class NetmapSnapshotMapper { + + public static NetmapSnapshot toModel(Service.NetmapSnapshotResponse netmap) { + return new NetmapSnapshot( + netmap.getBody().getNetmap().getEpoch(), + netmap.getBody().getNetmap().getNodesList().stream() + .map(t -> NodeInfoMapper.toModel(t, netmap.getMetaHeader().getVersion())) + .collect(Collectors.toList()) + ); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java index 934d60f..6c9e25c 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java +++ b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java @@ -1,21 +1,36 @@ package info.FrostFS.sdk.mappers.netmap; import frostFS.netmap.Service; +import frostFS.netmap.Types.NodeInfo.Attribute; +import frostFS.refs.Types; import info.FrostFS.sdk.enums.NodeState; import info.FrostFS.sdk.jdo.netmap.NodeInfo; import info.FrostFS.sdk.mappers.VersionMapper; +import java.util.stream.Collectors; + import static java.util.Objects.isNull; public class NodeInfoMapper { public static NodeInfo toModel(Service.LocalNodeInfoResponse.Body nodeInfo) { - var nodeState = NodeState.get(nodeInfo.getNodeInfo().getState().getNumber()); + return toModel(nodeInfo.getNodeInfo(), nodeInfo.getVersion()); + } + + public static NodeInfo toModel(frostFS.netmap.Types.NodeInfo nodeInfo, Types.Version version) { + NodeState nodeState = NodeState.get(nodeInfo.getState().getNumber()); + if (isNull(nodeState)) { throw new IllegalArgumentException( - String.format("Unknown NodeState. Value: %s.", nodeInfo.getNodeInfo().getState()) + String.format("Unknown NodeState. Value: %s.", nodeInfo.getState()) ); } - return new NodeInfo(nodeState, VersionMapper.toModel(nodeInfo.getVersion())); + return new NodeInfo( + nodeState, + VersionMapper.toModel(version), + nodeInfo.getAddressesList(), + nodeInfo.getAttributesList().stream().collect(Collectors.toMap(Attribute::getKey, Attribute::getValue)), + nodeInfo.getPublicKey().toByteArray() + ); } } -- 2.45.2 From b0db7df192e975da5da5629a524ca295053ddbc5 Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Mon, 22 Jul 2024 19:13:52 +0300 Subject: [PATCH 3/7] [#1] add client environment add client cut code cleanup Signed-off-by: Ori Bruk --- README.md | 32 +-- client/pom.xml | 12 +- .../src/main/java/info/FrostFS/sdk/Main.java | 51 ++-- .../info/FrostFS/sdk/RequestConstructor.java | 7 +- .../java/info/FrostFS/sdk/RequestSigner.java | 43 ++-- .../main/java/info/FrostFS/sdk/Verifier.java | 4 +- .../FrostFS/sdk/services/ContainerClient.java | 12 +- .../FrostFS/sdk/services/ContextAccessor.java | 6 +- .../FrostFS/sdk/services/FrostFSClient.java | 99 ++++---- .../FrostFS/sdk/services/NetmapClient.java | 11 +- .../FrostFS/sdk/services/ObjectClient.java | 21 +- .../FrostFS/sdk/services/SessionClient.java | 5 +- .../FrostFS/sdk/services/ToolsClient.java | 6 +- .../sdk/services/impl/ContainerService.java | 46 ++-- .../sdk/services/impl/NetmapService.java | 28 +-- .../sdk/services/impl/ObjectService.java | 228 +++++++++++++----- .../sdk/services/impl/ObjectTools.java | 106 ++++++++ .../sdk/services/impl/SessionService.java | 18 +- .../FrostFS/sdk/tools/ClientEnvironment.java | 25 +- .../sdk/{ => tools}/ClientSettings.java | 2 +- .../java/info/FrostFS/sdk/tools/ECDsa.java | 29 +++ .../sdk/tools/PutObjectParameters.java | 76 ++++++ cryptography/pom.xml | 10 - .../main/java/info/FrostFS/sdk/Helper.java | 10 +- .../java/info/FrostFS/sdk/KeyExtension.java | 18 +- {modelsV2 => models}/pom.xml | 4 +- .../java/info/FrostFS/sdk/UUIDExtension.java | 0 .../info/FrostFS/sdk/constants/AppConst.java | 4 +- .../FrostFS/sdk/constants/XHeaderConst.java | 0 .../info/FrostFS/sdk/dto}/MetaHeader.java | 8 +- .../java/info/FrostFS/sdk/dto}/OwnerId.java | 2 +- .../info/FrostFS/sdk/dto}/SessionToken.java | 6 +- .../java/info/FrostFS/sdk/dto/Signature.java | 33 +++ .../main/java/info/FrostFS/sdk/dto/Split.java | 69 ++++++ .../java/info/FrostFS/sdk/dto/SplitId.java | 44 ++++ .../java/info/FrostFS/sdk/dto}/Status.java | 12 +- .../java/info/FrostFS/sdk/dto}/Version.java | 16 +- .../FrostFS/sdk/dto/container}/Container.java | 32 +-- .../sdk/dto/container}/ContainerId.java | 7 +- .../sdk/dto}/netmap/NetmapSnapshot.java | 6 +- .../FrostFS/sdk/dto}/netmap/NodeInfo.java | 22 +- .../sdk/dto}/netmap/PlacementPolicy.java | 14 +- .../info/FrostFS/sdk/dto}/netmap/Replica.java | 10 +- .../FrostFS/sdk/dto/object/LargeObject.java | 29 +++ .../FrostFS/sdk/dto/object/LinkObject.java | 21 ++ .../sdk/dto/object}/ObjectAttribute.java | 6 +- .../FrostFS/sdk/dto/object}/ObjectFilter.java | 14 +- .../FrostFS/sdk/dto/object/ObjectFrostFS.java | 80 ++++++ .../FrostFS/sdk/dto/object/ObjectHeader.java | 118 +++++++++ .../FrostFS/sdk/dto/object}/ObjectId.java | 7 +- .../java/info/FrostFS/sdk/enums/BasicAcl.java | 2 +- .../info/FrostFS/sdk/enums/NodeState.java | 0 .../FrostFS/sdk/enums/ObjectMatchType.java | 0 .../info/FrostFS/sdk/enums/ObjectType.java | 0 .../FrostFS/sdk/enums/SignatureScheme.java | 14 ++ .../info/FrostFS/sdk/enums/StatusCode.java | 0 .../FrostFS/sdk/mappers/MetaHeaderMapper.java | 2 +- .../FrostFS/sdk/mappers/OwnerIdMapper.java | 3 +- .../FrostFS/sdk/mappers/SessionMapper.java | 12 +- .../FrostFS/sdk/mappers/SignatureMapper.java | 25 ++ .../FrostFS/sdk/mappers/StatusMapper.java | 4 +- .../FrostFS/sdk/mappers/VersionMapper.java | 2 +- .../mappers/container}/ContainerIdMapper.java | 6 +- .../mappers/container}/ContainerMapper.java | 22 +- .../mappers/netmap/NetmapSnapshotMapper.java | 4 +- .../sdk/mappers/netmap/NodeInfoMapper.java | 4 +- .../mappers/netmap/PlacementPolicyMapper.java | 5 +- .../sdk/mappers/netmap/ReplicaMapper.java | 3 +- .../object}/ObjectAttributeMapper.java | 5 +- .../mappers/object}/ObjectFilterMapper.java | 6 +- .../mappers/object/ObjectFrostFSMapper.java | 16 ++ .../mappers/object}/ObjectHeaderMapper.java | 18 +- .../sdk/mappers/object}/ObjectIdMapper.java | 9 +- .../info/FrostFS/sdk/jdo/ObjectFrostFs.java | 37 --- .../info/FrostFS/sdk/jdo/ObjectHeader.java | 71 ------ .../FrostFS/sdk/mappers/ObjectMapper.java | 15 -- pom.xml | 4 +- {protosV2 => protos}/pom.xml | 4 +- .../src/main/proto/accounting/service.proto | 0 .../src/main/proto/accounting/types.proto | 0 .../src/main/proto/acl/types.proto | 0 .../src/main/proto/apemanager/service.proto | 0 .../src/main/proto/apemanager/types.proto | 0 .../src/main/proto/container/service.proto | 0 .../src/main/proto/container/types.proto | 0 .../src/main/proto/lock/types.proto | 0 .../src/main/proto/netmap/service.proto | 0 .../src/main/proto/netmap/types.proto | 0 .../src/main/proto/object/service.proto | 0 .../src/main/proto/object/types.proto | 0 .../src/main/proto/refs/types.proto | 0 .../src/main/proto/session/service.proto | 0 .../src/main/proto/session/types.proto | 0 .../src/main/proto/status/types.proto | 0 .../src/main/proto/tombstone/types.proto | 0 95 files changed, 1202 insertions(+), 560 deletions(-) create mode 100644 client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java rename client/src/main/java/info/FrostFS/sdk/{ => tools}/ClientSettings.java (97%) create mode 100644 client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java create mode 100644 client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java rename {modelsV2 => models}/pom.xml (93%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/UUIDExtension.java (100%) rename modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java => models/src/main/java/info/FrostFS/sdk/constants/AppConst.java (66%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java (100%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/MetaHeader.java (86%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/OwnerId.java (94%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/SessionToken.java (74%) create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/Signature.java create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/Split.java create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/SplitId.java rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/Status.java (71%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/Version.java (88%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto/container}/Container.java (64%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto/container}/ContainerId.java (78%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/netmap/NetmapSnapshot.java (75%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/netmap/NodeInfo.java (66%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/netmap/PlacementPolicy.java (52%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto}/netmap/Replica.java (72%) create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto/object}/ObjectAttribute.java (82%) rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto/object}/ObjectFilter.java (82%) create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java create mode 100644 models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java rename {modelsV2/src/main/java/info/FrostFS/sdk/jdo => models/src/main/java/info/FrostFS/sdk/dto/object}/ObjectId.java (75%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java (93%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/enums/NodeState.java (100%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java (100%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/enums/ObjectType.java (100%) create mode 100644 models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/enums/StatusCode.java (100%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java (91%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java (89%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java (73%) create mode 100644 models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java (94%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java (92%) rename {modelsV2/src/main/java/info/FrostFS/sdk/mappers => models/src/main/java/info/FrostFS/sdk/mappers/container}/ContainerIdMapper.java (73%) rename {modelsV2/src/main/java/info/FrostFS/sdk/mappers => models/src/main/java/info/FrostFS/sdk/mappers/container}/ContainerMapper.java (60%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java (74%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java (96%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java (88%) rename {modelsV2 => models}/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java (91%) rename {modelsV2/src/main/java/info/FrostFS/sdk/mappers => models/src/main/java/info/FrostFS/sdk/mappers/object}/ObjectAttributeMapper.java (83%) rename {modelsV2/src/main/java/info/FrostFS/sdk/mappers => models/src/main/java/info/FrostFS/sdk/mappers/object}/ObjectFilterMapper.java (86%) create mode 100644 models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java rename {modelsV2/src/main/java/info/FrostFS/sdk/mappers => models/src/main/java/info/FrostFS/sdk/mappers/object}/ObjectHeaderMapper.java (75%) rename {modelsV2/src/main/java/info/FrostFS/sdk/mappers => models/src/main/java/info/FrostFS/sdk/mappers/object}/ObjectIdMapper.java (57%) delete mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java delete mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java delete mode 100644 modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java rename {protosV2 => protos}/pom.xml (98%) rename {protosV2 => protos}/src/main/proto/accounting/service.proto (100%) rename {protosV2 => protos}/src/main/proto/accounting/types.proto (100%) rename {protosV2 => protos}/src/main/proto/acl/types.proto (100%) rename {protosV2 => protos}/src/main/proto/apemanager/service.proto (100%) rename {protosV2 => protos}/src/main/proto/apemanager/types.proto (100%) rename {protosV2 => protos}/src/main/proto/container/service.proto (100%) rename {protosV2 => protos}/src/main/proto/container/types.proto (100%) rename {protosV2 => protos}/src/main/proto/lock/types.proto (100%) rename {protosV2 => protos}/src/main/proto/netmap/service.proto (100%) rename {protosV2 => protos}/src/main/proto/netmap/types.proto (100%) rename {protosV2 => protos}/src/main/proto/object/service.proto (100%) rename {protosV2 => protos}/src/main/proto/object/types.proto (100%) rename {protosV2 => protos}/src/main/proto/refs/types.proto (100%) rename {protosV2 => protos}/src/main/proto/session/service.proto (100%) rename {protosV2 => protos}/src/main/proto/session/types.proto (100%) rename {protosV2 => protos}/src/main/proto/status/types.proto (100%) rename {protosV2 => protos}/src/main/proto/tombstone/types.proto (100%) diff --git a/README.md b/README.md index 2883006..94031a8 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ neo-go wallet export -w -d ```java import info.FrostFS.sdk.enums.BasicAcl; -import info.FrostFS.sdk.jdo.Container; -import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; -import info.FrostFS.sdk.jdo.netmap.Replica; +import info.FrostFS.sdk.dto.container.Container; +import info.FrostFS.sdk.dto.netmap.PlacementPolicy; +import info.FrostFS.sdk.dto.netmap.Replica; import info.FrostFS.sdk.services.FrostFSClient; public class ContainerExample { @@ -36,16 +36,16 @@ public class ContainerExample { // Create container var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)}); - var containerId = frostFSClient.createContainerAsync(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); + var containerId = frostFSClient.createContainer(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); // Get container - var container = frostFSClient.getContainerAsync(containerId); + var container = frostFSClient.getContainer(containerId); // List containers - var containerIds = frostFSClient.listContainersAsync(); + var containerIds = frostFSClient.listContainers(); // Delete container - frostFSClient.deleteContainerAsync(containerId); + frostFSClient.deleteContainer(containerId); } } ``` @@ -54,10 +54,10 @@ public class ContainerExample { ```java import info.FrostFS.sdk.enums.ObjectType; -import info.FrostFS.sdk.jdo.ContainerId; -import info.FrostFS.sdk.jdo.ObjectAttribute; -import info.FrostFS.sdk.jdo.ObjectFilter; -import info.FrostFS.sdk.jdo.ObjectHeader; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.dto.object.ObjectAttribute; +import info.FrostFS.sdk.dto.object.ObjectFilter; +import info.FrostFS.sdk.dto.object.ObjectHeader; import info.FrostFS.sdk.services.FrostFSClient; import java.io.FileInputStream; @@ -71,24 +71,24 @@ public class ObjectExample { FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client); // Put object - info.FrostFS.sdk.jdo.ObjectId objectId; + info.FrostFS.sdk.dto.object.ObjectId objectId; try (FileInputStream fis = new FileInputStream("cat.jpg")) { var cat = new ObjectHeader( containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")} ); - objectId = frostFSClient.putObjectAsync(cat, fis); + objectId = frostFSClient.putObject(cat, fis); } catch (IOException e) { throw new RuntimeException(e); } // Get object - var obj = frostFSClient.getObjectAsync(containerId, objectId); + var obj = frostFSClient.getObject(containerId, objectId); // Get object header - var objectHeader = frostFSClient.getObjectHeadAsync(containerId, objectId); + var objectHeader = frostFSClient.getObjectHead(containerId, objectId); // Search regular objects - var objectIds = frostFSClient.searchObjectsAsync(containerId, ObjectFilter.RootFilter()); + var objectIds = frostFSClient.searchObjects(containerId, ObjectFilter.RootFilter()); } } ``` \ No newline at end of file diff --git a/client/pom.xml b/client/pom.xml index b416ee4..3d3426e 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -25,9 +25,19 @@ info.FrostFS.sdk - modelsV2 + models 0.1.0 + + org.apache.commons + commons-collections4 + 4.4 + + + commons-codec + commons-codec + 1.17.0 + \ No newline at end of file diff --git a/client/src/main/java/info/FrostFS/sdk/Main.java b/client/src/main/java/info/FrostFS/sdk/Main.java index d16f06e..4c854fe 100644 --- a/client/src/main/java/info/FrostFS/sdk/Main.java +++ b/client/src/main/java/info/FrostFS/sdk/Main.java @@ -1,14 +1,22 @@ package info.FrostFS.sdk; +import info.FrostFS.sdk.dto.container.Container; +import info.FrostFS.sdk.dto.container.ContainerId; import info.FrostFS.sdk.enums.BasicAcl; import info.FrostFS.sdk.enums.ObjectType; -import info.FrostFS.sdk.jdo.*; -import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; -import info.FrostFS.sdk.jdo.netmap.Replica; +import info.FrostFS.sdk.dto.netmap.PlacementPolicy; +import info.FrostFS.sdk.dto.netmap.Replica; +import info.FrostFS.sdk.dto.object.ObjectAttribute; +import info.FrostFS.sdk.dto.object.ObjectFrostFS; +import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.dto.object.ObjectId; import info.FrostFS.sdk.services.FrostFSClient; +import info.FrostFS.sdk.tools.ClientSettings; +import info.FrostFS.sdk.tools.PutObjectParameters; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.util.Collections; import java.util.List; public class Main { @@ -18,37 +26,42 @@ public class Main { /* var res2 = frostFSClient.searchObjectsAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); */ - - ObjectFrostFs res3 = frostFSClient - .getObjectAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"), new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww")); - - - var ttttt = frostFSClient.getNetworkSettingsAsync(); - Container container2 = frostFSClient.getContainerAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); - - var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)}); - var containerId = frostFSClient.createContainerAsync(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); + var containerId = frostFSClient.createContainer(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); Thread.sleep(1000); FileInputStream file = null; try { file = new FileInputStream("/home/ori/Desktop/cat.jpg"); - var cat = new ObjectHeader(containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")}); - frostFSClient.putObjectAsync(cat, file); + var cat = new ObjectHeader(containerId, ObjectType.REGULAR, Collections.singletonList(new ObjectAttribute("Filename", "cat3.jpg"))); + + var params = new PutObjectParameters(cat, file, false, 1024); + var tty = frostFSClient.putObject(params); + + System.out.println(1); } catch (FileNotFoundException e) { throw new RuntimeException(e); } - var res = frostFSClient.searchObjectsAsync(containerId); + + var res = frostFSClient.searchObjects(containerId); + + ObjectFrostFS res3 = frostFSClient + .getObject(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"), new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww")); - Container container = frostFSClient.getContainerAsync(containerId); - List containerIds = frostFSClient.listContainersAsync(); + var ttttt = frostFSClient.getNetworkSettings(); + Container container2 = frostFSClient.getContainer(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); + + + + + Container container = frostFSClient.getContainer(containerId); + List containerIds = frostFSClient.listContainers(); /* frostFSClient.deleteContainerAsync(containerId); */ - containerIds = frostFSClient.listContainersAsync(); + containerIds = frostFSClient.listContainers(); System.out.println(); } } \ No newline at end of file diff --git a/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java b/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java index 304a878..28daecc 100644 --- a/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java +++ b/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java @@ -2,8 +2,9 @@ package info.FrostFS.sdk; import com.google.protobuf.AbstractMessage; import frostFS.session.Types; -import info.FrostFS.sdk.jdo.MetaHeader; +import info.FrostFS.sdk.dto.MetaHeader; import info.FrostFS.sdk.mappers.MetaHeaderMapper; +import info.FrostFS.sdk.tools.ECDsa; import static info.FrostFS.sdk.RequestSigner.signMessagePart; import static java.util.Objects.isNull; @@ -27,7 +28,7 @@ public class RequestConstructor { frostFS.refs.Types.ContainerID cid, frostFS.refs.Types.ObjectID oid, Types.ObjectSessionContext.Verb verb, - byte[] publicKey, byte[] privateKey) { + ECDsa key) { var headerField = request.getDescriptorForType().findFieldByName("meta_header"); var header = (Types.RequestMetaHeader) request.getField(headerField); if (header.getSessionToken().getSerializedSize() > 0) { @@ -41,7 +42,7 @@ public class RequestConstructor { var body = sessionToken.getBody().toBuilder().setObject(ctx).build(); sessionToken = sessionToken.toBuilder() - .setSignature(signMessagePart(publicKey, privateKey, body)) + .setSignature(signMessagePart(key, body)) .setBody(body) .build(); diff --git a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java b/client/src/main/java/info/FrostFS/sdk/RequestSigner.java index 962a421..a26dadf 100644 --- a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java +++ b/client/src/main/java/info/FrostFS/sdk/RequestSigner.java @@ -3,6 +3,7 @@ package info.FrostFS.sdk; import com.google.protobuf.AbstractMessage; import com.google.protobuf.ByteString; import frostFS.session.Types; +import info.FrostFS.sdk.tools.ECDsa; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -14,19 +15,18 @@ import org.bouncycastle.crypto.signers.HMacDSAKCalculator; import java.math.BigInteger; import java.security.Signature; -import static info.FrostFS.sdk.KeyExtension.loadPrivateKey; import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; public class RequestSigner { public static final int RFC6979_SIGNATURE_SIZE = 64; - public static byte[] signData(byte[] privateKey, byte[] data) { + public static byte[] signData(ECDsa key, byte[] data) { var hash = new byte[65]; hash[0] = 0x04; try { Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format"); - signature.initSign(loadPrivateKey(privateKey)); + signature.initSign(key.getPrivateKey()); signature.update(DigestUtils.sha512(data)); byte[] sig = signature.sign(); System.arraycopy(sig, 0, hash, 1, sig.length); @@ -37,12 +37,12 @@ public class RequestSigner { return hash; } - public static byte[] signRFC6979(byte[] privateKey, byte[] data) { + public static byte[] signRFC6979(ECDsa key, byte[] data) { var digest = createSHA256(); var secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); var ecParameters = new ECDomainParameters(secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN()); - var ecPrivateKey = new ECPrivateKeyParameters(new BigInteger(1, privateKey), ecParameters); + var ecPrivateKey = new ECPrivateKeyParameters(new BigInteger(1, key.getPrivateKeyByte()), ecParameters); var signer = new ECDSASigner(new HMacDSAKCalculator(digest)); var hash = new byte[digest.getDigestSize()]; @@ -62,36 +62,29 @@ public class RequestSigner { return signature; } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, - byte[] privateKey, - AbstractMessage message) { + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, AbstractMessage message) { return frostFS.refs.Types.SignatureRFC6979.newBuilder() - .setKey(ByteString.copyFrom(publicKey)) - .setSign(ByteString.copyFrom(signRFC6979(privateKey, message.toByteArray()))) + .setKey(ByteString.copyFrom(key.getPublicKeyByte())) + .setSign(ByteString.copyFrom(signRFC6979(key, message.toByteArray()))) .build(); } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(byte[] publicKey, - byte[] privateKey, - ByteString data) { + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, ByteString data) { return frostFS.refs.Types.SignatureRFC6979.newBuilder() - .setKey(ByteString.copyFrom(publicKey)) - .setSign(ByteString.copyFrom(signRFC6979(privateKey, data.toByteArray()))) + .setKey(ByteString.copyFrom(key.getPublicKeyByte())) + .setSign(ByteString.copyFrom(signRFC6979(key, data.toByteArray()))) .build(); } - public static frostFS.refs.Types.Signature signMessagePart(byte[] publicKey, - byte[] privateKey, - AbstractMessage data) { + public static frostFS.refs.Types.Signature signMessagePart(ECDsa key, AbstractMessage data) { var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); - return frostFS.refs.Types.Signature.newBuilder() - .setKey(ByteString.copyFrom(publicKey)) - .setSign(ByteString.copyFrom(signData(privateKey, data2Sign))) + .setKey(ByteString.copyFrom(key.getPublicKeyByte())) + .setSign(ByteString.copyFrom(signData(key, data2Sign))) .build(); } - public static void sign(AbstractMessage.Builder request, byte[] publicKey, byte[] privateKey) { + public static void sign(AbstractMessage.Builder request, ECDsa key) { var meta = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("meta_header")); var body = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("body")); var verify = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("verify_header")); @@ -109,7 +102,7 @@ public class RequestSigner { if (verifyOrigin.getSerializedSize() == 0) { verifyBuilder.setField( verifyBuilder.getDescriptorForType().findFieldByName("body_signature"), - signMessagePart(publicKey, privateKey, body) + signMessagePart(key, body) ); } else { verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin); @@ -117,11 +110,11 @@ public class RequestSigner { verifyBuilder.setField( verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"), - signMessagePart(publicKey, privateKey, meta) + signMessagePart(key, meta) ); verifyBuilder.setField( verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"), - signMessagePart(publicKey, privateKey, verifyOrigin) + signMessagePart(key, verifyOrigin) ); request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build()); diff --git a/client/src/main/java/info/FrostFS/sdk/Verifier.java b/client/src/main/java/info/FrostFS/sdk/Verifier.java index 7a1b136..e0c37ec 100644 --- a/client/src/main/java/info/FrostFS/sdk/Verifier.java +++ b/client/src/main/java/info/FrostFS/sdk/Verifier.java @@ -16,7 +16,7 @@ import java.security.PublicKey; import java.security.Signature; import java.util.Arrays; -import static info.FrostFS.sdk.KeyExtension.getPublicKeyByPublic; +import static info.FrostFS.sdk.KeyExtension.getPublicKeyFromBytes; import static java.util.Objects.isNull; import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; @@ -99,7 +99,7 @@ public class Verifier { public static boolean verifyMessagePart(Types.Signature sig, AbstractMessage data) { if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false; - var publicKey = getPublicKeyByPublic(sig.getKey().toByteArray()); + var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray()); var data2Verify = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); return verifyData(publicKey, data2Verify, sig.getSign().toByteArray()); diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java b/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java index 3cdb8c2..385f616 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java @@ -1,16 +1,16 @@ package info.FrostFS.sdk.services; -import info.FrostFS.sdk.jdo.Container; -import info.FrostFS.sdk.jdo.ContainerId; +import info.FrostFS.sdk.dto.container.Container; +import info.FrostFS.sdk.dto.container.ContainerId; import java.util.List; public interface ContainerClient { - Container getContainerAsync(ContainerId cid); + Container getContainer(ContainerId cid); - List listContainersAsync(); + List listContainers(); - ContainerId createContainerAsync(Container container); + ContainerId createContainer(Container container); - void deleteContainerAsync(ContainerId cid); + void deleteContainer(ContainerId cid); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java b/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java index 6985310..d3880a9 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java +++ b/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java @@ -3,7 +3,7 @@ package info.FrostFS.sdk.services; import info.FrostFS.sdk.tools.ClientEnvironment; public class ContextAccessor { - protected ClientEnvironment context; + private final ClientEnvironment context; public ContextAccessor(ClientEnvironment context) { this.context = context; @@ -12,8 +12,4 @@ public class ContextAccessor { public ClientEnvironment getContext() { return context; } - - public void setContext(ClientEnvironment context) { - this.context = context; - } } diff --git a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java b/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java index 44a0388..64ba93c 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java @@ -1,19 +1,23 @@ package info.FrostFS.sdk.services; import frostFS.session.Types; -import info.FrostFS.sdk.ClientSettings; -import info.FrostFS.sdk.jdo.*; -import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; -import info.FrostFS.sdk.jdo.netmap.NodeInfo; -import info.FrostFS.sdk.services.impl.ContainerService; -import info.FrostFS.sdk.services.impl.NetmapService; -import info.FrostFS.sdk.services.impl.ObjectService; -import info.FrostFS.sdk.services.impl.SessionService; +import info.FrostFS.sdk.tools.ClientSettings; +import info.FrostFS.sdk.tools.PutObjectParameters; +import info.FrostFS.sdk.dto.container.Container; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.dto.SessionToken; +import info.FrostFS.sdk.dto.Version; +import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; +import info.FrostFS.sdk.dto.netmap.NodeInfo; +import info.FrostFS.sdk.dto.object.ObjectFilter; +import info.FrostFS.sdk.dto.object.ObjectFrostFS; +import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.dto.object.ObjectId; +import info.FrostFS.sdk.services.impl.*; import info.FrostFS.sdk.tools.ClientEnvironment; import info.FrostFS.sdk.tools.NetworkSettings; import io.grpc.Channel; -import java.io.FileInputStream; import java.util.List; import static info.FrostFS.sdk.GrpcClient.initGrpcChannel; @@ -24,7 +28,7 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien private final NetmapService netmapService; private final ObjectService objectService; private final SessionService sessionService; - private final ClientEnvironment clientEnvironment; + private final ObjectTools objectTools; public FrostFSClient(ClientSettings clientSettings) { if (isNull(clientSettings)) { @@ -32,20 +36,22 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien } clientSettings.validate(); + Channel channel = initGrpcChannel(clientSettings.getHost(), clientSettings.getCreds()); - this.clientEnvironment = + ClientEnvironment clientEnvironment = new ClientEnvironment(clientSettings.getKey(), channel, new Version(2, 13), this); this.containerService = new ContainerService(clientEnvironment); this.netmapService = new NetmapService(clientEnvironment); this.sessionService = new SessionService(clientEnvironment); this.objectService = new ObjectService(clientEnvironment); + this.objectTools = new ObjectTools(clientEnvironment); checkFrostFsVersionSupport(clientEnvironment.getVersion()); } private void checkFrostFsVersionSupport(Version version) { - var localNodeInfo = netmapService.getLocalNodeInfoAsync(); + var localNodeInfo = netmapService.getLocalNodeInfo(); if (!localNodeInfo.getVersion().isSupported(version)) { var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion()); System.out.println(msg); @@ -54,81 +60,76 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien } @Override - public Container getContainerAsync(ContainerId cid) { - return containerService.getContainerAsync(cid); + public Container getContainer(ContainerId cid) { + return containerService.getContainer(cid); } @Override - public List listContainersAsync() { - return containerService.listContainersAsync(); + public List listContainers() { + return containerService.listContainers(); } @Override - public ContainerId createContainerAsync(Container container) { - return containerService.createContainerAsync(container); + public ContainerId createContainer(Container container) { + return containerService.createContainer(container); } @Override - public void deleteContainerAsync(ContainerId cid) { - containerService.deleteContainerAsync(cid); + public void deleteContainer(ContainerId cid) { + containerService.deleteContainer(cid); } @Override - public ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId) { - return objectService.getObjectHeadAsync(containerId, objectId); + public ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId) { + return objectService.getObjectHead(containerId, objectId); } @Override - public ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId) { - return objectService.getObjectAsync(containerId, objectId); + public ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId) { + return objectService.getObject(containerId, objectId); } @Override - public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) { - return objectService.putObjectAsync(header, payload); + public ObjectId putObject(PutObjectParameters parameters) { + return objectService.putObject(parameters); } @Override - public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) { - return objectService.putObjectAsync(header, payload); + public void deleteObject(ContainerId containerId, ObjectId objectId) { + objectService.deleteObject(containerId, objectId); } @Override - public void deleteObjectAsync(ContainerId containerId, ObjectId objectId) { - objectService.deleteObjectAsync(containerId, objectId); + public Iterable searchObjects(ContainerId cid, ObjectFilter... filters) { + return objectService.searchObjects(cid, filters); } @Override - public Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters) { - return objectService.searchObjectsAsync(cid, filters); + public NetmapSnapshot getNetmapSnapshot() { + return netmapService.getNetmapSnapshot(); } @Override - public NetmapSnapshot getNetmapSnapshotAsync() { - return netmapService.getNetmapSnapshotAsync(); + public NodeInfo getLocalNodeInfo() { + return netmapService.getLocalNodeInfo(); } @Override - public NodeInfo getLocalNodeInfoAsync() { - return netmapService.getLocalNodeInfoAsync(); + public NetworkSettings getNetworkSettings() { + return netmapService.getNetworkSettings(); } @Override - public NetworkSettings getNetworkSettingsAsync() { - return netmapService.getNetworkSettingsAsync(); + public SessionToken createSession(long expiration) { + return sessionService.createSession(expiration); + } + + public Types.SessionToken createSessionInternal(long expiration) { + return sessionService.createSessionInternal(expiration); } @Override - public SessionToken createSessionAsync(long expiration) { - return sessionService.createSessionAsync(expiration); - } - - public Types.SessionToken createSessionInternalAsync(long expiration) { - return sessionService.createSessionInternalAsync(expiration); - } - - @Override - public ObjectId CalculateObjectId(ObjectHeader header) { - return null; + public ObjectId calculateObjectId(ObjectHeader header) { + return objectTools.calculateObjectId(header); } } diff --git a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java index f6e9401..80bbf1e 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java @@ -1,14 +1,13 @@ package info.FrostFS.sdk.services; -import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; -import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; +import info.FrostFS.sdk.dto.netmap.NodeInfo; import info.FrostFS.sdk.tools.NetworkSettings; public interface NetmapClient { + NetmapSnapshot getNetmapSnapshot(); - NetmapSnapshot getNetmapSnapshotAsync(); + NodeInfo getLocalNodeInfo(); - NodeInfo getLocalNodeInfoAsync(); - - NetworkSettings getNetworkSettingsAsync(); + NetworkSettings getNetworkSettings(); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java b/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java index 682d52a..f19fb61 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java @@ -1,19 +1,20 @@ package info.FrostFS.sdk.services; -import info.FrostFS.sdk.jdo.*; - -import java.io.FileInputStream; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.tools.PutObjectParameters; +import info.FrostFS.sdk.dto.object.ObjectFilter; +import info.FrostFS.sdk.dto.object.ObjectFrostFS; +import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.dto.object.ObjectId; public interface ObjectClient { - ObjectHeader getObjectHeadAsync(ContainerId containerId, ObjectId objectId); + ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId); - ObjectFrostFs getObjectAsync(ContainerId containerId, ObjectId objectId); + ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId); - ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload); + ObjectId putObject(PutObjectParameters parameters); - ObjectId putObjectAsync(ObjectHeader header, byte[] payload); + void deleteObject(ContainerId containerId, ObjectId objectId); - void deleteObjectAsync(ContainerId containerId, ObjectId objectId); - - Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters); + Iterable searchObjects(ContainerId cid, ObjectFilter... filters); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java b/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java index ffd1f0a..6fd7f4f 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java @@ -1,8 +1,7 @@ package info.FrostFS.sdk.services; -import info.FrostFS.sdk.jdo.SessionToken; +import info.FrostFS.sdk.dto.SessionToken; public interface SessionClient { - - SessionToken createSessionAsync(long expiration); + SessionToken createSession(long expiration); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java b/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java index 62dffc2..fb673a2 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java @@ -1,8 +1,8 @@ package info.FrostFS.sdk.services; -import info.FrostFS.sdk.jdo.ObjectHeader; -import info.FrostFS.sdk.jdo.ObjectId; +import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.dto.object.ObjectId; public interface ToolsClient { - ObjectId CalculateObjectId(ObjectHeader header); + ObjectId calculateObjectId(ObjectHeader header); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java index 824f967..4383579 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java @@ -3,10 +3,10 @@ package info.FrostFS.sdk.services.impl; import frostFS.container.ContainerServiceGrpc; import frostFS.container.Service; import info.FrostFS.sdk.Verifier; -import info.FrostFS.sdk.jdo.Container; -import info.FrostFS.sdk.jdo.ContainerId; -import info.FrostFS.sdk.mappers.ContainerIdMapper; -import info.FrostFS.sdk.mappers.ContainerMapper; +import info.FrostFS.sdk.dto.container.Container; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.mappers.container.ContainerIdMapper; +import info.FrostFS.sdk.mappers.container.ContainerMapper; import info.FrostFS.sdk.mappers.OwnerIdMapper; import info.FrostFS.sdk.mappers.VersionMapper; import info.FrostFS.sdk.services.ContainerClient; @@ -21,14 +21,14 @@ import static info.FrostFS.sdk.RequestSigner.sign; import static info.FrostFS.sdk.RequestSigner.signRFC6979; public class ContainerService extends ContextAccessor implements ContainerClient { - private final ContainerServiceGrpc.ContainerServiceBlockingStub containerServiceAsyncClient; + private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub; public ContainerService(ClientEnvironment clientEnvironment) { super(clientEnvironment); - this.containerServiceAsyncClient = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel()); + this.serviceBlockingStub = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel()); } - public Container getContainerAsync(ContainerId cid) { + public Container getContainer(ContainerId cid) { var request = Service.GetRequest.newBuilder() .setBody( Service.GetRequest.Body.newBuilder() @@ -37,26 +37,26 @@ public class ContainerService extends ContextAccessor implements ContainerClient ); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); - var response = containerServiceAsyncClient.get(request.build()); + var response = serviceBlockingStub.get(request.build()); Verifier.checkResponse(response); return ContainerMapper.toModel(response.getBody().getContainer()); } - public List listContainersAsync() { + public List listContainers() { var request = Service.ListRequest.newBuilder() .setBody( Service.ListRequest.Body.newBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .build() ); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); - var response = containerServiceAsyncClient.list(request.build()); + var response = serviceBlockingStub.list(request.build()); Verifier.checkResponse(response); @@ -65,12 +65,12 @@ public class ContainerService extends ContextAccessor implements ContainerClient .collect(Collectors.toList()); } - public ContainerId createContainerAsync(Container container) { + public ContainerId createContainer(Container container) { var grpcContainer = ContainerMapper.toGrpcMessage(container); grpcContainer = grpcContainer.toBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) - .setVersion(VersionMapper.toGrpcMessage(context.getVersion())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())) .build(); var request = Service.PutRequest.newBuilder() @@ -78,21 +78,21 @@ public class ContainerService extends ContextAccessor implements ContainerClient Service.PutRequest.Body.newBuilder() .setContainer(grpcContainer) .setSignature( - signRFC6979(context.getPublicKey(), context.getPrivateKey(), grpcContainer) + signRFC6979(getContext().getKey(), grpcContainer) ) .build() ); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); - var response = containerServiceAsyncClient.put(request.build()); + var response = serviceBlockingStub.put(request.build()); Verifier.checkResponse(response); return ContainerId.fromHash(response.getBody().getContainerId().getValue().toByteArray()); } - public void deleteContainerAsync(ContainerId cid) { + public void deleteContainer(ContainerId cid) { var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid); var request = Service.DeleteRequest.newBuilder() @@ -100,15 +100,15 @@ public class ContainerService extends ContextAccessor implements ContainerClient Service.DeleteRequest.Body.newBuilder() .setContainerId(grpcContainerId) .setSignature(signRFC6979( - context.getPublicKey(), context.getPrivateKey(), grpcContainerId.getValue() + getContext().getKey(), grpcContainerId.getValue() )) .build() ); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); - var response = containerServiceAsyncClient.delete(request.build()); + var response = serviceBlockingStub.delete(request.build()); Verifier.checkResponse(response); } diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java index b2ccf23..e55c655 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java @@ -4,8 +4,8 @@ import frostFS.netmap.NetmapServiceGrpc; import frostFS.netmap.Service; import frostFS.netmap.Types; import info.FrostFS.sdk.Verifier; -import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; -import info.FrostFS.sdk.jdo.netmap.NodeInfo; +import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; +import info.FrostFS.sdk.dto.netmap.NodeInfo; import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper; import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper; import info.FrostFS.sdk.services.ContextAccessor; @@ -24,7 +24,7 @@ public class NetmapService extends ContextAccessor implements NetmapClient { public NetmapService(ClientEnvironment clientEnvironment) { super(clientEnvironment); - this.netmapServiceClient = NetmapServiceGrpc.newBlockingStub(context.getChannel()); + this.netmapServiceClient = NetmapServiceGrpc.newBlockingStub(getContext().getChannel()); } private static boolean getBoolValue(byte[] bytes) { @@ -92,12 +92,12 @@ public class NetmapService extends ContextAccessor implements NetmapClient { } @Override - public NetworkSettings getNetworkSettingsAsync() { - if (nonNull(context.getNetworkSettings())) { - return context.getNetworkSettings(); + public NetworkSettings getNetworkSettings() { + if (nonNull(getContext().getNetworkSettings())) { + return getContext().getNetworkSettings(); } - var info = getNetworkInfoAsync(); + var info = getNetworkInfo(); var settings = new NetworkSettings(); @@ -105,18 +105,18 @@ public class NetmapService extends ContextAccessor implements NetmapClient { setNetworksParam(param, settings); } - context.setNetworkSettings(settings); + getContext().setNetworkSettings(settings); return settings; } @Override - public NodeInfo getLocalNodeInfoAsync() { + public NodeInfo getLocalNodeInfo() { var request = Service.LocalNodeInfoRequest.newBuilder() .setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build()); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var response = netmapServiceClient.localNodeInfo(request.build()); Verifier.checkResponse(response); @@ -124,12 +124,12 @@ public class NetmapService extends ContextAccessor implements NetmapClient { return NodeInfoMapper.toModel(response.getBody()); } - public Service.NetworkInfoResponse getNetworkInfoAsync() { + public Service.NetworkInfoResponse getNetworkInfo() { var request = Service.NetworkInfoRequest.newBuilder() .setBody(Service.NetworkInfoRequest.Body.newBuilder().build()); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var response = netmapServiceClient.networkInfo(request.build()); @@ -139,12 +139,12 @@ public class NetmapService extends ContextAccessor implements NetmapClient { } @Override - public NetmapSnapshot getNetmapSnapshotAsync() { + public NetmapSnapshot getNetmapSnapshot() { var request = Service.NetmapSnapshotRequest.newBuilder() .setBody(Service.NetmapSnapshotRequest.Body.newBuilder().build()); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var response = netmapServiceClient.netmapSnapshot(request.build()); diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java index 9ef6a6d..4fbe78d 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java @@ -6,16 +6,24 @@ import frostFS.object.ObjectServiceGrpc; import frostFS.object.Service; import frostFS.refs.Types; import info.FrostFS.sdk.Verifier; -import info.FrostFS.sdk.jdo.*; +import info.FrostFS.sdk.constants.AppConst; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.dto.Split; +import info.FrostFS.sdk.dto.object.*; import info.FrostFS.sdk.mappers.*; +import info.FrostFS.sdk.mappers.container.ContainerIdMapper; +import info.FrostFS.sdk.mappers.object.ObjectFilterMapper; +import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; +import info.FrostFS.sdk.mappers.object.ObjectIdMapper; +import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper; import info.FrostFS.sdk.services.ContextAccessor; import info.FrostFS.sdk.services.ObjectClient; import info.FrostFS.sdk.tools.ClientEnvironment; +import info.FrostFS.sdk.tools.PutObjectParameters; +import org.apache.commons.collections4.CollectionUtils; -import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -29,15 +37,17 @@ import static java.util.Objects.nonNull; public class ObjectService extends ContextAccessor implements ObjectClient { private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; + private final ObjectTools objectTools; public ObjectService(ClientEnvironment clientEnvironment) { super(clientEnvironment); - this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(context.getChannel()); - this.objectServiceClient = ObjectServiceGrpc.newStub(context.getChannel()); + this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(getContext().getChannel()); + this.objectServiceClient = ObjectServiceGrpc.newStub(getContext().getChannel()); + this.objectTools = new ObjectTools(clientEnvironment); } @Override - public ObjectHeader getObjectHeadAsync(ContainerId cid, ObjectId oid) { + public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) { var request = Service.HeadRequest.newBuilder() .setBody( Service.HeadRequest.Body.newBuilder() @@ -50,7 +60,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { ); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var response = objectServiceBlockingClient.head(request.build()); Verifier.checkResponse(response); @@ -59,8 +69,8 @@ public class ObjectService extends ContextAccessor implements ObjectClient { } @Override - public ObjectFrostFs getObjectAsync(ContainerId cid, ObjectId oid) { - var sessionToken = context.getFrostFSClient().createSessionInternalAsync(-1); + public ObjectFrostFS getObject(ContainerId cid, ObjectId oid) { + var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1); var request = Service.GetRequest.newBuilder() .setBody( @@ -71,24 +81,23 @@ public class ObjectService extends ContextAccessor implements ObjectClient { .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) .build() ) - .setRaw(false) .build() ); addMetaHeader(request); addObjectSessionToken( request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid), - frostFS.session.Types.ObjectSessionContext.Verb.GET, context.getPublicKey(), context.getPrivateKey() + frostFS.session.Types.ObjectSessionContext.Verb.GET, getContext().getKey() ); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var obj = getObject(request.build()); - - return ObjectMapper.toModel(obj); + return ObjectFrostFSMapper.toModel(obj); } + @Override - public void deleteObjectAsync(ContainerId cid, ObjectId oid) { + public void deleteObject(ContainerId cid, ObjectId oid) { var request = Service.DeleteRequest.newBuilder() .setBody( Service.DeleteRequest.Body.newBuilder() @@ -101,27 +110,17 @@ public class ObjectService extends ContextAccessor implements ObjectClient { .build()); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var response = objectServiceBlockingClient.delete(request.build()); Verifier.checkResponse(response); } @Override - public ObjectId putObjectAsync(ObjectHeader header, FileInputStream payload) { - return putObject(header, payload); - } - - @Override - public ObjectId putObjectAsync(ObjectHeader header, byte[] payload) { - return putObject(header, new ByteArrayInputStream(payload)); - } - - @Override - public Iterable searchObjectsAsync(ContainerId cid, ObjectFilter... filters) { + public Iterable searchObjects(ContainerId cid, ObjectFilter... filters) { var body = Service.SearchRequest.Body.newBuilder() .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) - .setVersion(1); + .setVersion(1);// TODO: clarify this param for (ObjectFilter filter : filters) { body.addFilters(ObjectFilterMapper.toGrpcMessage(filter)); @@ -131,13 +130,43 @@ public class ObjectService extends ContextAccessor implements ObjectClient { .setBody(body.build()); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); var objectsIds = searchObjects(request.build()); return Iterables.transform(objectsIds, input -> ObjectId.fromHash(input.getValue().toByteArray())); } + @Override + public ObjectId putObject(PutObjectParameters parameters) { + parameters.validate(); + + return parameters.clientCut ? putClientCutObject(parameters) : putStreamObject(parameters); + } + + public ObjectId putSingleObject(ObjectFrostFS modelObject) { + var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1); + + var grpcObject = objectTools.createObject(modelObject); + + var request = Service.PutSingleRequest.newBuilder() + .setBody(Service.PutSingleRequest.Body.newBuilder().setObject(grpcObject).build()); + + + addMetaHeader(request); + addObjectSessionToken( + request, sessionToken, grpcObject.getHeader().getContainerId(), grpcObject.getObjectId(), + frostFS.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() + ); + sign(request, getContext().getKey()); + + var response = objectServiceBlockingClient.putSingle(request.build()); + + Verifier.checkResponse(response); + + return ObjectId.fromHash(grpcObject.getObjectId().getValue().toByteArray()); + } + private frostFS.object.Types.Object getObject(Service.GetRequest request) { var iterator = getObjectInit(request); var obj = iterator.readHeader(); @@ -162,18 +191,20 @@ public class ObjectService extends ContextAccessor implements ObjectClient { return new ObjectReader(objectServiceBlockingClient.get(initRequest)); } - private ObjectId putObject(ObjectHeader header, InputStream payload) { - var sessionToken = context.getFrostFSClient().createSessionInternalAsync(-1); - var hdr = ObjectHeaderMapper.toGrpcMessage(header); + private ObjectId putStreamObject(PutObjectParameters parameters) { + var header = parameters.getHeader(); + var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1); + + var hdr = ObjectHeaderMapper.toGrpcMessage(header); hdr = hdr.toBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) - .setVersion(VersionMapper.toGrpcMessage(context.getVersion())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())) .build(); var oid = Types.ObjectID.newBuilder().setValue(getSha256(hdr)).build(); - var request = Service.PutRequest.newBuilder() + var initRequest = Service.PutRequest.newBuilder() .setBody( Service.PutRequest.Body.newBuilder() .setInit( @@ -181,34 +212,35 @@ public class ObjectService extends ContextAccessor implements ObjectClient { ).build() ); - addMetaHeader(request); + addMetaHeader(initRequest); addObjectSessionToken( - request, sessionToken, hdr.getContainerId(), oid, frostFS.session.Types.ObjectSessionContext.Verb.PUT, - context.getPublicKey(), context.getPrivateKey() + initRequest, sessionToken, hdr.getContainerId(), oid, + frostFS.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() ); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(initRequest, getContext().getKey()); - var writer = putObjectInit(request.build()); + var writer = putObjectInit(initRequest.build()); - var buffer = new byte[Constants.OBJECT_CHUNK_SIZE]; - int bufferLength = 0; - try { - bufferLength = payload.readNBytes(buffer, 0, Constants.OBJECT_CHUNK_SIZE); - while (bufferLength > 0) { - request.setBody( - Service.PutRequest.Body.newBuilder() - .setChunk(ByteString.copyFrom(Arrays.copyOfRange(buffer, 0, bufferLength))) - .build() - ) - .clearVerifyHeader(); - sign(request, context.getPublicKey(), context.getPrivateKey()); - writer.write(request.build()); - bufferLength = payload.readNBytes(buffer, 0, Constants.OBJECT_CHUNK_SIZE); - } - } catch ( - IOException e) { - throw new RuntimeException(e); + var bufferSize = parameters.getBufferMaxSize() > 0 ? parameters.getBufferMaxSize() : AppConst.OBJECT_CHUNK_SIZE; + bufferSize = (int) Math.min(getStreamSize(parameters.getPayload()), bufferSize); + bufferSize = header.getPayloadLength() > 0 ? (int) Math.min(header.getPayloadLength(), bufferSize) : bufferSize; + + var buffer = new byte[bufferSize]; + while (true) { + var bytesCount = readNBytes(parameters.getPayload(), buffer, bufferSize); + if (bytesCount <= 0) + break; + + var chunkRequest = Service.PutRequest.newBuilder(initRequest.build()) + .setBody( + Service.PutRequest.Body.newBuilder() + .setChunk(ByteString.copyFrom(Arrays.copyOfRange(buffer, 0, bytesCount))) + .build() + ) + .clearVerifyHeader(); + sign(chunkRequest, getContext().getKey()); + writer.write(chunkRequest.build()); } var response = writer.complete(); @@ -217,6 +249,71 @@ public class ObjectService extends ContextAccessor implements ObjectClient { return ObjectId.fromHash(response.getBody().getObjectId().getValue().toByteArray()); } + private ObjectId putClientCutObject(PutObjectParameters parameters) { + var header = parameters.getHeader(); + + var networkSettings = getContext().getFrostFSClient().getNetworkSettings(); + var payloadSize = getStreamSize(parameters.getPayload()); + var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize()); + var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength(); + if (fullLength == 0) { + throw new IllegalArgumentException("Payload stream must be able to seek or PayloadLength must be specified"); + } + + var buffer = new byte[objectSize]; + var largeObject = new LargeObject(header.getContainerId()); + var split = new Split(); + + ObjectId objectId; + List sentObjectIds = new ArrayList<>(); + ObjectFrostFS currentObject; + + while (true) { + var bytesCount = readNBytes(parameters.getPayload(), buffer, objectSize); + if (CollectionUtils.isNotEmpty(sentObjectIds)) { + split.setPrevious(sentObjectIds.get(sentObjectIds.size() - 1)); + } + + largeObject.appendBlock(buffer, bytesCount); + + currentObject = new ObjectFrostFS( + header.getContainerId(), + bytesCount < objectSize ? Arrays.copyOfRange(buffer, 0, bytesCount) : buffer + ); + currentObject.setSplit(split); + + if (largeObject.getPayloadLength() == fullLength) + break; + + objectId = putSingleObject(currentObject); + + sentObjectIds.add(objectId); + } + + if (CollectionUtils.isEmpty(sentObjectIds)) { + currentObject.addAttributes(parameters.getHeader().getAttributes()); + return putSingleObject(currentObject); + } + + largeObject.addAttributes(parameters.getHeader().getAttributes()); + largeObject.calculateHash(); + + currentObject.setParent(largeObject); + + objectId = putSingleObject(currentObject); + + sentObjectIds.add(objectId); + + var linkObject = new LinkObject(header.getContainerId(), split.getSplitId(), largeObject); + linkObject.addChildren(sentObjectIds); + + linkObject.getHeader().getAttributes().clear(); + + putSingleObject(linkObject); + + return objectTools.calculateObjectId(largeObject.getHeader()); + } + private ObjectWriter putObjectInit(Service.PutRequest initRequest) { if (initRequest.getSerializedSize() == 0) { throw new IllegalArgumentException(initRequest.getClass().getName()); @@ -248,4 +345,19 @@ public class ObjectService extends ContextAccessor implements ObjectClient { return new SearchReader(objectServiceBlockingClient.search(initRequest)); } + private int readNBytes(FileInputStream fileInputStream, byte[] buffer, int size) { + try { + return fileInputStream.readNBytes(buffer, 0, size); + } catch (IOException exp) { + throw new IllegalArgumentException(exp.getMessage()); + } + } + + private long getStreamSize(FileInputStream fileInputStream) { + try { + return fileInputStream.getChannel().size(); + } catch (IOException exp) { + throw new IllegalArgumentException(exp.getMessage()); + } + } } diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java new file mode 100644 index 0000000..31fbebd --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java @@ -0,0 +1,106 @@ +package info.FrostFS.sdk.services.impl; + +import com.google.protobuf.ByteString; +import frostFS.object.Types; +import info.FrostFS.sdk.dto.object.ObjectFrostFS; +import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.dto.object.ObjectId; +import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; +import info.FrostFS.sdk.mappers.object.ObjectIdMapper; +import info.FrostFS.sdk.mappers.OwnerIdMapper; +import info.FrostFS.sdk.mappers.VersionMapper; +import info.FrostFS.sdk.services.ContextAccessor; +import info.FrostFS.sdk.services.ToolsClient; +import info.FrostFS.sdk.tools.ClientEnvironment; +import org.apache.commons.collections4.ListUtils; + +import static info.FrostFS.sdk.Helper.getSha256; +import static info.FrostFS.sdk.RequestSigner.signData; +import static java.util.Objects.nonNull; + +public class ObjectTools extends ContextAccessor implements ToolsClient { + public ObjectTools(ClientEnvironment context) { + super(context); + } + + private static frostFS.refs.Types.Checksum sha256Checksum(byte[] data) { + return frostFS.refs.Types.Checksum.newBuilder() + .setType(frostFS.refs.Types.ChecksumType.SHA256) + .setSum(ByteString.copyFrom(getSha256(data))) + .build(); + } + + @Override + public ObjectId calculateObjectId(ObjectHeader header) { + var grpcHeader = createHeader(header, new byte[]{}); + + return ObjectIdMapper.toModel( + frostFS.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build() + ); + } + + public Types.Object createObject(ObjectFrostFS objectFrostFs) { + var grpcHeaderBuilder = ObjectHeaderMapper.toGrpcMessage(objectFrostFs.getHeader()).toBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())) + .setPayloadLength(objectFrostFs.getPayload().length) + .setPayloadHash(sha256Checksum(objectFrostFs.getPayload())); + + var split = objectFrostFs.getHeader().getSplit(); + if (nonNull(split)) { + var splitGrpc = Types.Header.Split.newBuilder() + .setSplitId(nonNull(split.getSplitId()) ? ByteString.copyFrom(split.getSplitId().toBinary()) : null); + + ListUtils.emptyIfNull(split.getChildren()).stream() + .map(ObjectIdMapper::toGrpcMessage) + .forEach(splitGrpc::addChildren); + + + if (nonNull(split.getParentHeader())) { + var grpcParentHeader = createHeader(split.getParentHeader(), new byte[]{}); + var parent = frostFS.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcParentHeader)).build(); + + splitGrpc + .setParent(parent) + .setParentHeader(grpcParentHeader) + .setParentSignature( + frostFS.refs.Types.Signature.newBuilder() + .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) + .setSign(ByteString.copyFrom(signData(getContext().getKey(), parent.toByteArray()))) + ); + + split.setParent(ObjectIdMapper.toModel(parent)); + } + if (nonNull(split.getPrevious())) { + splitGrpc.setPrevious(ObjectIdMapper.toGrpcMessage(split.getPrevious())); + } + grpcHeaderBuilder.setSplit(splitGrpc); + } + + var grpcHeader = grpcHeaderBuilder.build(); + var objectId = frostFS.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build(); + return Types.Object.newBuilder() + .setHeader(grpcHeader) + .setObjectId(objectId) + .setPayload(ByteString.copyFrom(objectFrostFs.getPayload())) + .setSignature( + frostFS.refs.Types.Signature.newBuilder() + .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) + .setSign(ByteString.copyFrom(signData(getContext().getKey(), objectId.toByteArray()))) + ) + .build(); + } + + private Types.Header createHeader(ObjectHeader header, byte[] payload) { + var grpcHeader = ObjectHeaderMapper.toGrpcMessage(header).toBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) + .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())); + + if (header.getPayloadCheckSum() != null) + grpcHeader.setPayloadHash(sha256Checksum(header.getPayloadCheckSum())); + else if (payload != null) + grpcHeader.setPayloadHash(sha256Checksum(payload)); + + return grpcHeader.build(); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java index 3406acf..cae3cb6 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java @@ -3,7 +3,7 @@ package info.FrostFS.sdk.services.impl; import frostFS.session.Service; import frostFS.session.SessionServiceGrpc; import frostFS.session.Types; -import info.FrostFS.sdk.jdo.SessionToken; +import info.FrostFS.sdk.dto.SessionToken; import info.FrostFS.sdk.mappers.OwnerIdMapper; import info.FrostFS.sdk.mappers.SessionMapper; import info.FrostFS.sdk.services.ContextAccessor; @@ -14,36 +14,36 @@ import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; import static info.FrostFS.sdk.RequestSigner.sign; public class SessionService extends ContextAccessor implements SessionClient { - private final SessionServiceGrpc.SessionServiceBlockingStub sessionServiceAsyncClient; + private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub; public SessionService(ClientEnvironment clientEnvironment) { super(clientEnvironment); - this.sessionServiceAsyncClient = SessionServiceGrpc.newBlockingStub(context.getChannel()); + this.serviceBlockingStub = SessionServiceGrpc.newBlockingStub(getContext().getChannel()); } @Override - public SessionToken createSessionAsync(long expiration) { - var sessionToken = createSessionInternalAsync(expiration); + public SessionToken createSession(long expiration) { + var sessionToken = createSessionInternal(expiration); var token = SessionMapper.serialize(sessionToken); return new SessionToken(new byte[]{}, token); } - public Types.SessionToken createSessionInternalAsync(long expiration) { + public Types.SessionToken createSessionInternal(long expiration) { var request = Service.CreateRequest.newBuilder() .setBody( Service.CreateRequest.Body.newBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(context.getOwnerId())) + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setExpiration(expiration).build() ); addMetaHeader(request); - sign(request, context.getPublicKey(), context.getPrivateKey()); + sign(request, getContext().getKey()); return createSession(request.build()); } private Types.SessionToken createSession(Service.CreateRequest request) { - var resp = sessionServiceAsyncClient.create(request); + var resp = serviceBlockingStub.create(request); var lifetime = Types.SessionToken.Body.TokenLifetime.newBuilder() .setExp(request.getBody().getExpiration()) diff --git a/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java b/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java index 93019ca..ee1d8d4 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java +++ b/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java @@ -1,26 +1,21 @@ package info.FrostFS.sdk.tools; -import info.FrostFS.sdk.jdo.OwnerId; -import info.FrostFS.sdk.jdo.Version; +import info.FrostFS.sdk.dto.OwnerId; +import info.FrostFS.sdk.dto.Version; import info.FrostFS.sdk.services.FrostFSClient; import io.grpc.Channel; -import static info.FrostFS.sdk.KeyExtension.getPrivateKeyFromWIF; -import static info.FrostFS.sdk.KeyExtension.loadPublicKey; - public class ClientEnvironment { private final OwnerId ownerId; private final Version version; - private final byte[] privateKey; - private final byte[] publicKey; + private final ECDsa key; private final Channel channel; private final FrostFSClient frostFSClient; private NetworkSettings networkSettings; - public ClientEnvironment(String key, Channel channel, Version version, FrostFSClient frostFSClient) { - this.privateKey = getPrivateKeyFromWIF(key); - this.publicKey = loadPublicKey(privateKey); - this.ownerId = OwnerId.fromKey(publicKey); + public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient) { + this.key = new ECDsa(wif); + this.ownerId = OwnerId.fromKey(key.getPublicKeyByte()); this.version = version; this.channel = channel; this.frostFSClient = frostFSClient; @@ -50,11 +45,7 @@ public class ClientEnvironment { return version; } - public byte[] getPrivateKey() { - return privateKey; - } - - public byte[] getPublicKey() { - return publicKey; + public ECDsa getKey() { + return key; } } diff --git a/client/src/main/java/info/FrostFS/sdk/ClientSettings.java b/client/src/main/java/info/FrostFS/sdk/tools/ClientSettings.java similarity index 97% rename from client/src/main/java/info/FrostFS/sdk/ClientSettings.java rename to client/src/main/java/info/FrostFS/sdk/tools/ClientSettings.java index 3b09497..2b25083 100644 --- a/client/src/main/java/info/FrostFS/sdk/ClientSettings.java +++ b/client/src/main/java/info/FrostFS/sdk/tools/ClientSettings.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk; +package info.FrostFS.sdk.tools; import io.grpc.ChannelCredentials; import org.apache.commons.lang3.StringUtils; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java b/client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java new file mode 100644 index 0000000..98ccfc0 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java @@ -0,0 +1,29 @@ +package info.FrostFS.sdk.tools; + +import java.security.PrivateKey; + +import static info.FrostFS.sdk.KeyExtension.*; + +public class ECDsa { + private final byte[] publicKeyByte; + private final byte[] privateKeyByte; + private final PrivateKey privateKey; + + public ECDsa(String wif) { + this.privateKeyByte = getPrivateKeyFromWIF(wif); + this.publicKeyByte = loadPublicKey(privateKeyByte); + this.privateKey = loadPrivateKey(privateKeyByte); + } + + public byte[] getPublicKeyByte() { + return publicKeyByte; + } + + public byte[] getPrivateKeyByte() { + return privateKeyByte; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java b/client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java new file mode 100644 index 0000000..ca62737 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java @@ -0,0 +1,76 @@ +package info.FrostFS.sdk.tools; + +import info.FrostFS.sdk.dto.object.ObjectHeader; + +import java.io.FileInputStream; + +import static java.util.Objects.isNull; + +public class PutObjectParameters { + private static final String ERROR_TEMPLATE = "%s value cannot be null."; + + public ObjectHeader header; + public FileInputStream payload; + public boolean clientCut; + public int bufferMaxSize; + + public PutObjectParameters(ObjectHeader header, FileInputStream payload, boolean clientCut, int bufferMaxSize) { + this.header = header; + this.payload = payload; + this.clientCut = clientCut; + this.bufferMaxSize = bufferMaxSize; + } + + public PutObjectParameters(ObjectHeader header, FileInputStream payload) { + this.header = header; + this.payload = payload; + } + + public ObjectHeader getHeader() { + return header; + } + + public void setHeader(ObjectHeader header) { + this.header = header; + } + + public FileInputStream getPayload() { + return payload; + } + + public void setPayload(FileInputStream payload) { + this.payload = payload; + } + + public boolean isClientCut() { + return clientCut; + } + + public void setClientCut(boolean clientCut) { + this.clientCut = clientCut; + } + + public int getBufferMaxSize() { + return bufferMaxSize; + } + + public void setBufferMaxSize(int bufferMaxSize) { + this.bufferMaxSize = bufferMaxSize; + } + + public void validate() { + StringBuilder errorMessage = new StringBuilder(); + + if (isNull(header)) { + errorMessage.append(String.format(ERROR_TEMPLATE, "Header")).append(System.lineSeparator()); + } + + if (isNull(payload)) { + errorMessage.append(String.format(ERROR_TEMPLATE, "Payload")).append(System.lineSeparator()); + } + + if (errorMessage.length() != 0) { + throw new IllegalArgumentException(errorMessage.toString()); + } + } +} diff --git a/cryptography/pom.xml b/cryptography/pom.xml index 9af2880..9c18d69 100644 --- a/cryptography/pom.xml +++ b/cryptography/pom.xml @@ -19,11 +19,6 @@ - - commons-codec - commons-codec - 1.17.0 - com.google.protobuf protobuf-java @@ -34,11 +29,6 @@ bcprov-jdk18on 1.78.1 - - org.bouncycastle - bcpkix-jdk18on - 1.78.1 - \ No newline at end of file diff --git a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java b/cryptography/src/main/java/info/FrostFS/sdk/Helper.java index e4e1460..fb11ac2 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java +++ b/cryptography/src/main/java/info/FrostFS/sdk/Helper.java @@ -18,19 +18,23 @@ public class Helper { return hash; } - public static byte[] getSha256(byte[] value) { + public static MessageDigest getSha256Instance() { try { - return MessageDigest.getInstance("SHA-256").digest(value); + return MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } + public static byte[] getSha256(byte[] value) { + return getSha256Instance().digest(value); + } + public static ByteString getSha256(AbstractMessage value) { return ByteString.copyFrom(getSha256(value.toByteArray())); } - public static String пуеHexString(byte[] array) { + public static String getHexString(byte[] array) { return String.format("%0" + (array.length << 1) + "x", new BigInteger(1, array)); } } diff --git a/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java b/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java index b8c5ab6..d057a04 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java +++ b/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java @@ -57,7 +57,9 @@ public class KeyExtension { public static byte[] loadPublicKey(byte[] privateKey) { X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); - ECDomainParameters domain = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + ECDomainParameters domain = new ECDomainParameters( + params.getCurve(), params.getG(), params.getN(), params.getH() + ); ECPoint q = domain.getG().multiply(new BigInteger(1, privateKey)); ECPublicKeyParameters publicParams = new ECPublicKeyParameters(q, domain); return publicParams.getQ().getEncoded(true); @@ -65,7 +67,9 @@ public class KeyExtension { public static PrivateKey loadPrivateKey(byte[] privateKey) { X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); - ECDomainParameters domain = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + ECDomainParameters domain = new ECDomainParameters( + params.getCurve(), params.getG(), params.getN(), params.getH() + ); ECPrivateKeyParameters ecParams = new ECPrivateKeyParameters(fromUnsignedByteArray(privateKey), domain); ECParameterSpec ecParameterSpec = new ECNamedCurveSpec( @@ -80,7 +84,7 @@ public class KeyExtension { } } - public static PublicKey getPublicKeyByPublic(byte[] publicKey) { + public static PublicKey getPublicKeyFromBytes(byte[] publicKey) { if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { throw new IllegalArgumentException( String.format("Decompress argument isn't compressed public key. Expected length=%s, actual=%s", @@ -89,14 +93,17 @@ public class KeyExtension { } X9ECParameters secp256R1 = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); - ECDomainParameters domain = new ECDomainParameters(secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH()); + ECDomainParameters domain = new ECDomainParameters( + secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH() + ); var ecPoint = secp256R1.getCurve().decodePoint(publicKey); var publicParams = new ECPublicKeyParameters(ecPoint, domain); java.security.spec.ECPoint point = new java.security.spec.ECPoint( publicParams.getQ().getRawXCoord().toBigInteger(), publicParams.getQ().getRawYCoord().toBigInteger() ); ECParameterSpec ecParameterSpec = new ECNamedCurveSpec( - "secp256r1", secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), secp256R1.getH(), secp256R1.getSeed() + "secp256r1", secp256R1.getCurve(), secp256R1.getG(), secp256R1.getN(), + secp256R1.getH(), secp256R1.getSeed() ); ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(point, ecParameterSpec); @@ -108,7 +115,6 @@ public class KeyExtension { } } - public static byte[] getScriptHash(byte[] publicKey) { var script = createSignatureRedeemScript(publicKey); diff --git a/modelsV2/pom.xml b/models/pom.xml similarity index 93% rename from modelsV2/pom.xml rename to models/pom.xml index 9093e71..7f9af60 100644 --- a/modelsV2/pom.xml +++ b/models/pom.xml @@ -9,7 +9,7 @@ 0.1.0 - modelsV2 + models 11 @@ -30,7 +30,7 @@ info.FrostFS.sdk - protosV2 + protos 0.1.0 diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/UUIDExtension.java b/models/src/main/java/info/FrostFS/sdk/UUIDExtension.java similarity index 100% rename from modelsV2/src/main/java/info/FrostFS/sdk/UUIDExtension.java rename to models/src/main/java/info/FrostFS/sdk/UUIDExtension.java diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java b/models/src/main/java/info/FrostFS/sdk/constants/AppConst.java similarity index 66% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java rename to models/src/main/java/info/FrostFS/sdk/constants/AppConst.java index 2c01d9e..8880eb0 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Constants.java +++ b/models/src/main/java/info/FrostFS/sdk/constants/AppConst.java @@ -1,6 +1,6 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.constants; -public class Constants { +public class AppConst { public static final int OBJECT_CHUNK_SIZE = 3 * (1 << 20); public static final int SHA256_HASH_LENGTH = 32; } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java b/models/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java similarity index 100% rename from modelsV2/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java rename to models/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java b/models/src/main/java/info/FrostFS/sdk/dto/MetaHeader.java similarity index 86% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java rename to models/src/main/java/info/FrostFS/sdk/dto/MetaHeader.java index 5f428b4..b0eead0 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/MetaHeader.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/MetaHeader.java @@ -1,9 +1,9 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto; public class MetaHeader { - public Version version; - public int epoch; - public int ttl; + private Version version; + private int epoch; + private int ttl; public MetaHeader(Version version, int epoch, int ttl) { this.version = version; diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java b/models/src/main/java/info/FrostFS/sdk/dto/OwnerId.java similarity index 94% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java rename to models/src/main/java/info/FrostFS/sdk/dto/OwnerId.java index 723e234..40b4f04 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/OwnerId.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/OwnerId.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto; import info.FrostFS.sdk.Base58; diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java b/models/src/main/java/info/FrostFS/sdk/dto/SessionToken.java similarity index 74% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java rename to models/src/main/java/info/FrostFS/sdk/dto/SessionToken.java index bd4f7b0..5980875 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/SessionToken.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/SessionToken.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto; public class SessionToken { - public byte[] id; - public byte[] sessionKey; + private final byte[] id; + private final byte[] sessionKey; public SessionToken(byte[] id, byte[] sessionKey) { this.id = id; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/Signature.java b/models/src/main/java/info/FrostFS/sdk/dto/Signature.java new file mode 100644 index 0000000..0ab5b3e --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/Signature.java @@ -0,0 +1,33 @@ +package info.FrostFS.sdk.dto; + +import info.FrostFS.sdk.enums.SignatureScheme; + +public class Signature { + private byte[] key; + private byte[] sign; + private SignatureScheme scheme; + + public byte[] getKey() { + return key; + } + + public void setKey(byte[] key) { + this.key = key; + } + + public byte[] getSign() { + return sign; + } + + public void setSign(byte[] sign) { + this.sign = sign; + } + + public SignatureScheme getScheme() { + return scheme; + } + + public void setScheme(SignatureScheme scheme) { + this.scheme = scheme; + } +} diff --git a/models/src/main/java/info/FrostFS/sdk/dto/Split.java b/models/src/main/java/info/FrostFS/sdk/dto/Split.java new file mode 100644 index 0000000..be51331 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/Split.java @@ -0,0 +1,69 @@ +package info.FrostFS.sdk.dto; + +import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.dto.object.ObjectId; + +import java.util.ArrayList; +import java.util.List; + +public class Split { + private final List children; + private SplitId splitId; + private ObjectId parent; + private ObjectId previous; + private Signature parentSignature; + private ObjectHeader parentHeader; + + public Split() { + this(new SplitId()); + } + + public Split(SplitId splitId) { + this.splitId = splitId; + this.children = new ArrayList<>(); + } + + public SplitId getSplitId() { + return splitId; + } + + private void setSplitId(SplitId splitId) { + this.splitId = splitId; + } + + public ObjectId getParent() { + return parent; + } + + public void setParent(ObjectId parent) { + this.parent = parent; + } + + public ObjectId getPrevious() { + return previous; + } + + public void setPrevious(ObjectId previous) { + this.previous = previous; + } + + public Signature getParentSignature() { + return parentSignature; + } + + public void setParentSignature(Signature parentSignature) { + this.parentSignature = parentSignature; + } + + public ObjectHeader getParentHeader() { + return parentHeader; + } + + public void setParentHeader(ObjectHeader parentHeader) { + this.parentHeader = parentHeader; + } + + public List getChildren() { + return children; + } +} diff --git a/models/src/main/java/info/FrostFS/sdk/dto/SplitId.java b/models/src/main/java/info/FrostFS/sdk/dto/SplitId.java new file mode 100644 index 0000000..b01b8d0 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/SplitId.java @@ -0,0 +1,44 @@ +package info.FrostFS.sdk.dto; + +import java.util.UUID; + +import static info.FrostFS.sdk.UUIDExtension.asBytes; +import static info.FrostFS.sdk.UUIDExtension.asUuid; +import static java.util.Objects.isNull; + +public class SplitId { + private final UUID id; + + public SplitId(UUID uuid) { + this.id = uuid; + } + + public SplitId() { + this.id = UUID.randomUUID(); + } + + private SplitId(byte[] binary) { + this.id = asUuid(binary); + } + + private SplitId(String str) { + this.id = UUID.fromString(str); + } + + public static SplitId createFromBinary(byte[] binaryData) { + return new SplitId(binaryData); + } + + public static SplitId createFromString(String stringData) { + return new SplitId(stringData); + } + + @Override + public String toString() { + return id.toString(); + } + + public byte[] toBinary() { + return isNull(id) ? null : asBytes(id); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java b/models/src/main/java/info/FrostFS/sdk/dto/Status.java similarity index 71% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java rename to models/src/main/java/info/FrostFS/sdk/dto/Status.java index bcb6f08..d766546 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Status.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/Status.java @@ -1,16 +1,16 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto; import info.FrostFS.sdk.enums.StatusCode; -import java.util.Optional; +import static java.util.Objects.isNull; public class Status { - public StatusCode code; - public String message; + private StatusCode code; + private String message; public Status(StatusCode code, String message) { this.code = code; - this.message = Optional.ofNullable(message).orElse(""); + this.message = isNull(message) ? "" : message; } public Status(StatusCode code) { @@ -36,7 +36,7 @@ public class Status { @Override public String toString() { - return "Response status: " + code + ". Message: " + message + "."; + return String.format("Response status: %s. Message: %s.", code, message); } public boolean isSuccess() { diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java b/models/src/main/java/info/FrostFS/sdk/dto/Version.java similarity index 88% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java rename to models/src/main/java/info/FrostFS/sdk/dto/Version.java index 22cd8c7..c498b49 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Version.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/Version.java @@ -1,8 +1,13 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto; public class Version { - public int major; - public int minor; + private int major; + private int minor; + + public Version(int major, int minor) { + this.major = major; + this.minor = minor; + } public int getMajor() { return major; @@ -25,11 +30,6 @@ public class Version { return "v" + major + "." + minor; } - public Version(int major, int minor) { - this.major = major; - this.minor = minor; - } - public boolean isSupported(Version version) { return major == version.getMajor(); } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java b/models/src/main/java/info/FrostFS/sdk/dto/container/Container.java similarity index 64% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java rename to models/src/main/java/info/FrostFS/sdk/dto/container/Container.java index 38df197..b952fcf 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/Container.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/container/Container.java @@ -1,15 +1,22 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto.container; +import info.FrostFS.sdk.dto.Version; +import info.FrostFS.sdk.dto.netmap.PlacementPolicy; import info.FrostFS.sdk.enums.BasicAcl; -import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; import java.util.UUID; public class Container { - public UUID nonce; - public BasicAcl basicAcl; - public PlacementPolicy placementPolicy; - public Version version; + private UUID nonce; + private BasicAcl basicAcl; + private PlacementPolicy placementPolicy; + private Version version; + + public Container(BasicAcl basicAcl, PlacementPolicy placementPolicy) { + this.nonce = UUID.randomUUID(); + this.basicAcl = basicAcl; + this.placementPolicy = placementPolicy; + } public UUID getNonce() { return nonce; @@ -42,17 +49,4 @@ public class Container { public void setVersion(Version version) { this.version = version; } - - public Container(BasicAcl basicAcl, PlacementPolicy placementPolicy) { - nonce = UUID.randomUUID(); - this.basicAcl = basicAcl; - this.placementPolicy = placementPolicy; - } - - public Container(BasicAcl basicAcl, PlacementPolicy placementPolicy, UUID nonce, Version version) { - this.nonce = nonce; - this.basicAcl = basicAcl; - this.placementPolicy = placementPolicy; - this.version = version; - } } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java b/models/src/main/java/info/FrostFS/sdk/dto/container/ContainerId.java similarity index 78% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java rename to models/src/main/java/info/FrostFS/sdk/dto/container/ContainerId.java index 309f25b..fd8d529 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ContainerId.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/container/ContainerId.java @@ -1,16 +1,17 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto.container; import info.FrostFS.sdk.Base58; +import info.FrostFS.sdk.constants.AppConst; public class ContainerId { - public String value; + private String value; public ContainerId(String value) { this.value = value; } public static ContainerId fromHash(byte[] hash) { - if (hash.length != Constants.SHA256_HASH_LENGTH) { + if (hash.length != AppConst.SHA256_HASH_LENGTH) { throw new IllegalArgumentException("ContainerID must be a sha256 hash."); } return new ContainerId(Base58.encode(hash)); diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java b/models/src/main/java/info/FrostFS/sdk/dto/netmap/NetmapSnapshot.java similarity index 75% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java rename to models/src/main/java/info/FrostFS/sdk/dto/netmap/NetmapSnapshot.java index 7fd344e..8619f00 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NetmapSnapshot.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/netmap/NetmapSnapshot.java @@ -1,10 +1,10 @@ -package info.FrostFS.sdk.jdo.netmap; +package info.FrostFS.sdk.dto.netmap; import java.util.List; public class NetmapSnapshot { - public Long epoch; - public List nodeInfoCollection; + private final Long epoch; + private final List nodeInfoCollection; public NetmapSnapshot(Long epoch, List nodeInfoCollection) { this.epoch = epoch; diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java b/models/src/main/java/info/FrostFS/sdk/dto/netmap/NodeInfo.java similarity index 66% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java rename to models/src/main/java/info/FrostFS/sdk/dto/netmap/NodeInfo.java index 5b060f1..bd78146 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/NodeInfo.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/netmap/NodeInfo.java @@ -1,17 +1,17 @@ -package info.FrostFS.sdk.jdo.netmap; +package info.FrostFS.sdk.dto.netmap; +import info.FrostFS.sdk.dto.Version; import info.FrostFS.sdk.enums.NodeState; -import info.FrostFS.sdk.jdo.Version; import java.util.List; import java.util.Map; public class NodeInfo { - public NodeState state; - public Version version; - public List addresses; - public Map attributes; - public byte[] publicKey; + private final NodeState state; + private final Version version; + private final List addresses; + private final Map attributes; + private final byte[] publicKey; public NodeInfo(NodeState state, Version version, List addresses, Map attributes, byte[] publicKey) { @@ -26,18 +26,10 @@ public class NodeInfo { return state; } - public void setState(NodeState state) { - this.state = state; - } - public Version getVersion() { return version; } - public void setVersion(Version version) { - this.version = version; - } - public byte[] getPublicKey() { return publicKey; } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java b/models/src/main/java/info/FrostFS/sdk/dto/netmap/PlacementPolicy.java similarity index 52% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java rename to models/src/main/java/info/FrostFS/sdk/dto/netmap/PlacementPolicy.java index d32b585..9e92a63 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/PlacementPolicy.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/netmap/PlacementPolicy.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.jdo.netmap; +package info.FrostFS.sdk.dto.netmap; public class PlacementPolicy { - public Replica[] replicas; - public boolean unique; + private final Replica[] replicas; + private final boolean unique; public PlacementPolicy(boolean unique, Replica[] replicas) { this.replicas = replicas; @@ -13,15 +13,7 @@ public class PlacementPolicy { return replicas; } - public void setReplicas(Replica[] replicas) { - this.replicas = replicas; - } - public boolean isUnique() { return unique; } - - public void setUnique(boolean unique) { - this.unique = unique; - } } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java b/models/src/main/java/info/FrostFS/sdk/dto/netmap/Replica.java similarity index 72% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java rename to models/src/main/java/info/FrostFS/sdk/dto/netmap/Replica.java index 80d1e89..5189df7 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/netmap/Replica.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/netmap/Replica.java @@ -1,14 +1,14 @@ -package info.FrostFS.sdk.jdo.netmap; +package info.FrostFS.sdk.dto.netmap; -import java.util.Optional; +import static java.util.Objects.isNull; public class Replica { - public int count; - public String selector; + private int count; + private String selector; public Replica(int count, String selector) { this.count = count; - this.selector = Optional.ofNullable(selector).orElse(""); + this.selector = isNull(selector) ? "" : selector; } public Replica(int count) { diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java b/models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java new file mode 100644 index 0000000..66d9ad0 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java @@ -0,0 +1,29 @@ +package info.FrostFS.sdk.dto.object; + +import info.FrostFS.sdk.dto.container.ContainerId; + +import java.security.MessageDigest; + +import static info.FrostFS.sdk.Helper.getSha256Instance; + +public class LargeObject extends ObjectFrostFS { + private final MessageDigest payloadHash; + + public LargeObject(ContainerId cid) { + super(cid, new byte[]{}); + this.payloadHash = getSha256Instance(); + } + + public void appendBlock(byte[] bytes, int count) { + this.getHeader().increasePayloadLength(count); + this.payloadHash.update(bytes, 0, count); + } + + public void calculateHash() { + this.getHeader().setPayloadCheckSum(this.payloadHash.digest()); + } + + public long getPayloadLength() { + return getHeader().getPayloadLength(); + } +} diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java b/models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java new file mode 100644 index 0000000..e7b8ea4 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java @@ -0,0 +1,21 @@ +package info.FrostFS.sdk.dto.object; + +import info.FrostFS.sdk.dto.Split; +import info.FrostFS.sdk.dto.SplitId; +import info.FrostFS.sdk.dto.container.ContainerId; + +import java.util.List; + +public class LinkObject extends ObjectFrostFS { + + public LinkObject(ContainerId cid, SplitId splitId, LargeObject largeObject) { + super(cid, new byte[]{}); + var split = new Split(splitId); + split.setParentHeader(largeObject.getHeader()); + this.getHeader().setSplit(split); + } + + public void addChildren(List objectIds) { + this.getHeader().getSplit().getChildren().addAll(objectIds); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectAttribute.java similarity index 82% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java rename to models/src/main/java/info/FrostFS/sdk/dto/object/ObjectAttribute.java index 1a122f4..9729f01 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectAttribute.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectAttribute.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto.object; public class ObjectAttribute { - public String key; - public String value; + private String key; + private String value; public ObjectAttribute(String key, String value) { this.key = key; diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFilter.java similarity index 82% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java rename to models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFilter.java index 0fb1db3..0dae796 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFilter.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFilter.java @@ -1,13 +1,15 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto.object; +import info.FrostFS.sdk.dto.OwnerId; +import info.FrostFS.sdk.dto.Version; import info.FrostFS.sdk.enums.ObjectMatchType; public class ObjectFilter { - private static final String HEADER_PREFIX = "Object:"; + private static final String HEADER_PREFIX = "$Object:"; - public ObjectMatchType matchType; - public String key; - public String value; + private ObjectMatchType matchType; + private String key; + private String value; public ObjectFilter(ObjectMatchType matchType, String key, String value) { @@ -17,7 +19,7 @@ public class ObjectFilter { } public static ObjectFilter ObjectIdFilter(ObjectMatchType matchType, ObjectId objectId) { - return new ObjectFilter(matchType, HEADER_PREFIX + "objectID", objectId.value); + return new ObjectFilter(matchType, HEADER_PREFIX + "objectID", objectId.getValue()); } public static ObjectFilter OwnerFilter(ObjectMatchType matchType, OwnerId ownerId) { diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java new file mode 100644 index 0000000..3b9d3c9 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java @@ -0,0 +1,80 @@ +package info.FrostFS.sdk.dto.object; + +import info.FrostFS.sdk.dto.Split; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.enums.ObjectType; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Objects.isNull; + +public class ObjectFrostFS { + private ObjectHeader header; + private ObjectId objectId; + private byte[] payload; + + public ObjectFrostFS(ObjectHeader header, ObjectId objectId, byte[] payload) { + this.header = header; + this.objectId = objectId; + this.payload = payload; + } + + public ObjectFrostFS(ContainerId container, byte[] payload) { + this.payload = payload; + this.header = new ObjectHeader(container, new ArrayList<>()); + } + + public ObjectFrostFS(ContainerId container, byte[] payload, ObjectType objectType) { + this.payload = payload; + this.header = new ObjectHeader(container, objectType, new ArrayList<>()); + } + + public ObjectHeader getHeader() { + return header; + } + + public void setHeader(ObjectHeader header) { + this.header = header; + } + + public ObjectId getObjectId() { + return objectId; + } + + private void setObjectId(ObjectId objectId) { + this.objectId = objectId; + } + + public byte[] getPayload() { + return payload; + } + + public void setPayload(byte[] payload) { + this.payload = payload; + } + + public void setSplit(Split split) { + header.setSplit(split); + } + + public void addAttribute(String key, String value) { + header.getAttributes().add(new ObjectAttribute(key, value)); + } + + public void addAttribute(ObjectAttribute attribute) { + header.getAttributes().add(attribute); + } + + public void addAttributes(List attributes) { + header.getAttributes().addAll(attributes); + } + + public void setParent(LargeObject largeObject) { + if (isNull(header.getSplit())) { + throw new IllegalArgumentException("The object is not initialized properly"); + } + + header.getSplit().setParentHeader(largeObject.getHeader()); + } +} diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java new file mode 100644 index 0000000..401ed41 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java @@ -0,0 +1,118 @@ +package info.FrostFS.sdk.dto.object; + +import info.FrostFS.sdk.dto.OwnerId; +import info.FrostFS.sdk.dto.Split; +import info.FrostFS.sdk.dto.Version; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.enums.ObjectType; + +import java.util.List; + +public class ObjectHeader { + private List attributes; + private ContainerId containerId; + private long size; + private ObjectType objectType; + private Version version; + private OwnerId ownerId; + private long payloadLength; + private byte[] payloadCheckSum; + private Split split; + + public ObjectHeader(ContainerId containerId, ObjectType objectType, + List attributes, long size, Version version) { + this.attributes = attributes; + this.containerId = containerId; + this.size = size; + this.objectType = objectType; + this.version = version; + } + + public ObjectHeader(ContainerId containerId, ObjectType type, List attributes) { + this.attributes = attributes; + this.containerId = containerId; + this.objectType = type; + } + + public ObjectHeader(ContainerId containerId, List attributes) { + this.attributes = attributes; + this.containerId = containerId; + this.objectType = ObjectType.REGULAR; + } + + public OwnerId getOwnerId() { + return ownerId; + } + + public void setOwnerId(OwnerId ownerId) { + this.ownerId = ownerId; + } + + public long getPayloadLength() { + return payloadLength; + } + + public void setPayloadLength(long payloadLength) { + this.payloadLength = payloadLength; + } + + public void increasePayloadLength(long payloadLength) { + this.payloadLength += payloadLength; + } + + public byte[] getPayloadCheckSum() { + return payloadCheckSum; + } + + public void setPayloadCheckSum(byte[] payloadCheckSum) { + this.payloadCheckSum = payloadCheckSum; + } + + public Split getSplit() { + return split; + } + + public void setSplit(Split split) { + this.split = split; + } + + public List getAttributes() { + return attributes; + } + + public void setAttributes(List attributes) { + this.attributes = attributes; + } + + public ContainerId getContainerId() { + return containerId; + } + + public void setContainerId(ContainerId containerId) { + this.containerId = containerId; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public ObjectType getObjectType() { + return objectType; + } + + public void setObjectType(ObjectType objectType) { + this.objectType = objectType; + } + + public Version getVersion() { + return version; + } + + public void setVersion(Version version) { + this.version = version; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectId.java similarity index 75% rename from modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java rename to models/src/main/java/info/FrostFS/sdk/dto/object/ObjectId.java index 438d027..4b36d80 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectId.java +++ b/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectId.java @@ -1,16 +1,17 @@ -package info.FrostFS.sdk.jdo; +package info.FrostFS.sdk.dto.object; import info.FrostFS.sdk.Base58; +import info.FrostFS.sdk.constants.AppConst; public class ObjectId { - public String value; + private final String value; public ObjectId(String id) { this.value = id; } public static ObjectId fromHash(byte[] hash) { - if (hash.length != Constants.SHA256_HASH_LENGTH) { + if (hash.length != AppConst.SHA256_HASH_LENGTH) { throw new IllegalArgumentException("ObjectId must be a sha256 hash."); } return new ObjectId(Base58.encode(hash)); diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java b/models/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java similarity index 93% rename from modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java rename to models/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java index b454a68..7ebf7f7 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java +++ b/models/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java @@ -28,6 +28,6 @@ public enum BasicAcl { } public static BasicAcl get(int value) { - return ENUM_MAP_BY_VALUE.get(value); + return ENUM_MAP_BY_VALUE.get(value); } } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/NodeState.java b/models/src/main/java/info/FrostFS/sdk/enums/NodeState.java similarity index 100% rename from modelsV2/src/main/java/info/FrostFS/sdk/enums/NodeState.java rename to models/src/main/java/info/FrostFS/sdk/enums/NodeState.java diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java b/models/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java similarity index 100% rename from modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java rename to models/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectType.java b/models/src/main/java/info/FrostFS/sdk/enums/ObjectType.java similarity index 100% rename from modelsV2/src/main/java/info/FrostFS/sdk/enums/ObjectType.java rename to models/src/main/java/info/FrostFS/sdk/enums/ObjectType.java diff --git a/models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java b/models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java new file mode 100644 index 0000000..362c75a --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java @@ -0,0 +1,14 @@ +package info.FrostFS.sdk.enums; + +public enum SignatureScheme { + ECDSA_SHA512(0), + ECDSA_RFC6979_SHA256(1), + ECDSA_RFC6979_SHA256_WALLET_CONNECT(2), + ; + + public final int value; + + SignatureScheme(int value) { + this.value = value; + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/enums/StatusCode.java b/models/src/main/java/info/FrostFS/sdk/enums/StatusCode.java similarity index 100% rename from modelsV2/src/main/java/info/FrostFS/sdk/enums/StatusCode.java rename to models/src/main/java/info/FrostFS/sdk/enums/StatusCode.java diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java similarity index 91% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java index 2d493c4..96371d7 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java @@ -1,7 +1,7 @@ package info.FrostFS.sdk.mappers; import frostFS.session.Types; -import info.FrostFS.sdk.jdo.MetaHeader; +import info.FrostFS.sdk.dto.MetaHeader; public class MetaHeaderMapper { diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java similarity index 89% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java index bc7027c..edf9f1c 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java @@ -2,9 +2,10 @@ package info.FrostFS.sdk.mappers; import com.google.protobuf.ByteString; import frostFS.refs.Types; -import info.FrostFS.sdk.jdo.OwnerId; +import info.FrostFS.sdk.dto.OwnerId; public class OwnerIdMapper { + public static Types.OwnerID toGrpcMessage(OwnerId ownerId) { return Types.OwnerID.newBuilder() .setValue(ByteString.copyFrom(ownerId.toHash())) diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java similarity index 73% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java index f9d7ecd..a8d329d 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java @@ -8,24 +8,22 @@ import java.io.IOException; public class SessionMapper { - public static byte[] serialize(Types.SessionToken token) - { + public static byte[] serialize(Types.SessionToken token) { try { byte[] bytes = new byte[token.getSerializedSize()]; CodedOutputStream stream = CodedOutputStream.newInstance(bytes); token.writeTo(stream); return bytes; - } catch (IOException e) { - throw new IllegalArgumentException(e); + } catch (IOException exp) { + throw new IllegalArgumentException(exp.getMessage()); } } - public static Types.SessionToken deserializeSessionToken(byte[] bytes) - { + public static Types.SessionToken deserializeSessionToken(byte[] bytes) { try { return Types.SessionToken.newBuilder().mergeFrom(bytes).build(); } catch (InvalidProtocolBufferException exp) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException(exp.getMessage()); } } } diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java new file mode 100644 index 0000000..3a388d0 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java @@ -0,0 +1,25 @@ +package info.FrostFS.sdk.mappers; + +import com.google.protobuf.ByteString; +import frostFS.refs.Types; +import info.FrostFS.sdk.dto.Signature; + +import static java.util.Objects.isNull; + +public class SignatureMapper { + + public static Types.Signature ToGrpcMessage(Signature signature) { + var scheme = Types.SignatureScheme.forNumber(signature.getScheme().value); + if (isNull(scheme)) { + throw new IllegalArgumentException( + String.format("Unknown SignatureScheme. Value: %s.", signature.getScheme().name()) + ); + } + + return Types.Signature.newBuilder() + .setKey(ByteString.copyFrom(signature.getKey())) + .setSign(ByteString.copyFrom(signature.getSign())) + .setScheme(scheme) + .build(); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java similarity index 94% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java index 6cb68d7..3817f7d 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java @@ -1,12 +1,13 @@ package info.FrostFS.sdk.mappers; import frostFS.status.Types; +import info.FrostFS.sdk.dto.Status; import info.FrostFS.sdk.enums.StatusCode; -import info.FrostFS.sdk.jdo.Status; import static java.util.Objects.isNull; public class StatusMapper { + public static Status toModel(Types.Status status) { if (isNull(status)) return new Status(StatusCode.SUCCESS); @@ -15,7 +16,6 @@ public class StatusMapper { throw new IllegalArgumentException( String.format("Unknown StatusCode. Value: %s.", status.getCode()) ); - } return new Status(statusCode, status.getMessage()); diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java similarity index 92% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java index 339746a..fefb7ba 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java @@ -1,7 +1,7 @@ package info.FrostFS.sdk.mappers; import frostFS.refs.Types; -import info.FrostFS.sdk.jdo.Version; +import info.FrostFS.sdk.dto.Version; public class VersionMapper { diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerIdMapper.java similarity index 73% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerIdMapper.java index bab5b61..b661e71 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerIdMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerIdMapper.java @@ -1,14 +1,12 @@ -package info.FrostFS.sdk.mappers; +package info.FrostFS.sdk.mappers.container; import com.google.protobuf.ByteString; import frostFS.refs.Types; -import info.FrostFS.sdk.jdo.ContainerId; +import info.FrostFS.sdk.dto.container.ContainerId; public class ContainerIdMapper { public static Types.ContainerID toGrpcMessage(ContainerId containerId) { - var test = containerId.toHash(); - return Types.ContainerID.newBuilder() .setValue(ByteString.copyFrom(containerId.toHash())) .build(); diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerMapper.java similarity index 60% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerMapper.java index 4f1d886..9895eee 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ContainerMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerMapper.java @@ -1,10 +1,10 @@ -package info.FrostFS.sdk.mappers; - +package info.FrostFS.sdk.mappers.container; import com.google.protobuf.ByteString; import frostFS.container.Types; +import info.FrostFS.sdk.dto.container.Container; import info.FrostFS.sdk.enums.BasicAcl; -import info.FrostFS.sdk.jdo.Container; +import info.FrostFS.sdk.mappers.VersionMapper; import info.FrostFS.sdk.mappers.netmap.PlacementPolicyMapper; import static info.FrostFS.sdk.UUIDExtension.asBytes; @@ -21,19 +21,17 @@ public class ContainerMapper { .build(); } - public static Container toModel(Types.Container container) { - var basicAcl = BasicAcl.get(container.getBasicAcl()); + public static Container toModel(Types.Container containerGrpc) { + var basicAcl = BasicAcl.get(containerGrpc.getBasicAcl()); if (isNull(basicAcl)) { throw new IllegalArgumentException( - String.format("Unknown BasicACL rule. Value: %s.", container.getBasicAcl()) + String.format("Unknown BasicACL rule. Value: %s.", containerGrpc.getBasicAcl()) ); } - return new Container( - basicAcl, - PlacementPolicyMapper.toModel(container.getPlacementPolicy()), - asUuid(container.getNonce().toByteArray()), - VersionMapper.toModel(container.getVersion()) - ); + var container = new Container(basicAcl, PlacementPolicyMapper.toModel(containerGrpc.getPlacementPolicy())); + container.setNonce(asUuid(containerGrpc.getNonce().toByteArray())); + container.setVersion(VersionMapper.toModel(containerGrpc.getVersion())); + return container; } } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java similarity index 74% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java index 9d9eb27..d18fc32 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java @@ -1,7 +1,7 @@ package info.FrostFS.sdk.mappers.netmap; import frostFS.netmap.Service; -import info.FrostFS.sdk.jdo.netmap.NetmapSnapshot; +import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; import java.util.stream.Collectors; @@ -11,7 +11,7 @@ public class NetmapSnapshotMapper { return new NetmapSnapshot( netmap.getBody().getNetmap().getEpoch(), netmap.getBody().getNetmap().getNodesList().stream() - .map(t -> NodeInfoMapper.toModel(t, netmap.getMetaHeader().getVersion())) + .map(node -> NodeInfoMapper.toModel(node, netmap.getMetaHeader().getVersion())) .collect(Collectors.toList()) ); } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java similarity index 96% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java index 6c9e25c..53eca35 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java @@ -3,8 +3,8 @@ package info.FrostFS.sdk.mappers.netmap; import frostFS.netmap.Service; import frostFS.netmap.Types.NodeInfo.Attribute; import frostFS.refs.Types; +import info.FrostFS.sdk.dto.netmap.NodeInfo; import info.FrostFS.sdk.enums.NodeState; -import info.FrostFS.sdk.jdo.netmap.NodeInfo; import info.FrostFS.sdk.mappers.VersionMapper; import java.util.stream.Collectors; @@ -12,13 +12,13 @@ import java.util.stream.Collectors; import static java.util.Objects.isNull; public class NodeInfoMapper { + public static NodeInfo toModel(Service.LocalNodeInfoResponse.Body nodeInfo) { return toModel(nodeInfo.getNodeInfo(), nodeInfo.getVersion()); } public static NodeInfo toModel(frostFS.netmap.Types.NodeInfo nodeInfo, Types.Version version) { NodeState nodeState = NodeState.get(nodeInfo.getState().getNumber()); - if (isNull(nodeState)) { throw new IllegalArgumentException( String.format("Unknown NodeState. Value: %s.", nodeInfo.getState()) diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java similarity index 88% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java index 871dfcb..e2803d6 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java @@ -1,10 +1,11 @@ package info.FrostFS.sdk.mappers.netmap; import frostFS.netmap.Types; -import info.FrostFS.sdk.jdo.netmap.PlacementPolicy; -import info.FrostFS.sdk.jdo.netmap.Replica; +import info.FrostFS.sdk.dto.netmap.PlacementPolicy; +import info.FrostFS.sdk.dto.netmap.Replica; public class PlacementPolicyMapper { + public static Types.PlacementPolicy toGrpcMessage(PlacementPolicy placementPolicy) { var pp = Types.PlacementPolicy.newBuilder() .setUnique(placementPolicy.isUnique()); diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java similarity index 91% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java index 93735ff..b2929ba 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java @@ -1,9 +1,10 @@ package info.FrostFS.sdk.mappers.netmap; import frostFS.netmap.Types; -import info.FrostFS.sdk.jdo.netmap.Replica; +import info.FrostFS.sdk.dto.netmap.Replica; public class ReplicaMapper { + public static Types.Replica toGrpcMessage(Replica replica) { return Types.Replica.newBuilder() .setCount(replica.getCount()) diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectAttributeMapper.java similarity index 83% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectAttributeMapper.java index 45489a5..7604e0f 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectAttributeMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectAttributeMapper.java @@ -1,9 +1,10 @@ -package info.FrostFS.sdk.mappers; +package info.FrostFS.sdk.mappers.object; import frostFS.object.Types; -import info.FrostFS.sdk.jdo.ObjectAttribute; +import info.FrostFS.sdk.dto.object.ObjectAttribute; public class ObjectAttributeMapper { + public static Types.Header.Attribute toGrpcMessage(ObjectAttribute attribute) { return Types.Header.Attribute.newBuilder() .setKey(attribute.getKey()) diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFilterMapper.java similarity index 86% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFilterMapper.java index 328de81..52adf8d 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectFilterMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFilterMapper.java @@ -1,13 +1,13 @@ -package info.FrostFS.sdk.mappers; +package info.FrostFS.sdk.mappers.object; import frostFS.object.Service; import frostFS.object.Types; -import info.FrostFS.sdk.jdo.ObjectFilter; -import org.apache.commons.lang3.EnumUtils; +import info.FrostFS.sdk.dto.object.ObjectFilter; import static java.util.Objects.isNull; public class ObjectFilterMapper { + public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter filter) { var objectMatchType = Types.MatchType.forNumber(filter.getMatchType().value); if (isNull(objectMatchType)) { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java new file mode 100644 index 0000000..22cc305 --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java @@ -0,0 +1,16 @@ +package info.FrostFS.sdk.mappers.object; + +import frostFS.object.Types; +import info.FrostFS.sdk.dto.object.ObjectFrostFS; +import info.FrostFS.sdk.dto.object.ObjectId; + +public class ObjectFrostFSMapper { + + public static ObjectFrostFS toModel(Types.Object obj) { + return new ObjectFrostFS( + ObjectHeaderMapper.toModel(obj.getHeader()), + ObjectId.fromHash(obj.getObjectId().getValue().toByteArray()), + obj.getPayload().toByteArray() + ); + } +} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectHeaderMapper.java similarity index 75% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectHeaderMapper.java index ba38b14..d47dc55 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectHeaderMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectHeaderMapper.java @@ -1,17 +1,21 @@ -package info.FrostFS.sdk.mappers; +package info.FrostFS.sdk.mappers.object; import frostFS.object.Types; +import info.FrostFS.sdk.dto.container.ContainerId; +import info.FrostFS.sdk.dto.object.ObjectAttribute; +import info.FrostFS.sdk.dto.object.ObjectHeader; import info.FrostFS.sdk.enums.ObjectType; -import info.FrostFS.sdk.jdo.ContainerId; -import info.FrostFS.sdk.jdo.ObjectAttribute; -import info.FrostFS.sdk.jdo.ObjectHeader; -import org.apache.commons.lang3.EnumUtils; +import info.FrostFS.sdk.mappers.VersionMapper; +import info.FrostFS.sdk.mappers.container.ContainerIdMapper; + +import java.util.stream.Collectors; import static java.util.Objects.isNull; public class ObjectHeaderMapper { + public static Types.Header toGrpcMessage(ObjectHeader header) { - var objectType = EnumUtils.getEnum(Types.ObjectType.class, header.getObjectType().name()); + var objectType = Types.ObjectType.forNumber(header.getObjectType().value); if (isNull(objectType)) { throw new IllegalArgumentException( String.format("Unknown ObjectType. Value: %s.", header.getObjectType().name()) @@ -40,7 +44,7 @@ public class ObjectHeaderMapper { return new ObjectHeader( ContainerId.fromHash(header.getContainerId().getValue().toByteArray()), objectType, - header.getAttributesList().stream().map(ObjectAttributeMapper::toModel).toArray(ObjectAttribute[]::new), + header.getAttributesList().stream().map(ObjectAttributeMapper::toModel).collect(Collectors.toList()), header.getPayloadLength(), VersionMapper.toModel(header.getVersion()) ); diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectIdMapper.java similarity index 57% rename from modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java rename to models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectIdMapper.java index 42200e2..437b4bb 100644 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectIdMapper.java +++ b/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectIdMapper.java @@ -1,13 +1,18 @@ -package info.FrostFS.sdk.mappers; +package info.FrostFS.sdk.mappers.object; import com.google.protobuf.ByteString; import frostFS.refs.Types; -import info.FrostFS.sdk.jdo.ObjectId; +import info.FrostFS.sdk.dto.object.ObjectId; public class ObjectIdMapper { + public static Types.ObjectID toGrpcMessage(ObjectId objectId) { return Types.ObjectID.newBuilder() .setValue(ByteString.copyFrom(objectId.toHash())) .build(); } + + public static ObjectId toModel(Types.ObjectID objectId) { + return ObjectId.fromHash(objectId.getValue().toByteArray()); + } } diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java deleted file mode 100644 index c7cc689..0000000 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectFrostFs.java +++ /dev/null @@ -1,37 +0,0 @@ -package info.FrostFS.sdk.jdo; - -public class ObjectFrostFs { - public ObjectHeader header; - public ObjectId objectId; - public byte[] payload; - - public ObjectFrostFs(ObjectHeader header, ObjectId objectId, byte[] payload) { - this.header = header; - this.objectId = objectId; - this.payload = payload; - } - - public ObjectHeader getHeader() { - return header; - } - - public void setHeader(ObjectHeader header) { - this.header = header; - } - - public ObjectId getObjectId() { - return objectId; - } - - public void setObjectId(ObjectId objectId) { - this.objectId = objectId; - } - - public byte[] getPayload() { - return payload; - } - - public void setPayload(byte[] payload) { - this.payload = payload; - } -} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java b/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java deleted file mode 100644 index 7dc795c..0000000 --- a/modelsV2/src/main/java/info/FrostFS/sdk/jdo/ObjectHeader.java +++ /dev/null @@ -1,71 +0,0 @@ -package info.FrostFS.sdk.jdo; - -import info.FrostFS.sdk.enums.ObjectType; - -public class ObjectHeader { - public ObjectAttribute[] attributes; - public ContainerId containerId; - public long size; - public ObjectType objectType; - public Version version; - - public ObjectHeader(ContainerId containerId, ObjectType objectType, ObjectAttribute[] attributes, long size, Version version) { - this.attributes = attributes; - this.containerId = containerId; - this.size = size; - this.objectType = objectType; - this.version = version; - } - - public ObjectHeader(ContainerId containerId, ObjectType type, ObjectAttribute[] attributes) { - this.attributes = attributes; - this.containerId = containerId; - this.objectType = type; - } - - public ObjectHeader(ContainerId containerId, ObjectAttribute[] attributes) { - this.attributes = attributes; - this.containerId = containerId; - this.objectType = ObjectType.REGULAR; - } - - public ObjectAttribute[] getAttributes() { - return attributes; - } - - public void setAttributes(ObjectAttribute[] attributes) { - this.attributes = attributes; - } - - public ContainerId getContainerId() { - return containerId; - } - - public void setContainerId(ContainerId containerId) { - this.containerId = containerId; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public ObjectType getObjectType() { - return objectType; - } - - public void setObjectType(ObjectType objectType) { - this.objectType = objectType; - } - - public Version getVersion() { - return version; - } - - public void setVersion(Version version) { - this.version = version; - } -} diff --git a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java b/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java deleted file mode 100644 index b970456..0000000 --- a/modelsV2/src/main/java/info/FrostFS/sdk/mappers/ObjectMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package info.FrostFS.sdk.mappers; - -import frostFS.object.Types; -import info.FrostFS.sdk.jdo.ObjectFrostFs; -import info.FrostFS.sdk.jdo.ObjectId; - -public class ObjectMapper { - public static ObjectFrostFs toModel(Types.Object obj) { - return new ObjectFrostFs( - ObjectHeaderMapper.toModel(obj.getHeader()), - ObjectId.fromHash(obj.getObjectId().getValue().toByteArray()), - obj.getPayload().toByteArray() - ); - } -} diff --git a/pom.xml b/pom.xml index 5c16e71..8423cfb 100644 --- a/pom.xml +++ b/pom.xml @@ -9,10 +9,10 @@ 0.1.0 pom - protosV2 client cryptography - modelsV2 + models + protos diff --git a/protosV2/pom.xml b/protos/pom.xml similarity index 98% rename from protosV2/pom.xml rename to protos/pom.xml index d7d8630..cee5fb0 100644 --- a/protosV2/pom.xml +++ b/protos/pom.xml @@ -9,13 +9,13 @@ 0.1.0 - protosV2 + protos 11 11 3.23.0 - 1.62.2 + 1.65.1 UTF-8 diff --git a/protosV2/src/main/proto/accounting/service.proto b/protos/src/main/proto/accounting/service.proto similarity index 100% rename from protosV2/src/main/proto/accounting/service.proto rename to protos/src/main/proto/accounting/service.proto diff --git a/protosV2/src/main/proto/accounting/types.proto b/protos/src/main/proto/accounting/types.proto similarity index 100% rename from protosV2/src/main/proto/accounting/types.proto rename to protos/src/main/proto/accounting/types.proto diff --git a/protosV2/src/main/proto/acl/types.proto b/protos/src/main/proto/acl/types.proto similarity index 100% rename from protosV2/src/main/proto/acl/types.proto rename to protos/src/main/proto/acl/types.proto diff --git a/protosV2/src/main/proto/apemanager/service.proto b/protos/src/main/proto/apemanager/service.proto similarity index 100% rename from protosV2/src/main/proto/apemanager/service.proto rename to protos/src/main/proto/apemanager/service.proto diff --git a/protosV2/src/main/proto/apemanager/types.proto b/protos/src/main/proto/apemanager/types.proto similarity index 100% rename from protosV2/src/main/proto/apemanager/types.proto rename to protos/src/main/proto/apemanager/types.proto diff --git a/protosV2/src/main/proto/container/service.proto b/protos/src/main/proto/container/service.proto similarity index 100% rename from protosV2/src/main/proto/container/service.proto rename to protos/src/main/proto/container/service.proto diff --git a/protosV2/src/main/proto/container/types.proto b/protos/src/main/proto/container/types.proto similarity index 100% rename from protosV2/src/main/proto/container/types.proto rename to protos/src/main/proto/container/types.proto diff --git a/protosV2/src/main/proto/lock/types.proto b/protos/src/main/proto/lock/types.proto similarity index 100% rename from protosV2/src/main/proto/lock/types.proto rename to protos/src/main/proto/lock/types.proto diff --git a/protosV2/src/main/proto/netmap/service.proto b/protos/src/main/proto/netmap/service.proto similarity index 100% rename from protosV2/src/main/proto/netmap/service.proto rename to protos/src/main/proto/netmap/service.proto diff --git a/protosV2/src/main/proto/netmap/types.proto b/protos/src/main/proto/netmap/types.proto similarity index 100% rename from protosV2/src/main/proto/netmap/types.proto rename to protos/src/main/proto/netmap/types.proto diff --git a/protosV2/src/main/proto/object/service.proto b/protos/src/main/proto/object/service.proto similarity index 100% rename from protosV2/src/main/proto/object/service.proto rename to protos/src/main/proto/object/service.proto diff --git a/protosV2/src/main/proto/object/types.proto b/protos/src/main/proto/object/types.proto similarity index 100% rename from protosV2/src/main/proto/object/types.proto rename to protos/src/main/proto/object/types.proto diff --git a/protosV2/src/main/proto/refs/types.proto b/protos/src/main/proto/refs/types.proto similarity index 100% rename from protosV2/src/main/proto/refs/types.proto rename to protos/src/main/proto/refs/types.proto diff --git a/protosV2/src/main/proto/session/service.proto b/protos/src/main/proto/session/service.proto similarity index 100% rename from protosV2/src/main/proto/session/service.proto rename to protos/src/main/proto/session/service.proto diff --git a/protosV2/src/main/proto/session/types.proto b/protos/src/main/proto/session/types.proto similarity index 100% rename from protosV2/src/main/proto/session/types.proto rename to protos/src/main/proto/session/types.proto diff --git a/protosV2/src/main/proto/status/types.proto b/protos/src/main/proto/status/types.proto similarity index 100% rename from protosV2/src/main/proto/status/types.proto rename to protos/src/main/proto/status/types.proto diff --git a/protosV2/src/main/proto/tombstone/types.proto b/protos/src/main/proto/tombstone/types.proto similarity index 100% rename from protosV2/src/main/proto/tombstone/types.proto rename to protos/src/main/proto/tombstone/types.proto -- 2.45.2 From a7fab6f31470f6166734021df2246d4265e1b98b Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Tue, 23 Jul 2024 19:30:07 +0300 Subject: [PATCH 4/7] [#1] code cleanup update README.md Signed-off-by: Ori Bruk --- README.md | 18 ++--- .../src/main/java/info/FrostFS/sdk/Main.java | 67 ------------------- .../FrostFS/sdk/constants/CryptoConst.java | 5 ++ .../sdk/{tools => jdo}/ClientEnvironment.java | 2 +- .../sdk/{tools => jdo}/ClientSettings.java | 2 +- .../FrostFS/sdk/{tools => jdo}/ECDsa.java | 2 +- .../sdk/{tools => jdo}/NetworkSettings.java | 2 +- .../{tools => jdo}/PutObjectParameters.java | 2 +- .../FrostFS/sdk/services/ContextAccessor.java | 2 +- .../FrostFS/sdk/services/FrostFSClient.java | 25 ++++--- .../FrostFS/sdk/services/NetmapClient.java | 2 +- .../FrostFS/sdk/services/ObjectClient.java | 2 +- .../sdk/services/impl/ContainerService.java | 14 ++-- .../sdk/services/impl/NetmapService.java | 10 +-- .../sdk/services/impl/ObjectReader.java | 11 +-- .../sdk/services/impl/ObjectService.java | 23 ++++--- .../sdk/services/impl/ObjectTools.java | 8 +-- .../sdk/services/impl/SearchReader.java | 2 +- .../sdk/services/impl/SessionService.java | 6 +- .../FrostFS/sdk/{ => tools}/GrpcClient.java | 6 +- .../info/FrostFS/sdk/tools/MessageHelper.java | 15 +++++ .../sdk/{ => tools}/RequestConstructor.java | 25 +++---- .../sdk/{ => tools}/RequestSigner.java | 58 ++++++++-------- .../FrostFS/sdk/{ => tools}/Verifier.java | 48 ++++++------- cryptography/pom.xml | 4 +- .../main/java/info/FrostFS/sdk/Helper.java | 4 +- models/pom.xml | 4 +- .../FrostFS/sdk/constants/FieldConst.java | 11 +++ 28 files changed, 177 insertions(+), 203 deletions(-) delete mode 100644 client/src/main/java/info/FrostFS/sdk/Main.java create mode 100644 client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java rename client/src/main/java/info/FrostFS/sdk/{tools => jdo}/ClientEnvironment.java (97%) rename client/src/main/java/info/FrostFS/sdk/{tools => jdo}/ClientSettings.java (97%) rename client/src/main/java/info/FrostFS/sdk/{tools => jdo}/ECDsa.java (95%) rename client/src/main/java/info/FrostFS/sdk/{tools => jdo}/NetworkSettings.java (99%) rename client/src/main/java/info/FrostFS/sdk/{tools => jdo}/PutObjectParameters.java (98%) rename client/src/main/java/info/FrostFS/sdk/{ => tools}/GrpcClient.java (73%) create mode 100644 client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java rename client/src/main/java/info/FrostFS/sdk/{ => tools}/RequestConstructor.java (61%) rename client/src/main/java/info/FrostFS/sdk/{ => tools}/RequestSigner.java (69%) rename client/src/main/java/info/FrostFS/sdk/{ => tools}/Verifier.java (70%) create mode 100644 models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java diff --git a/README.md b/README.md index 94031a8..fec8945 100644 --- a/README.md +++ b/README.md @@ -21,18 +21,18 @@ neo-go wallet export -w -d ### Container ```java -import info.FrostFS.sdk.enums.BasicAcl; import info.FrostFS.sdk.dto.container.Container; import info.FrostFS.sdk.dto.netmap.PlacementPolicy; import info.FrostFS.sdk.dto.netmap.Replica; +import info.FrostFS.sdk.enums.BasicAcl; +import info.FrostFS.sdk.jdo.ClientSettings; import info.FrostFS.sdk.services.FrostFSClient; public class ContainerExample { public void example() { - Client client = new Client( < your_key >); - GrpcClient grpcClient = new GrpcClient( < your_host >); - FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client); + ClientSettings clientSettings = new ClientSettings(, ); + FrostFSClient frostFSClient = new FrostFSClient(clientSettings); // Create container var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)}); @@ -58,6 +58,7 @@ import info.FrostFS.sdk.dto.container.ContainerId; import info.FrostFS.sdk.dto.object.ObjectAttribute; import info.FrostFS.sdk.dto.object.ObjectFilter; import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.FrostFS.sdk.jdo.PutObjectParameters; import info.FrostFS.sdk.services.FrostFSClient; import java.io.FileInputStream; @@ -66,9 +67,8 @@ import java.io.IOException; public class ObjectExample { public void example() { - Client client = new Client( < your_key >); - GrpcClient grpcClient = new GrpcClient( < your_host >); - FrostFSClient frostFSClient = new FrostFSClient(grpcClient, client); + ClientSettings clientSettings = new ClientSettings(, ); + FrostFSClient frostFSClient = new FrostFSClient(clientSettings); // Put object info.FrostFS.sdk.dto.object.ObjectId objectId; @@ -76,7 +76,9 @@ public class ObjectExample { var cat = new ObjectHeader( containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")} ); - objectId = frostFSClient.putObject(cat, fis); + + var params = new PutObjectParameters(cat, fis); + objectId = frostFSClient.putObject(params); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/client/src/main/java/info/FrostFS/sdk/Main.java b/client/src/main/java/info/FrostFS/sdk/Main.java deleted file mode 100644 index 4c854fe..0000000 --- a/client/src/main/java/info/FrostFS/sdk/Main.java +++ /dev/null @@ -1,67 +0,0 @@ -package info.FrostFS.sdk; - -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.enums.BasicAcl; -import info.FrostFS.sdk.enums.ObjectType; -import info.FrostFS.sdk.dto.netmap.PlacementPolicy; -import info.FrostFS.sdk.dto.netmap.Replica; -import info.FrostFS.sdk.dto.object.ObjectAttribute; -import info.FrostFS.sdk.dto.object.ObjectFrostFS; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.dto.object.ObjectId; -import info.FrostFS.sdk.services.FrostFSClient; -import info.FrostFS.sdk.tools.ClientSettings; -import info.FrostFS.sdk.tools.PutObjectParameters; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.util.Collections; -import java.util.List; - -public class Main { - public static void main(String[] args) throws Exception { - ClientSettings clientSettings = new ClientSettings("KwHDAJ66o8FoLBjVbjP2sWBmgBMGjt7Vv4boA7xQrBoAYBE397Aq", "http://localhost:8080"); - FrostFSClient frostFSClient = new FrostFSClient(clientSettings); -/* - var res2 = frostFSClient.searchObjectsAsync(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); -*/ - var placementPolicy = new PlacementPolicy(true, new Replica[]{new Replica(1)}); - var containerId = frostFSClient.createContainer(new Container(BasicAcl.PUBLIC_RW, placementPolicy)); - Thread.sleep(1000); - - FileInputStream file = null; - try { - file = new FileInputStream("/home/ori/Desktop/cat.jpg"); - var cat = new ObjectHeader(containerId, ObjectType.REGULAR, Collections.singletonList(new ObjectAttribute("Filename", "cat3.jpg"))); - - var params = new PutObjectParameters(cat, file, false, 1024); - var tty = frostFSClient.putObject(params); - - System.out.println(1); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - - - var res = frostFSClient.searchObjects(containerId); - - ObjectFrostFS res3 = frostFSClient - .getObject(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R"), new ObjectId("85orCLKSu3X1jGiTFmwmTUsBU88RBARNwuRwrEy5pyww")); - - - var ttttt = frostFSClient.getNetworkSettings(); - Container container2 = frostFSClient.getContainer(new ContainerId("EQGx2QeYHJb53uRwYGzcQaW191sZpdNrjutk6veUSV2R")); - - - - - Container container = frostFSClient.getContainer(containerId); - List containerIds = frostFSClient.listContainers(); -/* - frostFSClient.deleteContainerAsync(containerId); -*/ - containerIds = frostFSClient.listContainers(); - System.out.println(); - } -} \ No newline at end of file diff --git a/client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java b/client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java new file mode 100644 index 0000000..742ef60 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java @@ -0,0 +1,5 @@ +package info.FrostFS.sdk.constants; + +public class CryptoConst { + public static final String SIGNATURE_ALGORITHM = "NONEwithECDSAinP1363Format"; +} diff --git a/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java b/client/src/main/java/info/FrostFS/sdk/jdo/ClientEnvironment.java similarity index 97% rename from client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java rename to client/src/main/java/info/FrostFS/sdk/jdo/ClientEnvironment.java index ee1d8d4..f770057 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/ClientEnvironment.java +++ b/client/src/main/java/info/FrostFS/sdk/jdo/ClientEnvironment.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.FrostFS.sdk.jdo; import info.FrostFS.sdk.dto.OwnerId; import info.FrostFS.sdk.dto.Version; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/ClientSettings.java b/client/src/main/java/info/FrostFS/sdk/jdo/ClientSettings.java similarity index 97% rename from client/src/main/java/info/FrostFS/sdk/tools/ClientSettings.java rename to client/src/main/java/info/FrostFS/sdk/jdo/ClientSettings.java index 2b25083..c7f5de0 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/ClientSettings.java +++ b/client/src/main/java/info/FrostFS/sdk/jdo/ClientSettings.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.FrostFS.sdk.jdo; import io.grpc.ChannelCredentials; import org.apache.commons.lang3.StringUtils; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java b/client/src/main/java/info/FrostFS/sdk/jdo/ECDsa.java similarity index 95% rename from client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java rename to client/src/main/java/info/FrostFS/sdk/jdo/ECDsa.java index 98ccfc0..e3afee7 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/ECDsa.java +++ b/client/src/main/java/info/FrostFS/sdk/jdo/ECDsa.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.FrostFS.sdk.jdo; import java.security.PrivateKey; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java b/client/src/main/java/info/FrostFS/sdk/jdo/NetworkSettings.java similarity index 99% rename from client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java rename to client/src/main/java/info/FrostFS/sdk/jdo/NetworkSettings.java index d6971b3..680d3d3 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/NetworkSettings.java +++ b/client/src/main/java/info/FrostFS/sdk/jdo/NetworkSettings.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.FrostFS.sdk.jdo; import java.util.HashMap; import java.util.Map; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java b/client/src/main/java/info/FrostFS/sdk/jdo/PutObjectParameters.java similarity index 98% rename from client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java rename to client/src/main/java/info/FrostFS/sdk/jdo/PutObjectParameters.java index ca62737..51082a3 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/PutObjectParameters.java +++ b/client/src/main/java/info/FrostFS/sdk/jdo/PutObjectParameters.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.FrostFS.sdk.jdo; import info.FrostFS.sdk.dto.object.ObjectHeader; diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java b/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java index d3880a9..58f9c43 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java +++ b/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java @@ -1,6 +1,6 @@ package info.FrostFS.sdk.services; -import info.FrostFS.sdk.tools.ClientEnvironment; +import info.FrostFS.sdk.jdo.ClientEnvironment; public class ContextAccessor { private final ClientEnvironment context; diff --git a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java b/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java index 64ba93c..b0c7f1b 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java @@ -1,29 +1,32 @@ package info.FrostFS.sdk.services; import frostFS.session.Types; -import info.FrostFS.sdk.tools.ClientSettings; -import info.FrostFS.sdk.tools.PutObjectParameters; -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.dto.container.ContainerId; import info.FrostFS.sdk.dto.SessionToken; import info.FrostFS.sdk.dto.Version; +import info.FrostFS.sdk.dto.container.Container; +import info.FrostFS.sdk.dto.container.ContainerId; import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; import info.FrostFS.sdk.dto.netmap.NodeInfo; import info.FrostFS.sdk.dto.object.ObjectFilter; import info.FrostFS.sdk.dto.object.ObjectFrostFS; import info.FrostFS.sdk.dto.object.ObjectHeader; import info.FrostFS.sdk.dto.object.ObjectId; +import info.FrostFS.sdk.jdo.ClientEnvironment; +import info.FrostFS.sdk.jdo.ClientSettings; +import info.FrostFS.sdk.jdo.NetworkSettings; +import info.FrostFS.sdk.jdo.PutObjectParameters; import info.FrostFS.sdk.services.impl.*; -import info.FrostFS.sdk.tools.ClientEnvironment; -import info.FrostFS.sdk.tools.NetworkSettings; import io.grpc.Channel; import java.util.List; -import static info.FrostFS.sdk.GrpcClient.initGrpcChannel; +import static info.FrostFS.sdk.tools.GrpcClient.initGrpcChannel; import static java.util.Objects.isNull; public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient { + private static final String ERROR_CLIENT_OPTIONS_INIT = "Options must be initialized."; + private static final String ERROR_VERSION_SUPPORT_TEMPLATE = "FrostFS %s is not supported."; + private final ContainerService containerService; private final NetmapService netmapService; private final ObjectService objectService; @@ -32,7 +35,7 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien public FrostFSClient(ClientSettings clientSettings) { if (isNull(clientSettings)) { - throw new IllegalArgumentException("Options must be initialized"); + throw new IllegalArgumentException(ERROR_CLIENT_OPTIONS_INIT); } clientSettings.validate(); @@ -53,9 +56,9 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien private void checkFrostFsVersionSupport(Version version) { var localNodeInfo = netmapService.getLocalNodeInfo(); if (!localNodeInfo.getVersion().isSupported(version)) { - var msg = String.format("FrostFS %s is not supported.", localNodeInfo.getVersion()); - System.out.println(msg); - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException( + String.format(ERROR_VERSION_SUPPORT_TEMPLATE, localNodeInfo.getVersion()) + ); } } diff --git a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java index 80bbf1e..f053dfa 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java @@ -2,7 +2,7 @@ package info.FrostFS.sdk.services; import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; import info.FrostFS.sdk.dto.netmap.NodeInfo; -import info.FrostFS.sdk.tools.NetworkSettings; +import info.FrostFS.sdk.jdo.NetworkSettings; public interface NetmapClient { NetmapSnapshot getNetmapSnapshot(); diff --git a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java b/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java index f19fb61..96ae2a3 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java +++ b/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java @@ -1,11 +1,11 @@ package info.FrostFS.sdk.services; import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.tools.PutObjectParameters; import info.FrostFS.sdk.dto.object.ObjectFilter; import info.FrostFS.sdk.dto.object.ObjectFrostFS; import info.FrostFS.sdk.dto.object.ObjectHeader; import info.FrostFS.sdk.dto.object.ObjectId; +import info.FrostFS.sdk.jdo.PutObjectParameters; public interface ObjectClient { ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId); diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java index 4383579..a1df64c 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java @@ -2,23 +2,23 @@ package info.FrostFS.sdk.services.impl; import frostFS.container.ContainerServiceGrpc; import frostFS.container.Service; -import info.FrostFS.sdk.Verifier; import info.FrostFS.sdk.dto.container.Container; import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.mappers.container.ContainerIdMapper; -import info.FrostFS.sdk.mappers.container.ContainerMapper; +import info.FrostFS.sdk.jdo.ClientEnvironment; import info.FrostFS.sdk.mappers.OwnerIdMapper; import info.FrostFS.sdk.mappers.VersionMapper; +import info.FrostFS.sdk.mappers.container.ContainerIdMapper; +import info.FrostFS.sdk.mappers.container.ContainerMapper; import info.FrostFS.sdk.services.ContainerClient; import info.FrostFS.sdk.services.ContextAccessor; -import info.FrostFS.sdk.tools.ClientEnvironment; +import info.FrostFS.sdk.tools.Verifier; import java.util.List; import java.util.stream.Collectors; -import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.RequestSigner.sign; -import static info.FrostFS.sdk.RequestSigner.signRFC6979; +import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.tools.RequestSigner.sign; +import static info.FrostFS.sdk.tools.RequestSigner.signRFC6979; public class ContainerService extends ContextAccessor implements ContainerClient { private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub; diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java index e55c655..135e95b 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java @@ -3,20 +3,20 @@ package info.FrostFS.sdk.services.impl; import frostFS.netmap.NetmapServiceGrpc; import frostFS.netmap.Service; import frostFS.netmap.Types; -import info.FrostFS.sdk.Verifier; import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; import info.FrostFS.sdk.dto.netmap.NodeInfo; +import info.FrostFS.sdk.jdo.ClientEnvironment; +import info.FrostFS.sdk.jdo.NetworkSettings; import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper; import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper; import info.FrostFS.sdk.services.ContextAccessor; import info.FrostFS.sdk.services.NetmapClient; -import info.FrostFS.sdk.tools.ClientEnvironment; -import info.FrostFS.sdk.tools.NetworkSettings; +import info.FrostFS.sdk.tools.Verifier; import java.nio.charset.StandardCharsets; -import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.RequestSigner.sign; +import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.tools.RequestSigner.sign; import static java.util.Objects.nonNull; public class NetmapService extends ContextAccessor implements NetmapClient { diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java index 8350bd7..116b3c2 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java @@ -2,11 +2,14 @@ package info.FrostFS.sdk.services.impl; import frostFS.object.Service; import frostFS.object.Types; -import info.FrostFS.sdk.Verifier; +import info.FrostFS.sdk.tools.Verifier; import java.util.Iterator; public class ObjectReader { + public static final String ERROR_UNEXPECTED_STREAM = "unexpected end of stream"; + public static final String ERROR_UNEXPECTED_MESSAGE_TYPE = "unexpected message type"; + public Iterator call; public ObjectReader(Iterator call) { @@ -15,14 +18,14 @@ public class ObjectReader { public Types.Object readHeader() { if (!call.hasNext()) { - throw new IllegalArgumentException("unexpected end of stream"); + throw new IllegalArgumentException(ERROR_UNEXPECTED_STREAM); } var response = call.next(); Verifier.checkResponse(response); if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.INIT_FIELD_NUMBER) { - throw new IllegalArgumentException("unexpected message type"); + throw new IllegalArgumentException(ERROR_UNEXPECTED_MESSAGE_TYPE); } return Types.Object.newBuilder() @@ -40,7 +43,7 @@ public class ObjectReader { Verifier.checkResponse(response); if (response.getBody().getObjectPartCase().getNumber() != Service.GetResponse.Body.CHUNK_FIELD_NUMBER) { - throw new IllegalArgumentException("unexpected message type"); + throw new IllegalArgumentException(ERROR_UNEXPECTED_MESSAGE_TYPE); } return response.getBody().getChunk().toByteArray(); diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java index 4fbe78d..c9520e3 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java @@ -5,21 +5,22 @@ import com.google.protobuf.ByteString; import frostFS.object.ObjectServiceGrpc; import frostFS.object.Service; import frostFS.refs.Types; -import info.FrostFS.sdk.Verifier; import info.FrostFS.sdk.constants.AppConst; -import info.FrostFS.sdk.dto.container.ContainerId; import info.FrostFS.sdk.dto.Split; +import info.FrostFS.sdk.dto.container.ContainerId; import info.FrostFS.sdk.dto.object.*; -import info.FrostFS.sdk.mappers.*; +import info.FrostFS.sdk.jdo.ClientEnvironment; +import info.FrostFS.sdk.jdo.PutObjectParameters; +import info.FrostFS.sdk.mappers.OwnerIdMapper; +import info.FrostFS.sdk.mappers.VersionMapper; import info.FrostFS.sdk.mappers.container.ContainerIdMapper; import info.FrostFS.sdk.mappers.object.ObjectFilterMapper; +import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper; import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; import info.FrostFS.sdk.mappers.object.ObjectIdMapper; -import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper; import info.FrostFS.sdk.services.ContextAccessor; import info.FrostFS.sdk.services.ObjectClient; -import info.FrostFS.sdk.tools.ClientEnvironment; -import info.FrostFS.sdk.tools.PutObjectParameters; +import info.FrostFS.sdk.tools.Verifier; import org.apache.commons.collections4.CollectionUtils; import java.io.FileInputStream; @@ -29,12 +30,14 @@ import java.util.Arrays; import java.util.List; import static info.FrostFS.sdk.Helper.getSha256; -import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.RequestConstructor.addObjectSessionToken; -import static info.FrostFS.sdk.RequestSigner.sign; +import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.tools.RequestConstructor.addObjectSessionToken; +import static info.FrostFS.sdk.tools.RequestSigner.sign; import static java.util.Objects.nonNull; public class ObjectService extends ContextAccessor implements ObjectClient { + private static final String ERROR_PAYLOAD = "PayloadLength must be specified"; + private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; private final ObjectTools objectTools; @@ -257,7 +260,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { var objectSize = (int) Math.min(payloadSize, networkSettings.getMaxObjectSize()); var fullLength = header.getPayloadLength() == 0 ? payloadSize : header.getPayloadLength(); if (fullLength == 0) { - throw new IllegalArgumentException("Payload stream must be able to seek or PayloadLength must be specified"); + throw new IllegalArgumentException(ERROR_PAYLOAD); } var buffer = new byte[objectSize]; diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java index 31fbebd..412fa66 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java @@ -5,17 +5,17 @@ import frostFS.object.Types; import info.FrostFS.sdk.dto.object.ObjectFrostFS; import info.FrostFS.sdk.dto.object.ObjectHeader; import info.FrostFS.sdk.dto.object.ObjectId; -import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; -import info.FrostFS.sdk.mappers.object.ObjectIdMapper; +import info.FrostFS.sdk.jdo.ClientEnvironment; import info.FrostFS.sdk.mappers.OwnerIdMapper; import info.FrostFS.sdk.mappers.VersionMapper; +import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; +import info.FrostFS.sdk.mappers.object.ObjectIdMapper; import info.FrostFS.sdk.services.ContextAccessor; import info.FrostFS.sdk.services.ToolsClient; -import info.FrostFS.sdk.tools.ClientEnvironment; import org.apache.commons.collections4.ListUtils; import static info.FrostFS.sdk.Helper.getSha256; -import static info.FrostFS.sdk.RequestSigner.signData; +import static info.FrostFS.sdk.tools.RequestSigner.signData; import static java.util.Objects.nonNull; public class ObjectTools extends ContextAccessor implements ToolsClient { diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java b/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java index b0d3620..864d6e5 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java @@ -1,7 +1,7 @@ package info.FrostFS.sdk.services.impl; import frostFS.object.Service; -import info.FrostFS.sdk.Verifier; +import info.FrostFS.sdk.tools.Verifier; import java.util.Iterator; import java.util.List; diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java index cae3cb6..35e5967 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java +++ b/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java @@ -4,14 +4,14 @@ import frostFS.session.Service; import frostFS.session.SessionServiceGrpc; import frostFS.session.Types; import info.FrostFS.sdk.dto.SessionToken; +import info.FrostFS.sdk.jdo.ClientEnvironment; import info.FrostFS.sdk.mappers.OwnerIdMapper; import info.FrostFS.sdk.mappers.SessionMapper; import info.FrostFS.sdk.services.ContextAccessor; import info.FrostFS.sdk.services.SessionClient; -import info.FrostFS.sdk.tools.ClientEnvironment; -import static info.FrostFS.sdk.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.RequestSigner.sign; +import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; +import static info.FrostFS.sdk.tools.RequestSigner.sign; public class SessionService extends ContextAccessor implements SessionClient { private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub; diff --git a/client/src/main/java/info/FrostFS/sdk/GrpcClient.java b/client/src/main/java/info/FrostFS/sdk/tools/GrpcClient.java similarity index 73% rename from client/src/main/java/info/FrostFS/sdk/GrpcClient.java rename to client/src/main/java/info/FrostFS/sdk/tools/GrpcClient.java index 9062017..61cfee2 100644 --- a/client/src/main/java/info/FrostFS/sdk/GrpcClient.java +++ b/client/src/main/java/info/FrostFS/sdk/tools/GrpcClient.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk; +package info.FrostFS.sdk.tools; import io.grpc.Channel; import io.grpc.ChannelCredentials; @@ -10,6 +10,7 @@ import java.net.URISyntaxException; import static java.util.Objects.isNull; public class GrpcClient { + private static final String ERROR_INVALID_HOST_TEMPLATE = "Host %s has invalid format. Error: %s"; public static Channel initGrpcChannel(String host, ChannelCredentials creds) { try { @@ -19,8 +20,7 @@ public class GrpcClient { return channelBuilder.usePlaintext().build(); } catch (URISyntaxException exp) { - var message = String.format("Host %s has invalid format. Error: %s", host, exp.getMessage()); - throw new IllegalArgumentException(message); + throw new IllegalArgumentException(String.format(ERROR_INVALID_HOST_TEMPLATE, host, exp.getMessage())); } } } diff --git a/client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java b/client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java new file mode 100644 index 0000000..4e11b06 --- /dev/null +++ b/client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java @@ -0,0 +1,15 @@ +package info.FrostFS.sdk.tools; + +import com.google.protobuf.Message; +import com.google.protobuf.MessageOrBuilder; + +public class MessageHelper { + + public static Message getField(MessageOrBuilder messageOrBuilder, String fieldName) { + return (Message) messageOrBuilder.getField(messageOrBuilder.getDescriptorForType().findFieldByName(fieldName)); + } + + public static void setField(Message.Builder builder, String fieldName, Object value) { + builder.setField(builder.getDescriptorForType().findFieldByName(fieldName), value); + } +} diff --git a/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java b/client/src/main/java/info/FrostFS/sdk/tools/RequestConstructor.java similarity index 61% rename from client/src/main/java/info/FrostFS/sdk/RequestConstructor.java rename to client/src/main/java/info/FrostFS/sdk/tools/RequestConstructor.java index 28daecc..3d8d02a 100644 --- a/client/src/main/java/info/FrostFS/sdk/RequestConstructor.java +++ b/client/src/main/java/info/FrostFS/sdk/tools/RequestConstructor.java @@ -1,36 +1,37 @@ -package info.FrostFS.sdk; +package info.FrostFS.sdk.tools; -import com.google.protobuf.AbstractMessage; +import com.google.protobuf.Message; import frostFS.session.Types; import info.FrostFS.sdk.dto.MetaHeader; +import info.FrostFS.sdk.jdo.ECDsa; import info.FrostFS.sdk.mappers.MetaHeaderMapper; -import info.FrostFS.sdk.tools.ECDsa; -import static info.FrostFS.sdk.RequestSigner.signMessagePart; +import static info.FrostFS.sdk.constants.FieldConst.META_HEADER_FIELD_NAME; +import static info.FrostFS.sdk.tools.MessageHelper.getField; +import static info.FrostFS.sdk.tools.MessageHelper.setField; +import static info.FrostFS.sdk.tools.RequestSigner.signMessagePart; import static java.util.Objects.isNull; public class RequestConstructor { - public static void addMetaHeader(AbstractMessage.Builder request) { + public static void addMetaHeader(Message.Builder request) { addMetaHeader(request, null); } - public static void addMetaHeader(AbstractMessage.Builder request, Types.RequestMetaHeader metaHeader) { + public static void addMetaHeader(Message.Builder request, Types.RequestMetaHeader metaHeader) { if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) { metaHeader = MetaHeaderMapper.toGrpcMessage(MetaHeader.getDefault()); - var field = request.getDescriptorForType().findFieldByName("meta_header"); - request.setField(field, metaHeader); + setField(request, META_HEADER_FIELD_NAME, metaHeader); } } - public static void addObjectSessionToken(AbstractMessage.Builder request, + public static void addObjectSessionToken(Message.Builder request, Types.SessionToken sessionToken, frostFS.refs.Types.ContainerID cid, frostFS.refs.Types.ObjectID oid, Types.ObjectSessionContext.Verb verb, ECDsa key) { - var headerField = request.getDescriptorForType().findFieldByName("meta_header"); - var header = (Types.RequestMetaHeader) request.getField(headerField); + var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME); if (header.getSessionToken().getSerializedSize() > 0) { return; } @@ -46,6 +47,6 @@ public class RequestConstructor { .setBody(body) .build(); - request.setField(headerField, header.toBuilder().setSessionToken(sessionToken).build()); + setField(request, META_HEADER_FIELD_NAME, header.toBuilder().setSessionToken(sessionToken).build()); } } diff --git a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java b/client/src/main/java/info/FrostFS/sdk/tools/RequestSigner.java similarity index 69% rename from client/src/main/java/info/FrostFS/sdk/RequestSigner.java rename to client/src/main/java/info/FrostFS/sdk/tools/RequestSigner.java index a26dadf..daca2cc 100644 --- a/client/src/main/java/info/FrostFS/sdk/RequestSigner.java +++ b/client/src/main/java/info/FrostFS/sdk/tools/RequestSigner.java @@ -1,9 +1,9 @@ -package info.FrostFS.sdk; +package info.FrostFS.sdk.tools; -import com.google.protobuf.AbstractMessage; import com.google.protobuf.ByteString; +import com.google.protobuf.Message; import frostFS.session.Types; -import info.FrostFS.sdk.tools.ECDsa; +import info.FrostFS.sdk.jdo.ECDsa; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -15,17 +15,22 @@ import org.bouncycastle.crypto.signers.HMacDSAKCalculator; import java.math.BigInteger; import java.security.Signature; +import static info.FrostFS.sdk.constants.CryptoConst.SIGNATURE_ALGORITHM; +import static info.FrostFS.sdk.constants.FieldConst.*; +import static info.FrostFS.sdk.tools.MessageHelper.getField; +import static info.FrostFS.sdk.tools.MessageHelper.setField; import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; public class RequestSigner { + public static final String ERROR_UNSUPPORTED_TYPE_TEMPLATE = "Unsupported message type: %s"; public static final int RFC6979_SIGNATURE_SIZE = 64; public static byte[] signData(ECDsa key, byte[] data) { var hash = new byte[65]; hash[0] = 0x04; try { - Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format"); + Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(key.getPrivateKey()); signature.update(DigestUtils.sha512(data)); byte[] sig = signature.sign(); @@ -62,7 +67,7 @@ public class RequestSigner { return signature; } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, AbstractMessage message) { + public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, Message message) { return frostFS.refs.Types.SignatureRFC6979.newBuilder() .setKey(ByteString.copyFrom(key.getPublicKeyByte())) .setSign(ByteString.copyFrom(signRFC6979(key, message.toByteArray()))) @@ -76,7 +81,7 @@ public class RequestSigner { .build(); } - public static frostFS.refs.Types.Signature signMessagePart(ECDsa key, AbstractMessage data) { + public static frostFS.refs.Types.Signature signMessagePart(ECDsa key, Message data) { var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); return frostFS.refs.Types.Signature.newBuilder() .setKey(ByteString.copyFrom(key.getPublicKeyByte())) @@ -84,39 +89,32 @@ public class RequestSigner { .build(); } - public static void sign(AbstractMessage.Builder request, ECDsa key) { - var meta = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("meta_header")); - var body = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("body")); - var verify = (AbstractMessage) request.getField(request.getDescriptorForType().findFieldByName("verify_header")); + public static void sign(Message.Builder request, ECDsa key) { + var meta = getField(request, META_HEADER_FIELD_NAME); + var body = getField(request, BODY_FIELD_NAME); + var verify = getField(request, VERIFY_HEADER_FIELD_NAME); + var verifyOrigin = getField(verify, ORIGIN_FIELD_NAME); - AbstractMessage.Builder verifyBuilder; + Message.Builder verifyBuilder; if (verify instanceof Types.RequestVerificationHeader) { verifyBuilder = Types.RequestVerificationHeader.newBuilder(); } else if (verify instanceof Types.ResponseVerificationHeader) { verifyBuilder = Types.ResponseVerificationHeader.newBuilder(); } else { - throw new IllegalArgumentException("Unsopported message type"); - } - - var verifyOrigin = (AbstractMessage) verify.getField(verify.getDescriptorForType().findFieldByName("origin")); - if (verifyOrigin.getSerializedSize() == 0) { - verifyBuilder.setField( - verifyBuilder.getDescriptorForType().findFieldByName("body_signature"), - signMessagePart(key, body) + throw new IllegalArgumentException( + String.format(ERROR_UNSUPPORTED_TYPE_TEMPLATE, verify.getClass().getName()) ); - } else { - verifyBuilder.setField(verifyBuilder.getDescriptorForType().findFieldByName("origin"), verifyOrigin); } - verifyBuilder.setField( - verifyBuilder.getDescriptorForType().findFieldByName("meta_signature"), - signMessagePart(key, meta) - ); - verifyBuilder.setField( - verifyBuilder.getDescriptorForType().findFieldByName("origin_signature"), - signMessagePart(key, verifyOrigin) - ); + if (verifyOrigin.getSerializedSize() == 0) { + setField(verifyBuilder, BODY_SIGNATURE_FIELD_NAME, signMessagePart(key, body)); + } else { + setField(verifyBuilder, ORIGIN_FIELD_NAME, verifyOrigin); + } - request.setField(request.getDescriptorForType().findFieldByName("verify_header"), verifyBuilder.build()); + setField(verifyBuilder, META_SIGNATURE_FIELD_NAME, signMessagePart(key, meta)); + setField(verifyBuilder, ORIGIN_SIGNATURE_FIELD_NAME, signMessagePart(key, verifyOrigin)); + setField(request, VERIFY_HEADER_FIELD_NAME, verifyBuilder.build()); } + } diff --git a/client/src/main/java/info/FrostFS/sdk/Verifier.java b/client/src/main/java/info/FrostFS/sdk/tools/Verifier.java similarity index 70% rename from client/src/main/java/info/FrostFS/sdk/Verifier.java rename to client/src/main/java/info/FrostFS/sdk/tools/Verifier.java index e0c37ec..14e7327 100644 --- a/client/src/main/java/info/FrostFS/sdk/Verifier.java +++ b/client/src/main/java/info/FrostFS/sdk/tools/Verifier.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk; +package info.FrostFS.sdk.tools; -import com.google.protobuf.AbstractMessage; -import frostFS.refs.Types; +import com.google.protobuf.Message; +import frostFS.session.Types; import info.FrostFS.sdk.mappers.StatusMapper; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; @@ -17,17 +17,20 @@ import java.security.Signature; import java.util.Arrays; import static info.FrostFS.sdk.KeyExtension.getPublicKeyFromBytes; +import static info.FrostFS.sdk.constants.CryptoConst.SIGNATURE_ALGORITHM; +import static info.FrostFS.sdk.constants.FieldConst.*; +import static info.FrostFS.sdk.tools.MessageHelper.getField; import static java.util.Objects.isNull; import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; public class Verifier { + public static final String ERROR_WRONG_SIG_SIZE_TEMPLATE = "Wrong signature size. Expected length=%s, actual=%s"; + public static final String ERROR_INVALID_RESPONSE = "Invalid response"; public static final int RFC6979_SIG_SIZE = 64; - public static boolean verifyRFC6979(Types.SignatureRFC6979 signature, AbstractMessage message) { - return verifyRFC6979( - signature.getKey().toByteArray(), message.toByteArray(), signature.getSign().toByteArray() - ); + public static boolean verifyRFC6979(frostFS.refs.Types.SignatureRFC6979 signature, Message data) { + return verifyRFC6979(signature.getKey().toByteArray(), data.toByteArray(), signature.getSign().toByteArray()); } public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) { @@ -49,8 +52,7 @@ public class Verifier { private static BigInteger[] decodeSignature(byte[] sig) { if (sig.length != RFC6979_SIG_SIZE) { throw new IllegalArgumentException( - String.format("Wrong signature size. Expected length=%s, actual=%s", - RFC6979_SIG_SIZE, sig.length) + String.format(ERROR_WRONG_SIG_SIZE_TEMPLATE, RFC6979_SIG_SIZE, sig.length) ); } @@ -61,42 +63,40 @@ public class Verifier { return rs; } - public static void checkResponse(AbstractMessage response) { + public static void checkResponse(Message response) { if (!verify(response)) { - throw new IllegalArgumentException("Invalid response"); + throw new IllegalArgumentException(ERROR_INVALID_RESPONSE); } - var metaHeader = (frostFS.session.Types.ResponseMetaHeader) response - .getField(response.getDescriptorForType().findFieldByName("meta_header")); + + var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME); var status = StatusMapper.toModel(metaHeader.getStatus()); if (!status.isSuccess()) { throw new IllegalArgumentException(status.toString()); } } - public static boolean verify(AbstractMessage message) { - var body = (AbstractMessage) message.getField(message.getDescriptorForType().findFieldByName("body")); - var metaHeader = (frostFS.session.Types.ResponseMetaHeader) - message.getField(message.getDescriptorForType().findFieldByName("meta_header")); - var verifyHeader = (frostFS.session.Types.ResponseVerificationHeader) - message.getField(message.getDescriptorForType().findFieldByName("verify_header")); + public static boolean verify(Message response) { + var body = getField(response, BODY_FIELD_NAME); + var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME); + var verifyHeader = (Types.ResponseVerificationHeader) getField(response, VERIFY_HEADER_FIELD_NAME); return verifyMatryoshkaLevel(body, metaHeader, verifyHeader); } - public static boolean verifyMatryoshkaLevel(AbstractMessage body, + public static boolean verifyMatryoshkaLevel(Message data, frostFS.session.Types.ResponseMetaHeader meta, frostFS.session.Types.ResponseVerificationHeader verification) { if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false; var origin = verification.getOrigin(); if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false; if (origin.getSerializedSize() == 0) { - return verifyMessagePart(verification.getBodySignature(), body); + return verifyMessagePart(verification.getBodySignature(), data); } return verification.getBodySignature().getSerializedSize() == 0 - && verifyMatryoshkaLevel(body, meta.getOrigin(), origin); + && verifyMatryoshkaLevel(data, meta.getOrigin(), origin); } - public static boolean verifyMessagePart(Types.Signature sig, AbstractMessage data) { + public static boolean verifyMessagePart(frostFS.refs.Types.Signature sig, Message data) { if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false; var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray()); @@ -107,7 +107,7 @@ public class Verifier { public static boolean verifyData(PublicKey publicKey, byte[] data, byte[] sig) { try { - Signature signature = Signature.getInstance("NONEwithECDSAinP1363Format"); + Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicKey); signature.update(DigestUtils.sha512(data)); return signature.verify(Arrays.copyOfRange(sig, 1, sig.length)); diff --git a/cryptography/pom.xml b/cryptography/pom.xml index 9c18d69..f92accd 100644 --- a/cryptography/pom.xml +++ b/cryptography/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java b/cryptography/src/main/java/info/FrostFS/sdk/Helper.java index fb11ac2..083121b 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java +++ b/cryptography/src/main/java/info/FrostFS/sdk/Helper.java @@ -1,7 +1,7 @@ package info.FrostFS.sdk; -import com.google.protobuf.AbstractMessage; import com.google.protobuf.ByteString; +import com.google.protobuf.Message; import org.bouncycastle.crypto.digests.RIPEMD160Digest; import java.math.BigInteger; @@ -30,7 +30,7 @@ public class Helper { return getSha256Instance().digest(value); } - public static ByteString getSha256(AbstractMessage value) { + public static ByteString getSha256(Message value) { return ByteString.copyFrom(getSha256(value.toByteArray())); } diff --git a/models/pom.xml b/models/pom.xml index 7f9af60..1f04f5e 100644 --- a/models/pom.xml +++ b/models/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java b/models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java new file mode 100644 index 0000000..761258a --- /dev/null +++ b/models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java @@ -0,0 +1,11 @@ +package info.FrostFS.sdk.constants; + +public class FieldConst { + public static final String META_HEADER_FIELD_NAME = "meta_header"; + public static final String META_SIGNATURE_FIELD_NAME = "meta_signature"; + public static final String BODY_FIELD_NAME = "body"; + public static final String BODY_SIGNATURE_FIELD_NAME = "body_signature"; + public static final String ORIGIN_FIELD_NAME = "origin"; + public static final String ORIGIN_SIGNATURE_FIELD_NAME = "origin_signature"; + public static final String VERIFY_HEADER_FIELD_NAME = "verify_header"; +} -- 2.45.2 From bf2f19f08dcd36ff2cb9dd6591e759c4c2e50945 Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Tue, 23 Jul 2024 22:24:17 +0300 Subject: [PATCH 5/7] [#1] provide naming conventions Signed-off-by: Ori Bruk --- README.md | 28 +++++----- client/pom.xml | 8 +-- .../FrostFS/sdk/services/NetmapClient.java | 13 ----- .../FrostFS/sdk/services/ToolsClient.java | 8 --- .../sdk/constants/CryptoConst.java | 2 +- .../sdk/jdo/ClientEnvironment.java | 8 +-- .../sdk/jdo/ClientSettings.java | 2 +- .../{FrostFS => frostfs}/sdk/jdo/ECDsa.java | 4 +- .../sdk/jdo/NetworkSettings.java | 2 +- .../sdk/jdo/PutObjectParameters.java | 4 +- .../sdk/services/ContainerClient.java | 6 +- .../sdk/services/ContextAccessor.java | 4 +- .../sdk/services/FrostFSClient.java | 36 ++++++------ .../frostfs/sdk/services/NetmapClient.java | 13 +++++ .../sdk/services/ObjectClient.java | 14 ++--- .../sdk/services/SessionClient.java | 4 +- .../frostfs/sdk/services/ToolsClient.java | 8 +++ .../sdk/services/impl/ContainerService.java | 53 +++++++++--------- .../sdk/services/impl/NetmapService.java | 30 +++++----- .../sdk/services/impl/ObjectReader.java | 8 +-- .../sdk/services/impl/ObjectService.java | 56 +++++++++---------- .../sdk/services/impl/ObjectTools.java | 44 +++++++-------- .../sdk/services/impl/ObjectWriter.java | 6 +- .../sdk/services/impl/SearchReader.java | 8 +-- .../sdk/services/impl/SessionService.java | 27 ++++----- .../sdk/tools/GrpcClient.java | 2 +- .../sdk/tools/MessageHelper.java | 2 +- .../sdk/tools/RequestConstructor.java | 22 ++++---- .../sdk/tools/RequestSigner.java | 44 +++++++-------- .../sdk/tools/Verifier.java | 31 +++++----- cryptography/pom.xml | 4 +- .../{FrostFS => frostfs}/sdk/ArrayHelper.java | 2 +- .../info/{FrostFS => frostfs}/sdk/Base58.java | 6 +- .../info/{FrostFS => frostfs}/sdk/Helper.java | 2 +- .../sdk/KeyExtension.java | 6 +- models/pom.xml | 8 +-- .../sdk/UUIDExtension.java | 2 +- .../sdk/constants/AppConst.java | 2 +- .../sdk/constants/FieldConst.java | 2 +- .../sdk/constants/XHeaderConst.java | 2 +- .../sdk/dto/MetaHeader.java | 2 +- .../{FrostFS => frostfs}/sdk/dto/OwnerId.java | 6 +- .../sdk/dto/SessionToken.java | 2 +- .../sdk/dto/Signature.java | 4 +- .../{FrostFS => frostfs}/sdk/dto/Split.java | 6 +- .../{FrostFS => frostfs}/sdk/dto/SplitId.java | 6 +- .../{FrostFS => frostfs}/sdk/dto/Status.java | 4 +- .../{FrostFS => frostfs}/sdk/dto/Version.java | 2 +- .../sdk/dto/container/Container.java | 8 +-- .../sdk/dto/container/ContainerId.java | 6 +- .../sdk/dto/netmap/NetmapSnapshot.java | 2 +- .../sdk/dto/netmap/NodeInfo.java | 6 +- .../sdk/dto/netmap/PlacementPolicy.java | 2 +- .../sdk/dto/netmap/Replica.java | 2 +- .../sdk/dto/object/LargeObject.java | 6 +- .../sdk/dto/object/LinkObject.java | 8 +-- .../sdk/dto/object/ObjectAttribute.java | 2 +- .../sdk/dto/object/ObjectFilter.java | 8 +-- .../sdk/dto/object/ObjectFrostFS.java | 8 +-- .../sdk/dto/object/ObjectHeader.java | 12 ++-- .../sdk/dto/object/ObjectId.java | 6 +- .../sdk/enums/BasicAcl.java | 2 +- .../sdk/enums/NodeState.java | 2 +- .../sdk/enums/ObjectMatchType.java | 2 +- .../sdk/enums/ObjectType.java | 2 +- .../sdk/enums/SignatureScheme.java | 2 +- .../sdk/enums/StatusCode.java | 2 +- .../sdk/mappers/MetaHeaderMapper.java | 6 +- .../sdk/mappers/OwnerIdMapper.java | 6 +- .../sdk/mappers/SessionMapper.java | 4 +- .../sdk/mappers/SignatureMapper.java | 6 +- .../sdk/mappers/StatusMapper.java | 8 +-- .../sdk/mappers/VersionMapper.java | 6 +- .../mappers/container/ContainerIdMapper.java | 6 +- .../mappers/container/ContainerMapper.java | 16 +++--- .../mappers/netmap/NetmapSnapshotMapper.java | 6 +- .../sdk/mappers/netmap/NodeInfoMapper.java | 16 +++--- .../mappers/netmap/PlacementPolicyMapper.java | 8 +-- .../sdk/mappers/netmap/ReplicaMapper.java | 6 +- .../mappers/object/ObjectAttributeMapper.java | 6 +- .../mappers/object/ObjectFilterMapper.java | 8 +-- .../mappers/object/ObjectFrostFSMapper.java | 8 +-- .../mappers/object/ObjectHeaderMapper.java | 16 +++--- .../sdk/mappers/object/ObjectIdMapper.java | 6 +- pom.xml | 4 +- protos/pom.xml | 4 +- .../src/main/proto/accounting/service.proto | 2 +- protos/src/main/proto/accounting/types.proto | 2 +- protos/src/main/proto/acl/types.proto | 2 +- .../src/main/proto/apemanager/service.proto | 2 +- protos/src/main/proto/apemanager/types.proto | 2 +- protos/src/main/proto/container/service.proto | 2 +- protos/src/main/proto/container/types.proto | 2 +- protos/src/main/proto/lock/types.proto | 2 +- protos/src/main/proto/netmap/service.proto | 2 +- protos/src/main/proto/netmap/types.proto | 2 +- protos/src/main/proto/object/service.proto | 2 +- protos/src/main/proto/object/types.proto | 2 +- protos/src/main/proto/refs/types.proto | 2 +- protos/src/main/proto/session/service.proto | 2 +- protos/src/main/proto/session/types.proto | 2 +- protos/src/main/proto/status/types.proto | 2 +- protos/src/main/proto/tombstone/types.proto | 2 +- 103 files changed, 416 insertions(+), 417 deletions(-) delete mode 100644 client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java delete mode 100644 client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java rename client/src/main/java/info/{FrostFS => frostfs}/sdk/constants/CryptoConst.java (75%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/jdo/ClientEnvironment.java (88%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/jdo/ClientSettings.java (97%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/jdo/ECDsa.java (88%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/jdo/NetworkSettings.java (99%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/jdo/PutObjectParameters.java (96%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/ContainerClient.java (64%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/ContextAccessor.java (75%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/FrostFSClient.java (82%) create mode 100644 client/src/main/java/info/frostfs/sdk/services/NetmapClient.java rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/ObjectClient.java (54%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/SessionClient.java (52%) create mode 100644 client/src/main/java/info/frostfs/sdk/services/ToolsClient.java rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/ContainerService.java (68%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/NetmapService.java (86%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/ObjectReader.java (91%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/ObjectService.java (90%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/ObjectTools.java (75%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/ObjectWriter.java (93%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/SearchReader.java (72%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/services/impl/SessionService.java (75%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/tools/GrpcClient.java (96%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/tools/MessageHelper.java (94%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/tools/RequestConstructor.java (74%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/tools/RequestSigner.java (72%) rename client/src/main/java/info/{FrostFS => frostfs}/sdk/tools/Verifier.java (80%) rename cryptography/src/main/java/info/{FrostFS => frostfs}/sdk/ArrayHelper.java (93%) rename cryptography/src/main/java/info/{FrostFS => frostfs}/sdk/Base58.java (97%) rename cryptography/src/main/java/info/{FrostFS => frostfs}/sdk/Helper.java (97%) rename cryptography/src/main/java/info/{FrostFS => frostfs}/sdk/KeyExtension.java (98%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/UUIDExtension.java (95%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/constants/AppConst.java (79%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/constants/FieldConst.java (93%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/constants/XHeaderConst.java (89%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/MetaHeader.java (96%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/OwnerId.java (75%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/SessionToken.java (91%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/Signature.java (87%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/Split.java (91%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/SplitId.java (85%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/Status.java (92%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/Version.java (95%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/container/Container.java (86%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/container/ContainerId.java (85%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/netmap/NetmapSnapshot.java (92%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/netmap/NodeInfo.java (89%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/netmap/PlacementPolicy.java (90%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/netmap/Replica.java (94%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/LargeObject.java (81%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/LinkObject.java (74%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/ObjectAttribute.java (92%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/ObjectFilter.java (90%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/ObjectFrostFS.java (92%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/ObjectHeader.java (91%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/dto/object/ObjectId.java (83%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/enums/BasicAcl.java (95%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/enums/NodeState.java (95%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/enums/ObjectMatchType.java (87%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/enums/ObjectType.java (95%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/enums/SignatureScheme.java (87%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/enums/StatusCode.java (97%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/MetaHeaderMapper.java (78%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/OwnerIdMapper.java (73%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/SessionMapper.java (93%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/SignatureMapper.java (87%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/StatusMapper.java (78%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/VersionMapper.java (80%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/container/ContainerIdMapper.java (71%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/container/ContainerMapper.java (75%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/netmap/NetmapSnapshotMapper.java (80%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/netmap/NodeInfoMapper.java (72%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/netmap/PlacementPolicyMapper.java (80%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/netmap/ReplicaMapper.java (78%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/object/ObjectAttributeMapper.java (79%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/object/ObjectFilterMapper.java (82%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/object/ObjectFrostFSMapper.java (67%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/object/ObjectHeaderMapper.java (80%) rename models/src/main/java/info/{FrostFS => frostfs}/sdk/mappers/object/ObjectIdMapper.java (78%) diff --git a/README.md b/README.md index fec8945..ff4652e 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,12 @@ neo-go wallet export -w -d ### Container ```java -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.dto.netmap.PlacementPolicy; -import info.FrostFS.sdk.dto.netmap.Replica; -import info.FrostFS.sdk.enums.BasicAcl; -import info.FrostFS.sdk.jdo.ClientSettings; -import info.FrostFS.sdk.services.FrostFSClient; +import info.frostfs.sdk.dto.container.Container; +import info.frostfs.sdk.dto.netmap.PlacementPolicy; +import info.frostfs.sdk.dto.netmap.Replica; +import info.frostfs.sdk.enums.BasicAcl; +import info.frostfs.sdk.jdo.ClientSettings; +import info.frostfs.sdk.services.FrostFSClient; public class ContainerExample { @@ -53,13 +53,13 @@ public class ContainerExample { ### Object ```java -import info.FrostFS.sdk.enums.ObjectType; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.dto.object.ObjectAttribute; -import info.FrostFS.sdk.dto.object.ObjectFilter; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.jdo.PutObjectParameters; -import info.FrostFS.sdk.services.FrostFSClient; +import info.frostfs.sdk.enums.ObjectType; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.object.ObjectAttribute; +import info.frostfs.sdk.dto.object.ObjectFilter; +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.jdo.PutObjectParameters; +import info.frostfs.sdk.services.FrostFSClient; import java.io.FileInputStream; import java.io.IOException; @@ -71,7 +71,7 @@ public class ObjectExample { FrostFSClient frostFSClient = new FrostFSClient(clientSettings); // Put object - info.FrostFS.sdk.dto.object.ObjectId objectId; + info.frostfs.sdk.dto.object.ObjectId objectId; try (FileInputStream fis = new FileInputStream("cat.jpg")) { var cat = new ObjectHeader( containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")} diff --git a/client/pom.xml b/client/pom.xml index 3d3426e..917fc46 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - info.FrostFS.sdk - FrostFS-sdk-java + info.frostfs.sdk + frostfs-sdk-java 0.1.0 @@ -19,12 +19,12 @@ - info.FrostFS.sdk + info.frostfs.sdk cryptography 0.1.0 - info.FrostFS.sdk + info.frostfs.sdk models 0.1.0 diff --git a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java b/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java deleted file mode 100644 index f053dfa..0000000 --- a/client/src/main/java/info/FrostFS/sdk/services/NetmapClient.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.FrostFS.sdk.services; - -import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; -import info.FrostFS.sdk.dto.netmap.NodeInfo; -import info.FrostFS.sdk.jdo.NetworkSettings; - -public interface NetmapClient { - NetmapSnapshot getNetmapSnapshot(); - - NodeInfo getLocalNodeInfo(); - - NetworkSettings getNetworkSettings(); -} diff --git a/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java b/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java deleted file mode 100644 index fb673a2..0000000 --- a/client/src/main/java/info/FrostFS/sdk/services/ToolsClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.FrostFS.sdk.services; - -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.dto.object.ObjectId; - -public interface ToolsClient { - ObjectId calculateObjectId(ObjectHeader header); -} diff --git a/client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java b/client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java similarity index 75% rename from client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java rename to client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java index 742ef60..84db5c9 100644 --- a/client/src/main/java/info/FrostFS/sdk/constants/CryptoConst.java +++ b/client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.constants; +package info.frostfs.sdk.constants; public class CryptoConst { public static final String SIGNATURE_ALGORITHM = "NONEwithECDSAinP1363Format"; diff --git a/client/src/main/java/info/FrostFS/sdk/jdo/ClientEnvironment.java b/client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java similarity index 88% rename from client/src/main/java/info/FrostFS/sdk/jdo/ClientEnvironment.java rename to client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java index f770057..2165f06 100644 --- a/client/src/main/java/info/FrostFS/sdk/jdo/ClientEnvironment.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.jdo; +package info.frostfs.sdk.jdo; -import info.FrostFS.sdk.dto.OwnerId; -import info.FrostFS.sdk.dto.Version; -import info.FrostFS.sdk.services.FrostFSClient; +import info.frostfs.sdk.dto.OwnerId; +import info.frostfs.sdk.dto.Version; +import info.frostfs.sdk.services.FrostFSClient; import io.grpc.Channel; public class ClientEnvironment { diff --git a/client/src/main/java/info/FrostFS/sdk/jdo/ClientSettings.java b/client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java similarity index 97% rename from client/src/main/java/info/FrostFS/sdk/jdo/ClientSettings.java rename to client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java index c7f5de0..03b83ad 100644 --- a/client/src/main/java/info/FrostFS/sdk/jdo/ClientSettings.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.jdo; +package info.frostfs.sdk.jdo; import io.grpc.ChannelCredentials; import org.apache.commons.lang3.StringUtils; diff --git a/client/src/main/java/info/FrostFS/sdk/jdo/ECDsa.java b/client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java similarity index 88% rename from client/src/main/java/info/FrostFS/sdk/jdo/ECDsa.java rename to client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java index e3afee7..060eef9 100644 --- a/client/src/main/java/info/FrostFS/sdk/jdo/ECDsa.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.jdo; +package info.frostfs.sdk.jdo; import java.security.PrivateKey; -import static info.FrostFS.sdk.KeyExtension.*; +import static info.frostfs.sdk.KeyExtension.*; public class ECDsa { private final byte[] publicKeyByte; diff --git a/client/src/main/java/info/FrostFS/sdk/jdo/NetworkSettings.java b/client/src/main/java/info/frostfs/sdk/jdo/NetworkSettings.java similarity index 99% rename from client/src/main/java/info/FrostFS/sdk/jdo/NetworkSettings.java rename to client/src/main/java/info/frostfs/sdk/jdo/NetworkSettings.java index 680d3d3..1ed01a6 100644 --- a/client/src/main/java/info/FrostFS/sdk/jdo/NetworkSettings.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/NetworkSettings.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.jdo; +package info.frostfs.sdk.jdo; import java.util.HashMap; import java.util.Map; diff --git a/client/src/main/java/info/FrostFS/sdk/jdo/PutObjectParameters.java b/client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java similarity index 96% rename from client/src/main/java/info/FrostFS/sdk/jdo/PutObjectParameters.java rename to client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java index 51082a3..cd3338d 100644 --- a/client/src/main/java/info/FrostFS/sdk/jdo/PutObjectParameters.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java @@ -1,6 +1,6 @@ -package info.FrostFS.sdk.jdo; +package info.frostfs.sdk.jdo; -import info.FrostFS.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectHeader; import java.io.FileInputStream; diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java b/client/src/main/java/info/frostfs/sdk/services/ContainerClient.java similarity index 64% rename from client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java rename to client/src/main/java/info/frostfs/sdk/services/ContainerClient.java index 385f616..d3f7f9c 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ContainerClient.java +++ b/client/src/main/java/info/frostfs/sdk/services/ContainerClient.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.services; +package info.frostfs.sdk.services; -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.container.Container; +import info.frostfs.sdk.dto.container.ContainerId; import java.util.List; diff --git a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java b/client/src/main/java/info/frostfs/sdk/services/ContextAccessor.java similarity index 75% rename from client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java rename to client/src/main/java/info/frostfs/sdk/services/ContextAccessor.java index 58f9c43..72c47dd 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ContextAccessor.java +++ b/client/src/main/java/info/frostfs/sdk/services/ContextAccessor.java @@ -1,6 +1,6 @@ -package info.FrostFS.sdk.services; +package info.frostfs.sdk.services; -import info.FrostFS.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.jdo.ClientEnvironment; public class ContextAccessor { private final ClientEnvironment context; diff --git a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java b/client/src/main/java/info/frostfs/sdk/services/FrostFSClient.java similarity index 82% rename from client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java rename to client/src/main/java/info/frostfs/sdk/services/FrostFSClient.java index b0c7f1b..da87a20 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/FrostFSClient.java +++ b/client/src/main/java/info/frostfs/sdk/services/FrostFSClient.java @@ -1,26 +1,26 @@ -package info.FrostFS.sdk.services; +package info.frostfs.sdk.services; -import frostFS.session.Types; -import info.FrostFS.sdk.dto.SessionToken; -import info.FrostFS.sdk.dto.Version; -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; -import info.FrostFS.sdk.dto.netmap.NodeInfo; -import info.FrostFS.sdk.dto.object.ObjectFilter; -import info.FrostFS.sdk.dto.object.ObjectFrostFS; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.dto.object.ObjectId; -import info.FrostFS.sdk.jdo.ClientEnvironment; -import info.FrostFS.sdk.jdo.ClientSettings; -import info.FrostFS.sdk.jdo.NetworkSettings; -import info.FrostFS.sdk.jdo.PutObjectParameters; -import info.FrostFS.sdk.services.impl.*; +import frostfs.session.Types; +import info.frostfs.sdk.dto.SessionToken; +import info.frostfs.sdk.dto.Version; +import info.frostfs.sdk.dto.container.Container; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.netmap.NetmapSnapshot; +import info.frostfs.sdk.dto.netmap.NodeInfo; +import info.frostfs.sdk.dto.object.ObjectFilter; +import info.frostfs.sdk.dto.object.ObjectFrostFS; +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectId; +import info.frostfs.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.jdo.ClientSettings; +import info.frostfs.sdk.jdo.NetworkSettings; +import info.frostfs.sdk.jdo.PutObjectParameters; +import info.frostfs.sdk.services.impl.*; import io.grpc.Channel; import java.util.List; -import static info.FrostFS.sdk.tools.GrpcClient.initGrpcChannel; +import static info.frostfs.sdk.tools.GrpcClient.initGrpcChannel; import static java.util.Objects.isNull; public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClient, SessionClient, ToolsClient { diff --git a/client/src/main/java/info/frostfs/sdk/services/NetmapClient.java b/client/src/main/java/info/frostfs/sdk/services/NetmapClient.java new file mode 100644 index 0000000..bc34978 --- /dev/null +++ b/client/src/main/java/info/frostfs/sdk/services/NetmapClient.java @@ -0,0 +1,13 @@ +package info.frostfs.sdk.services; + +import info.frostfs.sdk.dto.netmap.NetmapSnapshot; +import info.frostfs.sdk.dto.netmap.NodeInfo; +import info.frostfs.sdk.jdo.NetworkSettings; + +public interface NetmapClient { + NetmapSnapshot getNetmapSnapshot(); + + NodeInfo getLocalNodeInfo(); + + NetworkSettings getNetworkSettings(); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java b/client/src/main/java/info/frostfs/sdk/services/ObjectClient.java similarity index 54% rename from client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java rename to client/src/main/java/info/frostfs/sdk/services/ObjectClient.java index 96ae2a3..423e938 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/ObjectClient.java +++ b/client/src/main/java/info/frostfs/sdk/services/ObjectClient.java @@ -1,11 +1,11 @@ -package info.FrostFS.sdk.services; +package info.frostfs.sdk.services; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.dto.object.ObjectFilter; -import info.FrostFS.sdk.dto.object.ObjectFrostFS; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.dto.object.ObjectId; -import info.FrostFS.sdk.jdo.PutObjectParameters; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.object.ObjectFilter; +import info.frostfs.sdk.dto.object.ObjectFrostFS; +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectId; +import info.frostfs.sdk.jdo.PutObjectParameters; public interface ObjectClient { ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId); diff --git a/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java b/client/src/main/java/info/frostfs/sdk/services/SessionClient.java similarity index 52% rename from client/src/main/java/info/FrostFS/sdk/services/SessionClient.java rename to client/src/main/java/info/frostfs/sdk/services/SessionClient.java index 6fd7f4f..16e0da0 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/SessionClient.java +++ b/client/src/main/java/info/frostfs/sdk/services/SessionClient.java @@ -1,6 +1,6 @@ -package info.FrostFS.sdk.services; +package info.frostfs.sdk.services; -import info.FrostFS.sdk.dto.SessionToken; +import info.frostfs.sdk.dto.SessionToken; public interface SessionClient { SessionToken createSession(long expiration); diff --git a/client/src/main/java/info/frostfs/sdk/services/ToolsClient.java b/client/src/main/java/info/frostfs/sdk/services/ToolsClient.java new file mode 100644 index 0000000..e8ce342 --- /dev/null +++ b/client/src/main/java/info/frostfs/sdk/services/ToolsClient.java @@ -0,0 +1,8 @@ +package info.frostfs.sdk.services; + +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectId; + +public interface ToolsClient { + ObjectId calculateObjectId(ObjectHeader header); +} diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java b/client/src/main/java/info/frostfs/sdk/services/impl/ContainerService.java similarity index 68% rename from client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ContainerService.java index a1df64c..1e2f5e7 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ContainerService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ContainerService.java @@ -1,24 +1,25 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; -import frostFS.container.ContainerServiceGrpc; -import frostFS.container.Service; -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.jdo.ClientEnvironment; -import info.FrostFS.sdk.mappers.OwnerIdMapper; -import info.FrostFS.sdk.mappers.VersionMapper; -import info.FrostFS.sdk.mappers.container.ContainerIdMapper; -import info.FrostFS.sdk.mappers.container.ContainerMapper; -import info.FrostFS.sdk.services.ContainerClient; -import info.FrostFS.sdk.services.ContextAccessor; -import info.FrostFS.sdk.tools.Verifier; +import frostfs.container.ContainerServiceGrpc; +import frostfs.container.Service; +import info.frostfs.sdk.dto.container.Container; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.mappers.OwnerIdMapper; +import info.frostfs.sdk.mappers.VersionMapper; +import info.frostfs.sdk.mappers.container.ContainerIdMapper; +import info.frostfs.sdk.mappers.container.ContainerMapper; +import info.frostfs.sdk.services.ContainerClient; +import info.frostfs.sdk.services.ContextAccessor; +import info.frostfs.sdk.tools.Verifier; +import info.frostfs.sdk.tools.RequestConstructor; +import info.frostfs.sdk.tools.RequestSigner; import java.util.List; import java.util.stream.Collectors; -import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.tools.RequestSigner.sign; -import static info.FrostFS.sdk.tools.RequestSigner.signRFC6979; +import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; +import static info.frostfs.sdk.tools.RequestSigner.signRFC6979; public class ContainerService extends ContextAccessor implements ContainerClient { private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub; @@ -36,8 +37,8 @@ public class ContainerService extends ContextAccessor implements ContainerClient .build() ); - addMetaHeader(request); - sign(request, getContext().getKey()); + RequestConstructor.addMetaHeader(request); + RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.get(request.build()); @@ -53,8 +54,8 @@ public class ContainerService extends ContextAccessor implements ContainerClient .build() ); - addMetaHeader(request); - sign(request, getContext().getKey()); + RequestConstructor.addMetaHeader(request); + RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.list(request.build()); @@ -78,13 +79,13 @@ public class ContainerService extends ContextAccessor implements ContainerClient Service.PutRequest.Body.newBuilder() .setContainer(grpcContainer) .setSignature( - signRFC6979(getContext().getKey(), grpcContainer) + RequestSigner.signRFC6979(getContext().getKey(), grpcContainer) ) .build() ); - addMetaHeader(request); - sign(request, getContext().getKey()); + RequestConstructor.addMetaHeader(request); + RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.put(request.build()); @@ -99,14 +100,14 @@ public class ContainerService extends ContextAccessor implements ContainerClient .setBody( Service.DeleteRequest.Body.newBuilder() .setContainerId(grpcContainerId) - .setSignature(signRFC6979( + .setSignature(RequestSigner.signRFC6979( getContext().getKey(), grpcContainerId.getValue() )) .build() ); - addMetaHeader(request); - sign(request, getContext().getKey()); + RequestConstructor.addMetaHeader(request); + RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.delete(request.build()); diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java b/client/src/main/java/info/frostfs/sdk/services/impl/NetmapService.java similarity index 86% rename from client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/NetmapService.java index 135e95b..19c5995 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/NetmapService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/NetmapService.java @@ -1,22 +1,22 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; -import frostFS.netmap.NetmapServiceGrpc; -import frostFS.netmap.Service; -import frostFS.netmap.Types; -import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; -import info.FrostFS.sdk.dto.netmap.NodeInfo; -import info.FrostFS.sdk.jdo.ClientEnvironment; -import info.FrostFS.sdk.jdo.NetworkSettings; -import info.FrostFS.sdk.mappers.netmap.NetmapSnapshotMapper; -import info.FrostFS.sdk.mappers.netmap.NodeInfoMapper; -import info.FrostFS.sdk.services.ContextAccessor; -import info.FrostFS.sdk.services.NetmapClient; -import info.FrostFS.sdk.tools.Verifier; +import frostfs.netmap.NetmapServiceGrpc; +import frostfs.netmap.Service; +import frostfs.netmap.Types; +import info.frostfs.sdk.dto.netmap.NetmapSnapshot; +import info.frostfs.sdk.dto.netmap.NodeInfo; +import info.frostfs.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.jdo.NetworkSettings; +import info.frostfs.sdk.mappers.netmap.NetmapSnapshotMapper; +import info.frostfs.sdk.mappers.netmap.NodeInfoMapper; +import info.frostfs.sdk.services.ContextAccessor; +import info.frostfs.sdk.services.NetmapClient; +import info.frostfs.sdk.tools.Verifier; import java.nio.charset.StandardCharsets; -import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.tools.RequestSigner.sign; +import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; +import static info.frostfs.sdk.tools.RequestSigner.sign; import static java.util.Objects.nonNull; public class NetmapService extends ContextAccessor implements NetmapClient { diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectReader.java similarity index 91% rename from client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ObjectReader.java index 116b3c2..62a9a70 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectReader.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectReader.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; -import frostFS.object.Service; -import frostFS.object.Types; -import info.FrostFS.sdk.tools.Verifier; +import frostfs.object.Service; +import frostfs.object.Types; +import info.frostfs.sdk.tools.Verifier; import java.util.Iterator; diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectService.java similarity index 90% rename from client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ObjectService.java index c9520e3..ca2652b 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectService.java @@ -1,26 +1,26 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; import com.google.common.collect.Iterables; import com.google.protobuf.ByteString; -import frostFS.object.ObjectServiceGrpc; -import frostFS.object.Service; -import frostFS.refs.Types; -import info.FrostFS.sdk.constants.AppConst; -import info.FrostFS.sdk.dto.Split; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.dto.object.*; -import info.FrostFS.sdk.jdo.ClientEnvironment; -import info.FrostFS.sdk.jdo.PutObjectParameters; -import info.FrostFS.sdk.mappers.OwnerIdMapper; -import info.FrostFS.sdk.mappers.VersionMapper; -import info.FrostFS.sdk.mappers.container.ContainerIdMapper; -import info.FrostFS.sdk.mappers.object.ObjectFilterMapper; -import info.FrostFS.sdk.mappers.object.ObjectFrostFSMapper; -import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; -import info.FrostFS.sdk.mappers.object.ObjectIdMapper; -import info.FrostFS.sdk.services.ContextAccessor; -import info.FrostFS.sdk.services.ObjectClient; -import info.FrostFS.sdk.tools.Verifier; +import frostfs.object.ObjectServiceGrpc; +import frostfs.object.Service; +import frostfs.refs.Types; +import info.frostfs.sdk.constants.AppConst; +import info.frostfs.sdk.dto.Split; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.object.*; +import info.frostfs.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.jdo.PutObjectParameters; +import info.frostfs.sdk.mappers.OwnerIdMapper; +import info.frostfs.sdk.mappers.VersionMapper; +import info.frostfs.sdk.mappers.container.ContainerIdMapper; +import info.frostfs.sdk.mappers.object.ObjectFilterMapper; +import info.frostfs.sdk.mappers.object.ObjectFrostFSMapper; +import info.frostfs.sdk.mappers.object.ObjectHeaderMapper; +import info.frostfs.sdk.mappers.object.ObjectIdMapper; +import info.frostfs.sdk.services.ContextAccessor; +import info.frostfs.sdk.services.ObjectClient; +import info.frostfs.sdk.tools.Verifier; import org.apache.commons.collections4.CollectionUtils; import java.io.FileInputStream; @@ -29,10 +29,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static info.FrostFS.sdk.Helper.getSha256; -import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.tools.RequestConstructor.addObjectSessionToken; -import static info.FrostFS.sdk.tools.RequestSigner.sign; +import static info.frostfs.sdk.Helper.getSha256; +import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; +import static info.frostfs.sdk.tools.RequestConstructor.addObjectSessionToken; +import static info.frostfs.sdk.tools.RequestSigner.sign; import static java.util.Objects.nonNull; public class ObjectService extends ContextAccessor implements ObjectClient { @@ -90,7 +90,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { addMetaHeader(request); addObjectSessionToken( request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid), - frostFS.session.Types.ObjectSessionContext.Verb.GET, getContext().getKey() + frostfs.session.Types.ObjectSessionContext.Verb.GET, getContext().getKey() ); sign(request, getContext().getKey()); @@ -159,7 +159,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { addMetaHeader(request); addObjectSessionToken( request, sessionToken, grpcObject.getHeader().getContainerId(), grpcObject.getObjectId(), - frostFS.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() + frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() ); sign(request, getContext().getKey()); @@ -170,7 +170,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { return ObjectId.fromHash(grpcObject.getObjectId().getValue().toByteArray()); } - private frostFS.object.Types.Object getObject(Service.GetRequest request) { + private frostfs.object.Types.Object getObject(Service.GetRequest request) { var iterator = getObjectInit(request); var obj = iterator.readHeader(); var payload = new byte[Math.toIntExact(obj.getHeader().getPayloadLength())]; @@ -218,7 +218,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { addMetaHeader(initRequest); addObjectSessionToken( initRequest, sessionToken, hdr.getContainerId(), oid, - frostFS.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() + frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() ); sign(initRequest, getContext().getKey()); diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectTools.java similarity index 75% rename from client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ObjectTools.java index 412fa66..5eb0680 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectTools.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectTools.java @@ -1,21 +1,21 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; import com.google.protobuf.ByteString; -import frostFS.object.Types; -import info.FrostFS.sdk.dto.object.ObjectFrostFS; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.dto.object.ObjectId; -import info.FrostFS.sdk.jdo.ClientEnvironment; -import info.FrostFS.sdk.mappers.OwnerIdMapper; -import info.FrostFS.sdk.mappers.VersionMapper; -import info.FrostFS.sdk.mappers.object.ObjectHeaderMapper; -import info.FrostFS.sdk.mappers.object.ObjectIdMapper; -import info.FrostFS.sdk.services.ContextAccessor; -import info.FrostFS.sdk.services.ToolsClient; +import frostfs.object.Types; +import info.frostfs.sdk.dto.object.ObjectFrostFS; +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectId; +import info.frostfs.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.mappers.OwnerIdMapper; +import info.frostfs.sdk.mappers.VersionMapper; +import info.frostfs.sdk.mappers.object.ObjectHeaderMapper; +import info.frostfs.sdk.mappers.object.ObjectIdMapper; +import info.frostfs.sdk.services.ContextAccessor; +import info.frostfs.sdk.services.ToolsClient; import org.apache.commons.collections4.ListUtils; -import static info.FrostFS.sdk.Helper.getSha256; -import static info.FrostFS.sdk.tools.RequestSigner.signData; +import static info.frostfs.sdk.Helper.getSha256; +import static info.frostfs.sdk.tools.RequestSigner.signData; import static java.util.Objects.nonNull; public class ObjectTools extends ContextAccessor implements ToolsClient { @@ -23,9 +23,9 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { super(context); } - private static frostFS.refs.Types.Checksum sha256Checksum(byte[] data) { - return frostFS.refs.Types.Checksum.newBuilder() - .setType(frostFS.refs.Types.ChecksumType.SHA256) + private static frostfs.refs.Types.Checksum sha256Checksum(byte[] data) { + return frostfs.refs.Types.Checksum.newBuilder() + .setType(frostfs.refs.Types.ChecksumType.SHA256) .setSum(ByteString.copyFrom(getSha256(data))) .build(); } @@ -35,7 +35,7 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { var grpcHeader = createHeader(header, new byte[]{}); return ObjectIdMapper.toModel( - frostFS.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build() + frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build() ); } @@ -58,13 +58,13 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { if (nonNull(split.getParentHeader())) { var grpcParentHeader = createHeader(split.getParentHeader(), new byte[]{}); - var parent = frostFS.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcParentHeader)).build(); + var parent = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcParentHeader)).build(); splitGrpc .setParent(parent) .setParentHeader(grpcParentHeader) .setParentSignature( - frostFS.refs.Types.Signature.newBuilder() + frostfs.refs.Types.Signature.newBuilder() .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) .setSign(ByteString.copyFrom(signData(getContext().getKey(), parent.toByteArray()))) ); @@ -78,13 +78,13 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { } var grpcHeader = grpcHeaderBuilder.build(); - var objectId = frostFS.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build(); + var objectId = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build(); return Types.Object.newBuilder() .setHeader(grpcHeader) .setObjectId(objectId) .setPayload(ByteString.copyFrom(objectFrostFs.getPayload())) .setSignature( - frostFS.refs.Types.Signature.newBuilder() + frostfs.refs.Types.Signature.newBuilder() .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) .setSign(ByteString.copyFrom(signData(getContext().getKey(), objectId.toByteArray()))) ) diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectWriter.java similarity index 93% rename from client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ObjectWriter.java index 01ae85e..8642dc8 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/ObjectWriter.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectWriter.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; -import frostFS.object.ObjectServiceGrpc; -import frostFS.object.Service; +import frostfs.object.ObjectServiceGrpc; +import frostfs.object.Service; import io.grpc.stub.StreamObserver; import static java.util.Objects.isNull; diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java b/client/src/main/java/info/frostfs/sdk/services/impl/SearchReader.java similarity index 72% rename from client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java rename to client/src/main/java/info/frostfs/sdk/services/impl/SearchReader.java index 864d6e5..873d48b 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/SearchReader.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/SearchReader.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; -import frostFS.object.Service; -import info.FrostFS.sdk.tools.Verifier; +import frostfs.object.Service; +import info.frostfs.sdk.tools.Verifier; import java.util.Iterator; import java.util.List; @@ -13,7 +13,7 @@ public class SearchReader { this.call = call; } - public List read() { + public List read() { if (!call.hasNext()) { return null; } diff --git a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java b/client/src/main/java/info/frostfs/sdk/services/impl/SessionService.java similarity index 75% rename from client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/SessionService.java index 35e5967..d6bf950 100644 --- a/client/src/main/java/info/FrostFS/sdk/services/impl/SessionService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/SessionService.java @@ -1,17 +1,18 @@ -package info.FrostFS.sdk.services.impl; +package info.frostfs.sdk.services.impl; -import frostFS.session.Service; -import frostFS.session.SessionServiceGrpc; -import frostFS.session.Types; -import info.FrostFS.sdk.dto.SessionToken; -import info.FrostFS.sdk.jdo.ClientEnvironment; -import info.FrostFS.sdk.mappers.OwnerIdMapper; -import info.FrostFS.sdk.mappers.SessionMapper; -import info.FrostFS.sdk.services.ContextAccessor; -import info.FrostFS.sdk.services.SessionClient; +import frostfs.session.Service; +import frostfs.session.SessionServiceGrpc; +import frostfs.session.Types; +import info.frostfs.sdk.dto.SessionToken; +import info.frostfs.sdk.jdo.ClientEnvironment; +import info.frostfs.sdk.mappers.OwnerIdMapper; +import info.frostfs.sdk.mappers.SessionMapper; +import info.frostfs.sdk.services.ContextAccessor; +import info.frostfs.sdk.services.SessionClient; +import info.frostfs.sdk.tools.RequestConstructor; -import static info.FrostFS.sdk.tools.RequestConstructor.addMetaHeader; -import static info.FrostFS.sdk.tools.RequestSigner.sign; +import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; +import static info.frostfs.sdk.tools.RequestSigner.sign; public class SessionService extends ContextAccessor implements SessionClient { private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub; @@ -36,7 +37,7 @@ public class SessionService extends ContextAccessor implements SessionClient { .setExpiration(expiration).build() ); - addMetaHeader(request); + RequestConstructor.addMetaHeader(request); sign(request, getContext().getKey()); return createSession(request.build()); diff --git a/client/src/main/java/info/FrostFS/sdk/tools/GrpcClient.java b/client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java similarity index 96% rename from client/src/main/java/info/FrostFS/sdk/tools/GrpcClient.java rename to client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java index 61cfee2..729d3e5 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/GrpcClient.java +++ b/client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.frostfs.sdk.tools; import io.grpc.Channel; import io.grpc.ChannelCredentials; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java b/client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java similarity index 94% rename from client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java rename to client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java index 4e11b06..00f87c4 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/MessageHelper.java +++ b/client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.tools; +package info.frostfs.sdk.tools; import com.google.protobuf.Message; import com.google.protobuf.MessageOrBuilder; diff --git a/client/src/main/java/info/FrostFS/sdk/tools/RequestConstructor.java b/client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java similarity index 74% rename from client/src/main/java/info/FrostFS/sdk/tools/RequestConstructor.java rename to client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java index 3d8d02a..9660de5 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/RequestConstructor.java +++ b/client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java @@ -1,15 +1,15 @@ -package info.FrostFS.sdk.tools; +package info.frostfs.sdk.tools; import com.google.protobuf.Message; -import frostFS.session.Types; -import info.FrostFS.sdk.dto.MetaHeader; -import info.FrostFS.sdk.jdo.ECDsa; -import info.FrostFS.sdk.mappers.MetaHeaderMapper; +import frostfs.session.Types; +import info.frostfs.sdk.dto.MetaHeader; +import info.frostfs.sdk.jdo.ECDsa; +import info.frostfs.sdk.mappers.MetaHeaderMapper; -import static info.FrostFS.sdk.constants.FieldConst.META_HEADER_FIELD_NAME; -import static info.FrostFS.sdk.tools.MessageHelper.getField; -import static info.FrostFS.sdk.tools.MessageHelper.setField; -import static info.FrostFS.sdk.tools.RequestSigner.signMessagePart; +import static info.frostfs.sdk.constants.FieldConst.META_HEADER_FIELD_NAME; +import static info.frostfs.sdk.tools.MessageHelper.getField; +import static info.frostfs.sdk.tools.MessageHelper.setField; +import static info.frostfs.sdk.tools.RequestSigner.signMessagePart; import static java.util.Objects.isNull; public class RequestConstructor { @@ -27,8 +27,8 @@ public class RequestConstructor { public static void addObjectSessionToken(Message.Builder request, Types.SessionToken sessionToken, - frostFS.refs.Types.ContainerID cid, - frostFS.refs.Types.ObjectID oid, + frostfs.refs.Types.ContainerID cid, + frostfs.refs.Types.ObjectID oid, Types.ObjectSessionContext.Verb verb, ECDsa key) { var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME); diff --git a/client/src/main/java/info/FrostFS/sdk/tools/RequestSigner.java b/client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java similarity index 72% rename from client/src/main/java/info/FrostFS/sdk/tools/RequestSigner.java rename to client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java index daca2cc..315af58 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/RequestSigner.java +++ b/client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java @@ -1,9 +1,10 @@ -package info.FrostFS.sdk.tools; +package info.frostfs.sdk.tools; import com.google.protobuf.ByteString; import com.google.protobuf.Message; -import frostFS.session.Types; -import info.FrostFS.sdk.jdo.ECDsa; +import frostfs.session.Types; +import info.frostfs.sdk.jdo.ECDsa; +import info.frostfs.sdk.constants.CryptoConst; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -15,10 +16,7 @@ import org.bouncycastle.crypto.signers.HMacDSAKCalculator; import java.math.BigInteger; import java.security.Signature; -import static info.FrostFS.sdk.constants.CryptoConst.SIGNATURE_ALGORITHM; -import static info.FrostFS.sdk.constants.FieldConst.*; -import static info.FrostFS.sdk.tools.MessageHelper.getField; -import static info.FrostFS.sdk.tools.MessageHelper.setField; +import static info.frostfs.sdk.constants.FieldConst.*; import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.asUnsignedByteArray; @@ -30,7 +28,7 @@ public class RequestSigner { var hash = new byte[65]; hash[0] = 0x04; try { - Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); + Signature signature = Signature.getInstance(CryptoConst.SIGNATURE_ALGORITHM); signature.initSign(key.getPrivateKey()); signature.update(DigestUtils.sha512(data)); byte[] sig = signature.sign(); @@ -67,33 +65,33 @@ public class RequestSigner { return signature; } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, Message message) { - return frostFS.refs.Types.SignatureRFC6979.newBuilder() + public static frostfs.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, Message message) { + return frostfs.refs.Types.SignatureRFC6979.newBuilder() .setKey(ByteString.copyFrom(key.getPublicKeyByte())) .setSign(ByteString.copyFrom(signRFC6979(key, message.toByteArray()))) .build(); } - public static frostFS.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, ByteString data) { - return frostFS.refs.Types.SignatureRFC6979.newBuilder() + public static frostfs.refs.Types.SignatureRFC6979 signRFC6979(ECDsa key, ByteString data) { + return frostfs.refs.Types.SignatureRFC6979.newBuilder() .setKey(ByteString.copyFrom(key.getPublicKeyByte())) .setSign(ByteString.copyFrom(signRFC6979(key, data.toByteArray()))) .build(); } - public static frostFS.refs.Types.Signature signMessagePart(ECDsa key, Message data) { + public static frostfs.refs.Types.Signature signMessagePart(ECDsa key, Message data) { var data2Sign = data.getSerializedSize() == 0 ? new byte[]{} : data.toByteArray(); - return frostFS.refs.Types.Signature.newBuilder() + return frostfs.refs.Types.Signature.newBuilder() .setKey(ByteString.copyFrom(key.getPublicKeyByte())) .setSign(ByteString.copyFrom(signData(key, data2Sign))) .build(); } public static void sign(Message.Builder request, ECDsa key) { - var meta = getField(request, META_HEADER_FIELD_NAME); - var body = getField(request, BODY_FIELD_NAME); - var verify = getField(request, VERIFY_HEADER_FIELD_NAME); - var verifyOrigin = getField(verify, ORIGIN_FIELD_NAME); + var meta = MessageHelper.getField(request, META_HEADER_FIELD_NAME); + var body = MessageHelper.getField(request, BODY_FIELD_NAME); + var verify = MessageHelper.getField(request, VERIFY_HEADER_FIELD_NAME); + var verifyOrigin = MessageHelper.getField(verify, ORIGIN_FIELD_NAME); Message.Builder verifyBuilder; if (verify instanceof Types.RequestVerificationHeader) { @@ -107,14 +105,14 @@ public class RequestSigner { } if (verifyOrigin.getSerializedSize() == 0) { - setField(verifyBuilder, BODY_SIGNATURE_FIELD_NAME, signMessagePart(key, body)); + MessageHelper.setField(verifyBuilder, BODY_SIGNATURE_FIELD_NAME, signMessagePart(key, body)); } else { - setField(verifyBuilder, ORIGIN_FIELD_NAME, verifyOrigin); + MessageHelper.setField(verifyBuilder, ORIGIN_FIELD_NAME, verifyOrigin); } - setField(verifyBuilder, META_SIGNATURE_FIELD_NAME, signMessagePart(key, meta)); - setField(verifyBuilder, ORIGIN_SIGNATURE_FIELD_NAME, signMessagePart(key, verifyOrigin)); - setField(request, VERIFY_HEADER_FIELD_NAME, verifyBuilder.build()); + MessageHelper.setField(verifyBuilder, META_SIGNATURE_FIELD_NAME, signMessagePart(key, meta)); + MessageHelper.setField(verifyBuilder, ORIGIN_SIGNATURE_FIELD_NAME, signMessagePart(key, verifyOrigin)); + MessageHelper.setField(request, VERIFY_HEADER_FIELD_NAME, verifyBuilder.build()); } } diff --git a/client/src/main/java/info/FrostFS/sdk/tools/Verifier.java b/client/src/main/java/info/frostfs/sdk/tools/Verifier.java similarity index 80% rename from client/src/main/java/info/FrostFS/sdk/tools/Verifier.java rename to client/src/main/java/info/frostfs/sdk/tools/Verifier.java index 14e7327..8fed127 100644 --- a/client/src/main/java/info/FrostFS/sdk/tools/Verifier.java +++ b/client/src/main/java/info/frostfs/sdk/tools/Verifier.java @@ -1,8 +1,9 @@ -package info.FrostFS.sdk.tools; +package info.frostfs.sdk.tools; import com.google.protobuf.Message; -import frostFS.session.Types; -import info.FrostFS.sdk.mappers.StatusMapper; +import frostfs.session.Types; +import info.frostfs.sdk.mappers.StatusMapper; +import info.frostfs.sdk.constants.CryptoConst; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -16,10 +17,8 @@ import java.security.PublicKey; import java.security.Signature; import java.util.Arrays; -import static info.FrostFS.sdk.KeyExtension.getPublicKeyFromBytes; -import static info.FrostFS.sdk.constants.CryptoConst.SIGNATURE_ALGORITHM; -import static info.FrostFS.sdk.constants.FieldConst.*; -import static info.FrostFS.sdk.tools.MessageHelper.getField; +import static info.frostfs.sdk.KeyExtension.getPublicKeyFromBytes; +import static info.frostfs.sdk.constants.FieldConst.*; import static java.util.Objects.isNull; import static org.bouncycastle.crypto.util.DigestFactory.createSHA256; import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; @@ -29,7 +28,7 @@ public class Verifier { public static final String ERROR_INVALID_RESPONSE = "Invalid response"; public static final int RFC6979_SIG_SIZE = 64; - public static boolean verifyRFC6979(frostFS.refs.Types.SignatureRFC6979 signature, Message data) { + public static boolean verifyRFC6979(frostfs.refs.Types.SignatureRFC6979 signature, Message data) { return verifyRFC6979(signature.getKey().toByteArray(), data.toByteArray(), signature.getSign().toByteArray()); } @@ -68,7 +67,7 @@ public class Verifier { throw new IllegalArgumentException(ERROR_INVALID_RESPONSE); } - var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME); + var metaHeader = (Types.ResponseMetaHeader) MessageHelper.getField(response, META_HEADER_FIELD_NAME); var status = StatusMapper.toModel(metaHeader.getStatus()); if (!status.isSuccess()) { throw new IllegalArgumentException(status.toString()); @@ -76,16 +75,16 @@ public class Verifier { } public static boolean verify(Message response) { - var body = getField(response, BODY_FIELD_NAME); - var metaHeader = (Types.ResponseMetaHeader) getField(response, META_HEADER_FIELD_NAME); - var verifyHeader = (Types.ResponseVerificationHeader) getField(response, VERIFY_HEADER_FIELD_NAME); + var body = MessageHelper.getField(response, BODY_FIELD_NAME); + var metaHeader = (Types.ResponseMetaHeader) MessageHelper.getField(response, META_HEADER_FIELD_NAME); + var verifyHeader = (Types.ResponseVerificationHeader) MessageHelper.getField(response, VERIFY_HEADER_FIELD_NAME); return verifyMatryoshkaLevel(body, metaHeader, verifyHeader); } public static boolean verifyMatryoshkaLevel(Message data, - frostFS.session.Types.ResponseMetaHeader meta, - frostFS.session.Types.ResponseVerificationHeader verification) { + frostfs.session.Types.ResponseMetaHeader meta, + frostfs.session.Types.ResponseVerificationHeader verification) { if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false; var origin = verification.getOrigin(); if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false; @@ -96,7 +95,7 @@ public class Verifier { && verifyMatryoshkaLevel(data, meta.getOrigin(), origin); } - public static boolean verifyMessagePart(frostFS.refs.Types.Signature sig, Message data) { + public static boolean verifyMessagePart(frostfs.refs.Types.Signature sig, Message data) { if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false; var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray()); @@ -107,7 +106,7 @@ public class Verifier { public static boolean verifyData(PublicKey publicKey, byte[] data, byte[] sig) { try { - Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); + Signature signature = Signature.getInstance(CryptoConst.SIGNATURE_ALGORITHM); signature.initVerify(publicKey); signature.update(DigestUtils.sha512(data)); return signature.verify(Arrays.copyOfRange(sig, 1, sig.length)); diff --git a/cryptography/pom.xml b/cryptography/pom.xml index f92accd..156b0bd 100644 --- a/cryptography/pom.xml +++ b/cryptography/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - info.FrostFS.sdk - FrostFS-sdk-java + info.frostfs.sdk + frostfs-sdk-java 0.1.0 diff --git a/cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java b/cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java similarity index 93% rename from cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java rename to cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java index 5274f60..ae43afd 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/ArrayHelper.java +++ b/cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk; +package info.frostfs.sdk; public class ArrayHelper { diff --git a/cryptography/src/main/java/info/FrostFS/sdk/Base58.java b/cryptography/src/main/java/info/frostfs/sdk/Base58.java similarity index 97% rename from cryptography/src/main/java/info/FrostFS/sdk/Base58.java rename to cryptography/src/main/java/info/frostfs/sdk/Base58.java index 9fe27af..f75d705 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/Base58.java +++ b/cryptography/src/main/java/info/frostfs/sdk/Base58.java @@ -1,9 +1,9 @@ -package info.FrostFS.sdk; +package info.frostfs.sdk; import java.util.Arrays; -import static info.FrostFS.sdk.ArrayHelper.concat; -import static info.FrostFS.sdk.Helper.getSha256; +import static info.frostfs.sdk.ArrayHelper.concat; +import static info.frostfs.sdk.Helper.getSha256; import static java.util.Objects.isNull; public class Base58 { diff --git a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java b/cryptography/src/main/java/info/frostfs/sdk/Helper.java similarity index 97% rename from cryptography/src/main/java/info/FrostFS/sdk/Helper.java rename to cryptography/src/main/java/info/frostfs/sdk/Helper.java index 083121b..a6068e2 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/Helper.java +++ b/cryptography/src/main/java/info/frostfs/sdk/Helper.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk; +package info.frostfs.sdk; import com.google.protobuf.ByteString; import com.google.protobuf.Message; diff --git a/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java b/cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java similarity index 98% rename from cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java rename to cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java index d057a04..4ef8ffe 100644 --- a/cryptography/src/main/java/info/FrostFS/sdk/KeyExtension.java +++ b/cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk; +package info.frostfs.sdk; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -23,8 +23,8 @@ import java.security.spec.ECPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.util.Arrays; -import static info.FrostFS.sdk.Helper.getRIPEMD160; -import static info.FrostFS.sdk.Helper.getSha256; +import static info.frostfs.sdk.Helper.getRIPEMD160; +import static info.frostfs.sdk.Helper.getSha256; import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; public class KeyExtension { diff --git a/models/pom.xml b/models/pom.xml index 1f04f5e..e9dd655 100644 --- a/models/pom.xml +++ b/models/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - info.FrostFS.sdk - FrostFS-sdk-java + info.frostfs.sdk + frostfs-sdk-java 0.1.0 @@ -24,12 +24,12 @@ 3.14.0 - info.FrostFS.sdk + info.frostfs.sdk cryptography 0.1.0 - info.FrostFS.sdk + info.frostfs.sdk protos 0.1.0 diff --git a/models/src/main/java/info/FrostFS/sdk/UUIDExtension.java b/models/src/main/java/info/frostfs/sdk/UUIDExtension.java similarity index 95% rename from models/src/main/java/info/FrostFS/sdk/UUIDExtension.java rename to models/src/main/java/info/frostfs/sdk/UUIDExtension.java index df146ec..7edc01c 100644 --- a/models/src/main/java/info/FrostFS/sdk/UUIDExtension.java +++ b/models/src/main/java/info/frostfs/sdk/UUIDExtension.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk; +package info.frostfs.sdk; import java.nio.ByteBuffer; import java.util.UUID; diff --git a/models/src/main/java/info/FrostFS/sdk/constants/AppConst.java b/models/src/main/java/info/frostfs/sdk/constants/AppConst.java similarity index 79% rename from models/src/main/java/info/FrostFS/sdk/constants/AppConst.java rename to models/src/main/java/info/frostfs/sdk/constants/AppConst.java index 8880eb0..ea60f0e 100644 --- a/models/src/main/java/info/FrostFS/sdk/constants/AppConst.java +++ b/models/src/main/java/info/frostfs/sdk/constants/AppConst.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.constants; +package info.frostfs.sdk.constants; public class AppConst { public static final int OBJECT_CHUNK_SIZE = 3 * (1 << 20); diff --git a/models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java b/models/src/main/java/info/frostfs/sdk/constants/FieldConst.java similarity index 93% rename from models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java rename to models/src/main/java/info/frostfs/sdk/constants/FieldConst.java index 761258a..fe85aad 100644 --- a/models/src/main/java/info/FrostFS/sdk/constants/FieldConst.java +++ b/models/src/main/java/info/frostfs/sdk/constants/FieldConst.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.constants; +package info.frostfs.sdk.constants; public class FieldConst { public static final String META_HEADER_FIELD_NAME = "meta_header"; diff --git a/models/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java b/models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java similarity index 89% rename from models/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java rename to models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java index 8c435e7..c1cc83c 100644 --- a/models/src/main/java/info/FrostFS/sdk/constants/XHeaderConst.java +++ b/models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.constants; +package info.frostfs.sdk.constants; public class XHeaderConst { public static final String RESERVED_XHEADER_PREFIX = "__SYSTEM__"; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/MetaHeader.java b/models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java similarity index 96% rename from models/src/main/java/info/FrostFS/sdk/dto/MetaHeader.java rename to models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java index b0eead0..4e22f46 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/MetaHeader.java +++ b/models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; public class MetaHeader { private Version version; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/OwnerId.java b/models/src/main/java/info/frostfs/sdk/dto/OwnerId.java similarity index 75% rename from models/src/main/java/info/FrostFS/sdk/dto/OwnerId.java rename to models/src/main/java/info/frostfs/sdk/dto/OwnerId.java index 40b4f04..d4a173b 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/OwnerId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/OwnerId.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; -import info.FrostFS.sdk.Base58; +import info.frostfs.sdk.Base58; -import static info.FrostFS.sdk.KeyExtension.publicKeyToAddress; +import static info.frostfs.sdk.KeyExtension.publicKeyToAddress; public class OwnerId { private final String value; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/SessionToken.java b/models/src/main/java/info/frostfs/sdk/dto/SessionToken.java similarity index 91% rename from models/src/main/java/info/FrostFS/sdk/dto/SessionToken.java rename to models/src/main/java/info/frostfs/sdk/dto/SessionToken.java index 5980875..2f4055b 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/SessionToken.java +++ b/models/src/main/java/info/frostfs/sdk/dto/SessionToken.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; public class SessionToken { private final byte[] id; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/Signature.java b/models/src/main/java/info/frostfs/sdk/dto/Signature.java similarity index 87% rename from models/src/main/java/info/FrostFS/sdk/dto/Signature.java rename to models/src/main/java/info/frostfs/sdk/dto/Signature.java index 0ab5b3e..5b2b85d 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/Signature.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Signature.java @@ -1,6 +1,6 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; -import info.FrostFS.sdk.enums.SignatureScheme; +import info.frostfs.sdk.enums.SignatureScheme; public class Signature { private byte[] key; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/Split.java b/models/src/main/java/info/frostfs/sdk/dto/Split.java similarity index 91% rename from models/src/main/java/info/FrostFS/sdk/dto/Split.java rename to models/src/main/java/info/frostfs/sdk/dto/Split.java index be51331..2b5726a 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/Split.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Split.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.dto.object.ObjectId; +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectId; import java.util.ArrayList; import java.util.List; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/SplitId.java b/models/src/main/java/info/frostfs/sdk/dto/SplitId.java similarity index 85% rename from models/src/main/java/info/FrostFS/sdk/dto/SplitId.java rename to models/src/main/java/info/frostfs/sdk/dto/SplitId.java index b01b8d0..6ecc031 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/SplitId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/SplitId.java @@ -1,9 +1,9 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; import java.util.UUID; -import static info.FrostFS.sdk.UUIDExtension.asBytes; -import static info.FrostFS.sdk.UUIDExtension.asUuid; +import static info.frostfs.sdk.UUIDExtension.asBytes; +import static info.frostfs.sdk.UUIDExtension.asUuid; import static java.util.Objects.isNull; public class SplitId { diff --git a/models/src/main/java/info/FrostFS/sdk/dto/Status.java b/models/src/main/java/info/frostfs/sdk/dto/Status.java similarity index 92% rename from models/src/main/java/info/FrostFS/sdk/dto/Status.java rename to models/src/main/java/info/frostfs/sdk/dto/Status.java index d766546..dd242a3 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/Status.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Status.java @@ -1,6 +1,6 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; -import info.FrostFS.sdk.enums.StatusCode; +import info.frostfs.sdk.enums.StatusCode; import static java.util.Objects.isNull; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/Version.java b/models/src/main/java/info/frostfs/sdk/dto/Version.java similarity index 95% rename from models/src/main/java/info/FrostFS/sdk/dto/Version.java rename to models/src/main/java/info/frostfs/sdk/dto/Version.java index c498b49..563d8b6 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/Version.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Version.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto; +package info.frostfs.sdk.dto; public class Version { private int major; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/container/Container.java b/models/src/main/java/info/frostfs/sdk/dto/container/Container.java similarity index 86% rename from models/src/main/java/info/FrostFS/sdk/dto/container/Container.java rename to models/src/main/java/info/frostfs/sdk/dto/container/Container.java index b952fcf..e07c28a 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/container/Container.java +++ b/models/src/main/java/info/frostfs/sdk/dto/container/Container.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.dto.container; +package info.frostfs.sdk.dto.container; -import info.FrostFS.sdk.dto.Version; -import info.FrostFS.sdk.dto.netmap.PlacementPolicy; -import info.FrostFS.sdk.enums.BasicAcl; +import info.frostfs.sdk.dto.Version; +import info.frostfs.sdk.dto.netmap.PlacementPolicy; +import info.frostfs.sdk.enums.BasicAcl; import java.util.UUID; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/container/ContainerId.java b/models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java similarity index 85% rename from models/src/main/java/info/FrostFS/sdk/dto/container/ContainerId.java rename to models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java index fd8d529..b24a069 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/container/ContainerId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.dto.container; +package info.frostfs.sdk.dto.container; -import info.FrostFS.sdk.Base58; -import info.FrostFS.sdk.constants.AppConst; +import info.frostfs.sdk.Base58; +import info.frostfs.sdk.constants.AppConst; public class ContainerId { private String value; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/netmap/NetmapSnapshot.java b/models/src/main/java/info/frostfs/sdk/dto/netmap/NetmapSnapshot.java similarity index 92% rename from models/src/main/java/info/FrostFS/sdk/dto/netmap/NetmapSnapshot.java rename to models/src/main/java/info/frostfs/sdk/dto/netmap/NetmapSnapshot.java index 8619f00..9c2ef2c 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/netmap/NetmapSnapshot.java +++ b/models/src/main/java/info/frostfs/sdk/dto/netmap/NetmapSnapshot.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto.netmap; +package info.frostfs.sdk.dto.netmap; import java.util.List; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/netmap/NodeInfo.java b/models/src/main/java/info/frostfs/sdk/dto/netmap/NodeInfo.java similarity index 89% rename from models/src/main/java/info/FrostFS/sdk/dto/netmap/NodeInfo.java rename to models/src/main/java/info/frostfs/sdk/dto/netmap/NodeInfo.java index bd78146..2be1b1b 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/netmap/NodeInfo.java +++ b/models/src/main/java/info/frostfs/sdk/dto/netmap/NodeInfo.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.dto.netmap; +package info.frostfs.sdk.dto.netmap; -import info.FrostFS.sdk.dto.Version; -import info.FrostFS.sdk.enums.NodeState; +import info.frostfs.sdk.dto.Version; +import info.frostfs.sdk.enums.NodeState; import java.util.List; import java.util.Map; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/netmap/PlacementPolicy.java b/models/src/main/java/info/frostfs/sdk/dto/netmap/PlacementPolicy.java similarity index 90% rename from models/src/main/java/info/FrostFS/sdk/dto/netmap/PlacementPolicy.java rename to models/src/main/java/info/frostfs/sdk/dto/netmap/PlacementPolicy.java index 9e92a63..74a1c72 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/netmap/PlacementPolicy.java +++ b/models/src/main/java/info/frostfs/sdk/dto/netmap/PlacementPolicy.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto.netmap; +package info.frostfs.sdk.dto.netmap; public class PlacementPolicy { private final Replica[] replicas; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/netmap/Replica.java b/models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java similarity index 94% rename from models/src/main/java/info/FrostFS/sdk/dto/netmap/Replica.java rename to models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java index 5189df7..235d288 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/netmap/Replica.java +++ b/models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto.netmap; +package info.frostfs.sdk.dto.netmap; import static java.util.Objects.isNull; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java b/models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java similarity index 81% rename from models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java rename to models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java index 66d9ad0..4cab2ed 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/LargeObject.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java @@ -1,10 +1,10 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; -import info.FrostFS.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.container.ContainerId; import java.security.MessageDigest; -import static info.FrostFS.sdk.Helper.getSha256Instance; +import static info.frostfs.sdk.Helper.getSha256Instance; public class LargeObject extends ObjectFrostFS { private final MessageDigest payloadHash; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java b/models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java similarity index 74% rename from models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java rename to models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java index e7b8ea4..b641888 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/LinkObject.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; -import info.FrostFS.sdk.dto.Split; -import info.FrostFS.sdk.dto.SplitId; -import info.FrostFS.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.Split; +import info.frostfs.sdk.dto.SplitId; +import info.frostfs.sdk.dto.container.ContainerId; import java.util.List; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectAttribute.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java similarity index 92% rename from models/src/main/java/info/FrostFS/sdk/dto/object/ObjectAttribute.java rename to models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java index 9729f01..0c2554b 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectAttribute.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; public class ObjectAttribute { private String key; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFilter.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFilter.java similarity index 90% rename from models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFilter.java rename to models/src/main/java/info/frostfs/sdk/dto/object/ObjectFilter.java index 0dae796..1443ee2 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFilter.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFilter.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; -import info.FrostFS.sdk.dto.OwnerId; -import info.FrostFS.sdk.dto.Version; -import info.FrostFS.sdk.enums.ObjectMatchType; +import info.frostfs.sdk.dto.OwnerId; +import info.frostfs.sdk.dto.Version; +import info.frostfs.sdk.enums.ObjectMatchType; public class ObjectFilter { private static final String HEADER_PREFIX = "$Object:"; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java similarity index 92% rename from models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java rename to models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java index 3b9d3c9..5001161 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectFrostFS.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; -import info.FrostFS.sdk.dto.Split; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.enums.ObjectType; +import info.frostfs.sdk.dto.Split; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.enums.ObjectType; import java.util.ArrayList; import java.util.List; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java similarity index 91% rename from models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java rename to models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java index 401ed41..147ec4e 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectHeader.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java @@ -1,10 +1,10 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; -import info.FrostFS.sdk.dto.OwnerId; -import info.FrostFS.sdk.dto.Split; -import info.FrostFS.sdk.dto.Version; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.enums.ObjectType; +import info.frostfs.sdk.dto.OwnerId; +import info.frostfs.sdk.dto.Split; +import info.frostfs.sdk.dto.Version; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.enums.ObjectType; import java.util.List; diff --git a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectId.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java similarity index 83% rename from models/src/main/java/info/FrostFS/sdk/dto/object/ObjectId.java rename to models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java index 4b36d80..3c9965a 100644 --- a/models/src/main/java/info/FrostFS/sdk/dto/object/ObjectId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.dto.object; +package info.frostfs.sdk.dto.object; -import info.FrostFS.sdk.Base58; -import info.FrostFS.sdk.constants.AppConst; +import info.frostfs.sdk.Base58; +import info.frostfs.sdk.constants.AppConst; public class ObjectId { private final String value; diff --git a/models/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java b/models/src/main/java/info/frostfs/sdk/enums/BasicAcl.java similarity index 95% rename from models/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java rename to models/src/main/java/info/frostfs/sdk/enums/BasicAcl.java index 7ebf7f7..52bab99 100644 --- a/models/src/main/java/info/FrostFS/sdk/enums/BasicAcl.java +++ b/models/src/main/java/info/frostfs/sdk/enums/BasicAcl.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.enums; +package info.frostfs.sdk.enums; import java.util.Collections; import java.util.HashMap; diff --git a/models/src/main/java/info/FrostFS/sdk/enums/NodeState.java b/models/src/main/java/info/frostfs/sdk/enums/NodeState.java similarity index 95% rename from models/src/main/java/info/FrostFS/sdk/enums/NodeState.java rename to models/src/main/java/info/frostfs/sdk/enums/NodeState.java index e6f1464..3f833e3 100644 --- a/models/src/main/java/info/FrostFS/sdk/enums/NodeState.java +++ b/models/src/main/java/info/frostfs/sdk/enums/NodeState.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.enums; +package info.frostfs.sdk.enums; import java.util.Collections; import java.util.HashMap; diff --git a/models/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java b/models/src/main/java/info/frostfs/sdk/enums/ObjectMatchType.java similarity index 87% rename from models/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java rename to models/src/main/java/info/frostfs/sdk/enums/ObjectMatchType.java index 385756f..2122ad6 100644 --- a/models/src/main/java/info/FrostFS/sdk/enums/ObjectMatchType.java +++ b/models/src/main/java/info/frostfs/sdk/enums/ObjectMatchType.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.enums; +package info.frostfs.sdk.enums; public enum ObjectMatchType { UNSPECIFIED(0), diff --git a/models/src/main/java/info/FrostFS/sdk/enums/ObjectType.java b/models/src/main/java/info/frostfs/sdk/enums/ObjectType.java similarity index 95% rename from models/src/main/java/info/FrostFS/sdk/enums/ObjectType.java rename to models/src/main/java/info/frostfs/sdk/enums/ObjectType.java index feb545f..d252a7a 100644 --- a/models/src/main/java/info/FrostFS/sdk/enums/ObjectType.java +++ b/models/src/main/java/info/frostfs/sdk/enums/ObjectType.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.enums; +package info.frostfs.sdk.enums; import java.util.Collections; import java.util.HashMap; diff --git a/models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java b/models/src/main/java/info/frostfs/sdk/enums/SignatureScheme.java similarity index 87% rename from models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java rename to models/src/main/java/info/frostfs/sdk/enums/SignatureScheme.java index 362c75a..7bb7511 100644 --- a/models/src/main/java/info/FrostFS/sdk/enums/SignatureScheme.java +++ b/models/src/main/java/info/frostfs/sdk/enums/SignatureScheme.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.enums; +package info.frostfs.sdk.enums; public enum SignatureScheme { ECDSA_SHA512(0), diff --git a/models/src/main/java/info/FrostFS/sdk/enums/StatusCode.java b/models/src/main/java/info/frostfs/sdk/enums/StatusCode.java similarity index 97% rename from models/src/main/java/info/FrostFS/sdk/enums/StatusCode.java rename to models/src/main/java/info/frostfs/sdk/enums/StatusCode.java index 4e44421..b67e766 100644 --- a/models/src/main/java/info/FrostFS/sdk/enums/StatusCode.java +++ b/models/src/main/java/info/frostfs/sdk/enums/StatusCode.java @@ -1,4 +1,4 @@ -package info.FrostFS.sdk.enums; +package info.frostfs.sdk.enums; import java.util.Collections; import java.util.HashMap; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java similarity index 78% rename from models/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java index 96371d7..736871c 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/MetaHeaderMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.mappers; +package info.frostfs.sdk.mappers; -import frostFS.session.Types; -import info.FrostFS.sdk.dto.MetaHeader; +import frostfs.session.Types; +import info.frostfs.sdk.dto.MetaHeader; public class MetaHeaderMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java similarity index 73% rename from models/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java index edf9f1c..69cb6e8 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/OwnerIdMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers; +package info.frostfs.sdk.mappers; import com.google.protobuf.ByteString; -import frostFS.refs.Types; -import info.FrostFS.sdk.dto.OwnerId; +import frostfs.refs.Types; +import info.frostfs.sdk.dto.OwnerId; public class OwnerIdMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java similarity index 93% rename from models/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java index a8d329d..c13a61e 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/SessionMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers; +package info.frostfs.sdk.mappers; import com.google.protobuf.CodedOutputStream; import com.google.protobuf.InvalidProtocolBufferException; -import frostFS.session.Types; +import frostfs.session.Types; import java.io.IOException; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java similarity index 87% rename from models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java index 3a388d0..1a62bfd 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/SignatureMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers; +package info.frostfs.sdk.mappers; import com.google.protobuf.ByteString; -import frostFS.refs.Types; -import info.FrostFS.sdk.dto.Signature; +import frostfs.refs.Types; +import info.frostfs.sdk.dto.Signature; import static java.util.Objects.isNull; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java similarity index 78% rename from models/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java index 3817f7d..7c6f3b1 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/StatusMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers; +package info.frostfs.sdk.mappers; -import frostFS.status.Types; -import info.FrostFS.sdk.dto.Status; -import info.FrostFS.sdk.enums.StatusCode; +import frostfs.status.Types; +import info.frostfs.sdk.dto.Status; +import info.frostfs.sdk.enums.StatusCode; import static java.util.Objects.isNull; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java similarity index 80% rename from models/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java index fefb7ba..7888a67 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/VersionMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.mappers; +package info.frostfs.sdk.mappers; -import frostFS.refs.Types; -import info.FrostFS.sdk.dto.Version; +import frostfs.refs.Types; +import info.frostfs.sdk.dto.Version; public class VersionMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerIdMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java similarity index 71% rename from models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerIdMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java index b661e71..cbe7237 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerIdMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers.container; +package info.frostfs.sdk.mappers.container; import com.google.protobuf.ByteString; -import frostFS.refs.Types; -import info.FrostFS.sdk.dto.container.ContainerId; +import frostfs.refs.Types; +import info.frostfs.sdk.dto.container.ContainerId; public class ContainerIdMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java similarity index 75% rename from models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java index 9895eee..ff36486 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/container/ContainerMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java @@ -1,14 +1,14 @@ -package info.FrostFS.sdk.mappers.container; +package info.frostfs.sdk.mappers.container; import com.google.protobuf.ByteString; -import frostFS.container.Types; -import info.FrostFS.sdk.dto.container.Container; -import info.FrostFS.sdk.enums.BasicAcl; -import info.FrostFS.sdk.mappers.VersionMapper; -import info.FrostFS.sdk.mappers.netmap.PlacementPolicyMapper; +import frostfs.container.Types; +import info.frostfs.sdk.dto.container.Container; +import info.frostfs.sdk.enums.BasicAcl; +import info.frostfs.sdk.mappers.VersionMapper; +import info.frostfs.sdk.mappers.netmap.PlacementPolicyMapper; -import static info.FrostFS.sdk.UUIDExtension.asBytes; -import static info.FrostFS.sdk.UUIDExtension.asUuid; +import static info.frostfs.sdk.UUIDExtension.asBytes; +import static info.frostfs.sdk.UUIDExtension.asUuid; import static java.util.Objects.isNull; public class ContainerMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java similarity index 80% rename from models/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java index d18fc32..a396f58 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NetmapSnapshotMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.mappers.netmap; +package info.frostfs.sdk.mappers.netmap; -import frostFS.netmap.Service; -import info.FrostFS.sdk.dto.netmap.NetmapSnapshot; +import frostfs.netmap.Service; +import info.frostfs.sdk.dto.netmap.NetmapSnapshot; import java.util.stream.Collectors; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java similarity index 72% rename from models/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java index 53eca35..c2bd9b7 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/NodeInfoMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java @@ -1,11 +1,11 @@ -package info.FrostFS.sdk.mappers.netmap; +package info.frostfs.sdk.mappers.netmap; -import frostFS.netmap.Service; -import frostFS.netmap.Types.NodeInfo.Attribute; -import frostFS.refs.Types; -import info.FrostFS.sdk.dto.netmap.NodeInfo; -import info.FrostFS.sdk.enums.NodeState; -import info.FrostFS.sdk.mappers.VersionMapper; +import frostfs.netmap.Service; +import frostfs.netmap.Types.NodeInfo.Attribute; +import frostfs.refs.Types; +import info.frostfs.sdk.dto.netmap.NodeInfo; +import info.frostfs.sdk.enums.NodeState; +import info.frostfs.sdk.mappers.VersionMapper; import java.util.stream.Collectors; @@ -17,7 +17,7 @@ public class NodeInfoMapper { return toModel(nodeInfo.getNodeInfo(), nodeInfo.getVersion()); } - public static NodeInfo toModel(frostFS.netmap.Types.NodeInfo nodeInfo, Types.Version version) { + public static NodeInfo toModel(frostfs.netmap.Types.NodeInfo nodeInfo, Types.Version version) { NodeState nodeState = NodeState.get(nodeInfo.getState().getNumber()); if (isNull(nodeState)) { throw new IllegalArgumentException( diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java similarity index 80% rename from models/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java index e2803d6..4a6675c 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/PlacementPolicyMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers.netmap; +package info.frostfs.sdk.mappers.netmap; -import frostFS.netmap.Types; -import info.FrostFS.sdk.dto.netmap.PlacementPolicy; -import info.FrostFS.sdk.dto.netmap.Replica; +import frostfs.netmap.Types; +import info.frostfs.sdk.dto.netmap.PlacementPolicy; +import info.frostfs.sdk.dto.netmap.Replica; public class PlacementPolicyMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java similarity index 78% rename from models/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java index b2929ba..eef3e70 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/netmap/ReplicaMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.mappers.netmap; +package info.frostfs.sdk.mappers.netmap; -import frostFS.netmap.Types; -import info.FrostFS.sdk.dto.netmap.Replica; +import frostfs.netmap.Types; +import info.frostfs.sdk.dto.netmap.Replica; public class ReplicaMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectAttributeMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java similarity index 79% rename from models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectAttributeMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java index 7604e0f..62c67cb 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectAttributeMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java @@ -1,7 +1,7 @@ -package info.FrostFS.sdk.mappers.object; +package info.frostfs.sdk.mappers.object; -import frostFS.object.Types; -import info.FrostFS.sdk.dto.object.ObjectAttribute; +import frostfs.object.Types; +import info.frostfs.sdk.dto.object.ObjectAttribute; public class ObjectAttributeMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFilterMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java similarity index 82% rename from models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFilterMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java index 52adf8d..8bbe23e 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFilterMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers.object; +package info.frostfs.sdk.mappers.object; -import frostFS.object.Service; -import frostFS.object.Types; -import info.FrostFS.sdk.dto.object.ObjectFilter; +import frostfs.object.Service; +import frostfs.object.Types; +import info.frostfs.sdk.dto.object.ObjectFilter; import static java.util.Objects.isNull; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java similarity index 67% rename from models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java index 22cc305..28b8332 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectFrostFSMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers.object; +package info.frostfs.sdk.mappers.object; -import frostFS.object.Types; -import info.FrostFS.sdk.dto.object.ObjectFrostFS; -import info.FrostFS.sdk.dto.object.ObjectId; +import frostfs.object.Types; +import info.frostfs.sdk.dto.object.ObjectFrostFS; +import info.frostfs.sdk.dto.object.ObjectId; public class ObjectFrostFSMapper { diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectHeaderMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java similarity index 80% rename from models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectHeaderMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java index d47dc55..6b8bc91 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectHeaderMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java @@ -1,12 +1,12 @@ -package info.FrostFS.sdk.mappers.object; +package info.frostfs.sdk.mappers.object; -import frostFS.object.Types; -import info.FrostFS.sdk.dto.container.ContainerId; -import info.FrostFS.sdk.dto.object.ObjectAttribute; -import info.FrostFS.sdk.dto.object.ObjectHeader; -import info.FrostFS.sdk.enums.ObjectType; -import info.FrostFS.sdk.mappers.VersionMapper; -import info.FrostFS.sdk.mappers.container.ContainerIdMapper; +import frostfs.object.Types; +import info.frostfs.sdk.dto.container.ContainerId; +import info.frostfs.sdk.dto.object.ObjectAttribute; +import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.enums.ObjectType; +import info.frostfs.sdk.mappers.VersionMapper; +import info.frostfs.sdk.mappers.container.ContainerIdMapper; import java.util.stream.Collectors; diff --git a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectIdMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java similarity index 78% rename from models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectIdMapper.java rename to models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java index 437b4bb..62ca7c5 100644 --- a/models/src/main/java/info/FrostFS/sdk/mappers/object/ObjectIdMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java @@ -1,8 +1,8 @@ -package info.FrostFS.sdk.mappers.object; +package info.frostfs.sdk.mappers.object; import com.google.protobuf.ByteString; -import frostFS.refs.Types; -import info.FrostFS.sdk.dto.object.ObjectId; +import frostfs.refs.Types; +import info.frostfs.sdk.dto.object.ObjectId; public class ObjectIdMapper { diff --git a/pom.xml b/pom.xml index 8423cfb..561413c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - info.FrostFS.sdk - FrostFS-sdk-java + info.frostfs.sdk + frostfs-sdk-java 0.1.0 pom diff --git a/protos/pom.xml b/protos/pom.xml index cee5fb0..d2e06dc 100644 --- a/protos/pom.xml +++ b/protos/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - info.FrostFS.sdk - FrostFS-sdk-java + info.frostfs.sdk + frostfs-sdk-java 0.1.0 diff --git a/protos/src/main/proto/accounting/service.proto b/protos/src/main/proto/accounting/service.proto index c225c58..414d71d 100644 --- a/protos/src/main/proto/accounting/service.proto +++ b/protos/src/main/proto/accounting/service.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.accounting; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc;accounting"; -option java_package = "frostFS.accounting"; +option java_package = "frostfs.accounting"; import "accounting/types.proto"; import "refs/types.proto"; diff --git a/protos/src/main/proto/accounting/types.proto b/protos/src/main/proto/accounting/types.proto index 57229d9..61952f5 100644 --- a/protos/src/main/proto/accounting/types.proto +++ b/protos/src/main/proto/accounting/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.accounting; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc;accounting"; -option java_package = "frostFS.accounting"; +option java_package = "frostfs.accounting"; // Standard floating point data type can't be used in NeoFS due to inexactness // of the result when doing lots of small number operations. To solve the lost diff --git a/protos/src/main/proto/acl/types.proto b/protos/src/main/proto/acl/types.proto index 86a9311..b59ac7d 100644 --- a/protos/src/main/proto/acl/types.proto +++ b/protos/src/main/proto/acl/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.acl; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl/grpc;acl"; -option java_package = "frostFS.acl"; +option java_package = "frostfs.acl"; import "refs/types.proto"; diff --git a/protos/src/main/proto/apemanager/service.proto b/protos/src/main/proto/apemanager/service.proto index da0da48..d4eeca2 100644 --- a/protos/src/main/proto/apemanager/service.proto +++ b/protos/src/main/proto/apemanager/service.proto @@ -6,7 +6,7 @@ import "apemanager/types.proto"; import "session/types.proto"; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc;apemanager"; -option java_package = "frostFS.apemanager"; +option java_package = "frostfs.apemanager"; // `APEManagerService` provides API to manage rule chains within sidechain's // `Policy` smart contract. diff --git a/protos/src/main/proto/apemanager/types.proto b/protos/src/main/proto/apemanager/types.proto index 644a8b5..7ca80ae 100644 --- a/protos/src/main/proto/apemanager/types.proto +++ b/protos/src/main/proto/apemanager/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package frostfs.v2.apemanager; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc;apemanager"; -option java_package = "frostFS.apemanager"; +option java_package = "frostfs.apemanager"; // TargetType is a type target to which a rule chain is defined. enum TargetType { diff --git a/protos/src/main/proto/container/service.proto b/protos/src/main/proto/container/service.proto index ce7634a..6a85979 100644 --- a/protos/src/main/proto/container/service.proto +++ b/protos/src/main/proto/container/service.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.container; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc;container"; -option java_package = "frostFS.container"; +option java_package = "frostfs.container"; import "acl/types.proto"; import "container/types.proto"; diff --git a/protos/src/main/proto/container/types.proto b/protos/src/main/proto/container/types.proto index 128a0bd..fc523ca 100644 --- a/protos/src/main/proto/container/types.proto +++ b/protos/src/main/proto/container/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.container; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc;container"; -option java_package = "frostFS.container"; +option java_package = "frostfs.container"; import "netmap/types.proto"; import "refs/types.proto"; diff --git a/protos/src/main/proto/lock/types.proto b/protos/src/main/proto/lock/types.proto index 85766db..e4a8879 100644 --- a/protos/src/main/proto/lock/types.proto +++ b/protos/src/main/proto/lock/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.lock; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/lock/grpc;lock"; -option java_package = "frostFS.lock"; +option java_package = "frostfs.lock"; import "refs/types.proto"; diff --git a/protos/src/main/proto/netmap/service.proto b/protos/src/main/proto/netmap/service.proto index ac4f4cc..7e97e09 100644 --- a/protos/src/main/proto/netmap/service.proto +++ b/protos/src/main/proto/netmap/service.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.netmap; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc;netmap"; -option java_package = "frostFS.netmap"; +option java_package = "frostfs.netmap"; import "netmap/types.proto"; import "refs/types.proto"; diff --git a/protos/src/main/proto/netmap/types.proto b/protos/src/main/proto/netmap/types.proto index 1ff2e9e..3c311ba 100644 --- a/protos/src/main/proto/netmap/types.proto +++ b/protos/src/main/proto/netmap/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.netmap; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc;netmap"; -option java_package = "frostFS.netmap"; +option java_package = "frostfs.netmap"; // Operations on filters enum Operation { diff --git a/protos/src/main/proto/object/service.proto b/protos/src/main/proto/object/service.proto index 98ce6f0..7635f8a 100644 --- a/protos/src/main/proto/object/service.proto +++ b/protos/src/main/proto/object/service.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.object; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc;object"; -option java_package = "frostFS.object"; +option java_package = "frostfs.object"; import "object/types.proto"; import "refs/types.proto"; diff --git a/protos/src/main/proto/object/types.proto b/protos/src/main/proto/object/types.proto index 3162270..623c2a3 100644 --- a/protos/src/main/proto/object/types.proto +++ b/protos/src/main/proto/object/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.object; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc;object"; -option java_package = "frostFS.object"; +option java_package = "frostfs.object"; import "refs/types.proto"; import "session/types.proto"; diff --git a/protos/src/main/proto/refs/types.proto b/protos/src/main/proto/refs/types.proto index 30cb552..0ed5840 100644 --- a/protos/src/main/proto/refs/types.proto +++ b/protos/src/main/proto/refs/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.refs; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc;refs"; -option java_package = "frostFS.refs"; +option java_package = "frostfs.refs"; // Objects in NeoFS are addressed by their ContainerID and ObjectID. // diff --git a/protos/src/main/proto/session/service.proto b/protos/src/main/proto/session/service.proto index 84cbff4..b31bd8e 100644 --- a/protos/src/main/proto/session/service.proto +++ b/protos/src/main/proto/session/service.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.session; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc;session"; -option java_package = "frostFS.session"; +option java_package = "frostfs.session"; import "refs/types.proto"; import "session/types.proto"; diff --git a/protos/src/main/proto/session/types.proto b/protos/src/main/proto/session/types.proto index 2b33386..9f5259a 100644 --- a/protos/src/main/proto/session/types.proto +++ b/protos/src/main/proto/session/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.session; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc;session"; -option java_package = "frostFS.session"; +option java_package = "frostfs.session"; import "refs/types.proto"; import "acl/types.proto"; diff --git a/protos/src/main/proto/status/types.proto b/protos/src/main/proto/status/types.proto index b7be372..7d8f8e9 100644 --- a/protos/src/main/proto/status/types.proto +++ b/protos/src/main/proto/status/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.status; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status/grpc;status"; -option java_package = "frostFS.status"; +option java_package = "frostfs.status"; // Declares the general format of the status returns of the NeoFS RPC protocol. // Status is present in all response messages. Each RPC of NeoFS protocol diff --git a/protos/src/main/proto/tombstone/types.proto b/protos/src/main/proto/tombstone/types.proto index 3e821c1..9128160 100644 --- a/protos/src/main/proto/tombstone/types.proto +++ b/protos/src/main/proto/tombstone/types.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package neo.fs.v2.tombstone; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/tombstone/grpc;tombstone"; -option java_package = "frostFS.tombstone"; +option java_package = "frostfs.tombstone"; import "refs/types.proto"; -- 2.45.2 From 1be65c63aed28d9dbfd48ec8428aff52ed4c20f6 Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Wed, 24 Jul 2024 14:41:42 +0300 Subject: [PATCH 6/7] [#1] Add additional security Signed-off-by: Ori Bruk --- README.md | 4 +- client/pom.xml | 4 +- .../sdk/{services => }/FrostFSClient.java | 57 ++++++------ .../frostfs/sdk/constants/CryptoConst.java | 3 + .../frostfs/sdk/jdo/ClientEnvironment.java | 11 ++- .../info/frostfs/sdk/jdo/ClientSettings.java | 8 ++ .../main/java/info/frostfs/sdk/jdo/ECDsa.java | 6 ++ .../frostfs/sdk/jdo/PutObjectParameters.java | 4 + ...rService.java => ContainerClientImpl.java} | 84 +++++++++-------- ...tmapService.java => NetmapClientImpl.java} | 16 ++-- ...jectService.java => ObjectClientImpl.java} | 93 ++++++++++--------- ...{ObjectTools.java => ObjectToolsImpl.java} | 30 +++--- ...ionService.java => SessionClientImpl.java} | 17 ++-- .../impl/{ => rwhelper}/ObjectReader.java | 2 +- .../impl/{ => rwhelper}/ObjectWriter.java | 2 +- .../impl/{ => rwhelper}/SearchReader.java | 2 +- .../info/frostfs/sdk/tools/GrpcClient.java | 3 + .../info/frostfs/sdk/tools/MessageHelper.java | 3 + .../frostfs/sdk/tools/RequestConstructor.java | 15 ++- .../info/frostfs/sdk/tools/RequestSigner.java | 5 +- .../java/info/frostfs/sdk/tools/Verifier.java | 23 ++++- cryptography/pom.xml | 5 + .../java/info/frostfs/sdk/ArrayHelper.java | 2 + .../main/java/info/frostfs/sdk/Base58.java | 18 +++- .../main/java/info/frostfs/sdk/Helper.java | 24 ++++- .../java/info/frostfs/sdk/KeyExtension.java | 31 ++++++- models/pom.xml | 15 ++- .../java/info/frostfs/sdk/UUIDExtension.java | 20 +++- .../info/frostfs/sdk/constants/AppConst.java | 5 + .../frostfs/sdk/constants/FieldConst.java | 4 + .../frostfs/sdk/constants/XHeaderConst.java | 3 + .../java/info/frostfs/sdk/dto/MetaHeader.java | 26 +++++- .../java/info/frostfs/sdk/dto/OwnerId.java | 9 +- .../main/java/info/frostfs/sdk/dto/Split.java | 12 ++- .../java/info/frostfs/sdk/dto/SplitId.java | 20 ++-- .../java/info/frostfs/sdk/dto/Status.java | 5 +- .../java/info/frostfs/sdk/dto/Version.java | 25 +++-- .../sdk/dto/container/ContainerId.java | 22 +++-- .../info/frostfs/sdk/dto/netmap/Replica.java | 28 +++--- .../frostfs/sdk/dto/object/LargeObject.java | 5 + .../frostfs/sdk/dto/object/LinkObject.java | 5 + .../sdk/dto/object/ObjectAttribute.java | 18 ++-- .../frostfs/sdk/dto/object/ObjectFrostFS.java | 18 ++-- .../frostfs/sdk/dto/object/ObjectHeader.java | 34 ++++--- .../info/frostfs/sdk/dto/object/ObjectId.java | 18 +++- .../frostfs/sdk/mappers/MetaHeaderMapper.java | 9 ++ .../frostfs/sdk/mappers/OwnerIdMapper.java | 9 ++ .../frostfs/sdk/mappers/SessionMapper.java | 13 +++ .../frostfs/sdk/mappers/SignatureMapper.java | 9 +- .../frostfs/sdk/mappers/StatusMapper.java | 7 +- .../frostfs/sdk/mappers/VersionMapper.java | 13 +++ .../mappers/container/ContainerIdMapper.java | 9 ++ .../mappers/container/ContainerMapper.java | 11 +++ .../mappers/netmap/NetmapSnapshotMapper.java | 9 ++ .../sdk/mappers/netmap/NodeInfoMapper.java | 11 +++ .../mappers/netmap/PlacementPolicyMapper.java | 13 +++ .../sdk/mappers/netmap/ReplicaMapper.java | 13 +++ .../mappers/object/ObjectAttributeMapper.java | 13 +++ .../mappers/object/ObjectFilterMapper.java | 7 ++ .../mappers/object/ObjectFrostFSMapper.java | 17 +++- .../mappers/object/ObjectHeaderMapper.java | 13 ++- .../sdk/mappers/object/ObjectIdMapper.java | 11 ++- 62 files changed, 670 insertions(+), 281 deletions(-) rename client/src/main/java/info/frostfs/sdk/{services => }/FrostFSClient.java (65%) rename client/src/main/java/info/frostfs/sdk/services/impl/{ContainerService.java => ContainerClientImpl.java} (58%) rename client/src/main/java/info/frostfs/sdk/services/impl/{NetmapService.java => NetmapClientImpl.java} (91%) rename client/src/main/java/info/frostfs/sdk/services/impl/{ObjectService.java => ObjectClientImpl.java} (81%) rename client/src/main/java/info/frostfs/sdk/services/impl/{ObjectTools.java => ObjectToolsImpl.java} (79%) rename client/src/main/java/info/frostfs/sdk/services/impl/{SessionService.java => SessionClientImpl.java} (79%) rename client/src/main/java/info/frostfs/sdk/services/impl/{ => rwhelper}/ObjectReader.java (96%) rename client/src/main/java/info/frostfs/sdk/services/impl/{ => rwhelper}/ObjectWriter.java (97%) rename client/src/main/java/info/frostfs/sdk/services/impl/{ => rwhelper}/SearchReader.java (91%) diff --git a/README.md b/README.md index ff4652e..bd5444b 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ import info.frostfs.sdk.dto.netmap.PlacementPolicy; import info.frostfs.sdk.dto.netmap.Replica; import info.frostfs.sdk.enums.BasicAcl; import info.frostfs.sdk.jdo.ClientSettings; -import info.frostfs.sdk.services.FrostFSClient; +import info.frostfs.sdk.FrostFSClient; public class ContainerExample { @@ -59,7 +59,7 @@ import info.frostfs.sdk.dto.object.ObjectAttribute; import info.frostfs.sdk.dto.object.ObjectFilter; import info.frostfs.sdk.dto.object.ObjectHeader; import info.frostfs.sdk.jdo.PutObjectParameters; -import info.frostfs.sdk.services.FrostFSClient; +import info.frostfs.sdk.FrostFSClient; import java.io.FileInputStream; import java.io.IOException; diff --git a/client/pom.xml b/client/pom.xml index 917fc46..bb808ce 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/client/src/main/java/info/frostfs/sdk/services/FrostFSClient.java b/client/src/main/java/info/frostfs/sdk/FrostFSClient.java similarity index 65% rename from client/src/main/java/info/frostfs/sdk/services/FrostFSClient.java rename to client/src/main/java/info/frostfs/sdk/FrostFSClient.java index da87a20..48fdcc5 100644 --- a/client/src/main/java/info/frostfs/sdk/services/FrostFSClient.java +++ b/client/src/main/java/info/frostfs/sdk/FrostFSClient.java @@ -1,4 +1,4 @@ -package info.frostfs.sdk.services; +package info.frostfs.sdk; import frostfs.session.Types; import info.frostfs.sdk.dto.SessionToken; @@ -15,6 +15,7 @@ import info.frostfs.sdk.jdo.ClientEnvironment; import info.frostfs.sdk.jdo.ClientSettings; import info.frostfs.sdk.jdo.NetworkSettings; import info.frostfs.sdk.jdo.PutObjectParameters; +import info.frostfs.sdk.services.*; import info.frostfs.sdk.services.impl.*; import io.grpc.Channel; @@ -27,11 +28,11 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien private static final String ERROR_CLIENT_OPTIONS_INIT = "Options must be initialized."; private static final String ERROR_VERSION_SUPPORT_TEMPLATE = "FrostFS %s is not supported."; - private final ContainerService containerService; - private final NetmapService netmapService; - private final ObjectService objectService; - private final SessionService sessionService; - private final ObjectTools objectTools; + private final ContainerClientImpl containerClientImpl; + private final NetmapClientImpl netmapClientImpl; + private final ObjectClientImpl objectClientImpl; + private final SessionClientImpl sessionClientImpl; + private final ObjectToolsImpl objectToolsImpl; public FrostFSClient(ClientSettings clientSettings) { if (isNull(clientSettings)) { @@ -43,18 +44,18 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien Channel channel = initGrpcChannel(clientSettings.getHost(), clientSettings.getCreds()); ClientEnvironment clientEnvironment = - new ClientEnvironment(clientSettings.getKey(), channel, new Version(2, 13), this); + new ClientEnvironment(clientSettings.getKey(), channel, new Version(), this); - this.containerService = new ContainerService(clientEnvironment); - this.netmapService = new NetmapService(clientEnvironment); - this.sessionService = new SessionService(clientEnvironment); - this.objectService = new ObjectService(clientEnvironment); - this.objectTools = new ObjectTools(clientEnvironment); + this.containerClientImpl = new ContainerClientImpl(clientEnvironment); + this.netmapClientImpl = new NetmapClientImpl(clientEnvironment); + this.sessionClientImpl = new SessionClientImpl(clientEnvironment); + this.objectClientImpl = new ObjectClientImpl(clientEnvironment); + this.objectToolsImpl = new ObjectToolsImpl(clientEnvironment); checkFrostFsVersionSupport(clientEnvironment.getVersion()); } private void checkFrostFsVersionSupport(Version version) { - var localNodeInfo = netmapService.getLocalNodeInfo(); + var localNodeInfo = netmapClientImpl.getLocalNodeInfo(); if (!localNodeInfo.getVersion().isSupported(version)) { throw new IllegalArgumentException( String.format(ERROR_VERSION_SUPPORT_TEMPLATE, localNodeInfo.getVersion()) @@ -64,75 +65,75 @@ public class FrostFSClient implements ContainerClient, ObjectClient, NetmapClien @Override public Container getContainer(ContainerId cid) { - return containerService.getContainer(cid); + return containerClientImpl.getContainer(cid); } @Override public List listContainers() { - return containerService.listContainers(); + return containerClientImpl.listContainers(); } @Override public ContainerId createContainer(Container container) { - return containerService.createContainer(container); + return containerClientImpl.createContainer(container); } @Override public void deleteContainer(ContainerId cid) { - containerService.deleteContainer(cid); + containerClientImpl.deleteContainer(cid); } @Override public ObjectHeader getObjectHead(ContainerId containerId, ObjectId objectId) { - return objectService.getObjectHead(containerId, objectId); + return objectClientImpl.getObjectHead(containerId, objectId); } @Override public ObjectFrostFS getObject(ContainerId containerId, ObjectId objectId) { - return objectService.getObject(containerId, objectId); + return objectClientImpl.getObject(containerId, objectId); } @Override public ObjectId putObject(PutObjectParameters parameters) { - return objectService.putObject(parameters); + return objectClientImpl.putObject(parameters); } @Override public void deleteObject(ContainerId containerId, ObjectId objectId) { - objectService.deleteObject(containerId, objectId); + objectClientImpl.deleteObject(containerId, objectId); } @Override public Iterable searchObjects(ContainerId cid, ObjectFilter... filters) { - return objectService.searchObjects(cid, filters); + return objectClientImpl.searchObjects(cid, filters); } @Override public NetmapSnapshot getNetmapSnapshot() { - return netmapService.getNetmapSnapshot(); + return netmapClientImpl.getNetmapSnapshot(); } @Override public NodeInfo getLocalNodeInfo() { - return netmapService.getLocalNodeInfo(); + return netmapClientImpl.getLocalNodeInfo(); } @Override public NetworkSettings getNetworkSettings() { - return netmapService.getNetworkSettings(); + return netmapClientImpl.getNetworkSettings(); } @Override public SessionToken createSession(long expiration) { - return sessionService.createSession(expiration); + return sessionClientImpl.createSession(expiration); } public Types.SessionToken createSessionInternal(long expiration) { - return sessionService.createSessionInternal(expiration); + return sessionClientImpl.createSessionInternal(expiration); } @Override public ObjectId calculateObjectId(ObjectHeader header) { - return objectTools.calculateObjectId(header); + return objectToolsImpl.calculateObjectId(header); } } diff --git a/client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java b/client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java index 84db5c9..4e28686 100644 --- a/client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java +++ b/client/src/main/java/info/frostfs/sdk/constants/CryptoConst.java @@ -2,4 +2,7 @@ package info.frostfs.sdk.constants; public class CryptoConst { public static final String SIGNATURE_ALGORITHM = "NONEwithECDSAinP1363Format"; + + private CryptoConst() { + } } diff --git a/client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java b/client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java index 2165f06..6b140d3 100644 --- a/client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/ClientEnvironment.java @@ -2,8 +2,11 @@ package info.frostfs.sdk.jdo; import info.frostfs.sdk.dto.OwnerId; import info.frostfs.sdk.dto.Version; -import info.frostfs.sdk.services.FrostFSClient; +import info.frostfs.sdk.FrostFSClient; import io.grpc.Channel; +import org.apache.commons.lang3.StringUtils; + +import static java.util.Objects.isNull; public class ClientEnvironment { private final OwnerId ownerId; @@ -14,8 +17,12 @@ public class ClientEnvironment { private NetworkSettings networkSettings; public ClientEnvironment(String wif, Channel channel, Version version, FrostFSClient frostFSClient) { + if (StringUtils.isEmpty(wif) || isNull(channel) || isNull(version) || isNull(frostFSClient)) { + throw new IllegalArgumentException("One of the input attributes is missing"); + } + this.key = new ECDsa(wif); - this.ownerId = OwnerId.fromKey(key.getPublicKeyByte()); + this.ownerId = new OwnerId(key.getPublicKeyByte()); this.version = version; this.channel = channel; this.frostFSClient = frostFSClient; diff --git a/client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java b/client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java index 03b83ad..5f7bd32 100644 --- a/client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/ClientSettings.java @@ -13,6 +13,14 @@ public class ClientSettings { public ClientSettings(String key, String host) { this.key = key; this.host = host; + validate(); + } + + public ClientSettings(String key, String host, ChannelCredentials creds) { + this.key = key; + this.host = host; + this.creds = creds; + validate(); } public ChannelCredentials getCreds() { diff --git a/client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java b/client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java index 060eef9..d328c10 100644 --- a/client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/ECDsa.java @@ -1,5 +1,7 @@ package info.frostfs.sdk.jdo; +import org.apache.commons.lang3.StringUtils; + import java.security.PrivateKey; import static info.frostfs.sdk.KeyExtension.*; @@ -10,6 +12,10 @@ public class ECDsa { private final PrivateKey privateKey; public ECDsa(String wif) { + if (StringUtils.isEmpty(wif)) { + throw new IllegalArgumentException("Wif is invalid"); + } + this.privateKeyByte = getPrivateKeyFromWIF(wif); this.publicKeyByte = loadPublicKey(privateKeyByte); this.privateKey = loadPrivateKey(privateKeyByte); diff --git a/client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java b/client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java index cd3338d..3c4ecdd 100644 --- a/client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java +++ b/client/src/main/java/info/frostfs/sdk/jdo/PutObjectParameters.java @@ -19,11 +19,15 @@ public class PutObjectParameters { this.payload = payload; this.clientCut = clientCut; this.bufferMaxSize = bufferMaxSize; + + validate(); } public PutObjectParameters(ObjectHeader header, FileInputStream payload) { this.header = header; this.payload = payload; + + validate(); } public ObjectHeader getHeader() { diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/ContainerService.java b/client/src/main/java/info/frostfs/sdk/services/impl/ContainerClientImpl.java similarity index 58% rename from client/src/main/java/info/frostfs/sdk/services/impl/ContainerService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ContainerClientImpl.java index 1e2f5e7..5c0e7af 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/ContainerService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ContainerClientImpl.java @@ -11,33 +11,36 @@ import info.frostfs.sdk.mappers.container.ContainerIdMapper; import info.frostfs.sdk.mappers.container.ContainerMapper; import info.frostfs.sdk.services.ContainerClient; import info.frostfs.sdk.services.ContextAccessor; -import info.frostfs.sdk.tools.Verifier; import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.RequestSigner; +import info.frostfs.sdk.tools.Verifier; import java.util.List; import java.util.stream.Collectors; -import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; -import static info.frostfs.sdk.tools.RequestSigner.signRFC6979; +import static java.util.Objects.isNull; -public class ContainerService extends ContextAccessor implements ContainerClient { +public class ContainerClientImpl extends ContextAccessor implements ContainerClient { private final ContainerServiceGrpc.ContainerServiceBlockingStub serviceBlockingStub; - public ContainerService(ClientEnvironment clientEnvironment) { + public ContainerClientImpl(ClientEnvironment clientEnvironment) { super(clientEnvironment); this.serviceBlockingStub = ContainerServiceGrpc.newBlockingStub(clientEnvironment.getChannel()); } + @Override public Container getContainer(ContainerId cid) { - var request = Service.GetRequest.newBuilder() - .setBody( - Service.GetRequest.Body.newBuilder() - .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) - .build() - ); + if (isNull(cid)) { + throw new IllegalArgumentException("ContainerId is not present"); + } - RequestConstructor.addMetaHeader(request); + var body = Service.GetRequest.Body.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .build(); + var request = Service.GetRequest.newBuilder() + .setBody(body); + + RequestConstructor.addDefaultMetaHeader(request); RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.get(request.build()); @@ -46,15 +49,15 @@ public class ContainerService extends ContextAccessor implements ContainerClient return ContainerMapper.toModel(response.getBody().getContainer()); } + @Override public List listContainers() { + var body = Service.ListRequest.Body.newBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) + .build(); var request = Service.ListRequest.newBuilder() - .setBody( - Service.ListRequest.Body.newBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) - .build() - ); + .setBody(body); - RequestConstructor.addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.list(request.build()); @@ -62,51 +65,54 @@ public class ContainerService extends ContextAccessor implements ContainerClient Verifier.checkResponse(response); return response.getBody().getContainerIdsList().stream() - .map(cid -> ContainerId.fromHash(cid.getValue().toByteArray())) + .map(cid -> new ContainerId(cid.getValue().toByteArray())) .collect(Collectors.toList()); } + @Override public ContainerId createContainer(Container container) { - var grpcContainer = ContainerMapper.toGrpcMessage(container); + if (isNull(container)) { + throw new IllegalArgumentException("Container is not present"); + } + var grpcContainer = ContainerMapper.toGrpcMessage(container); grpcContainer = grpcContainer.toBuilder() .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())) .build(); + var body = Service.PutRequest.Body.newBuilder() + .setContainer(grpcContainer) + .setSignature(RequestSigner.signRFC6979(getContext().getKey(), grpcContainer)) + .build(); var request = Service.PutRequest.newBuilder() - .setBody( - Service.PutRequest.Body.newBuilder() - .setContainer(grpcContainer) - .setSignature( - RequestSigner.signRFC6979(getContext().getKey(), grpcContainer) - ) - .build() - ); + .setBody(body); - RequestConstructor.addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.put(request.build()); Verifier.checkResponse(response); - return ContainerId.fromHash(response.getBody().getContainerId().getValue().toByteArray()); + return new ContainerId(response.getBody().getContainerId().getValue().toByteArray()); } + @Override public void deleteContainer(ContainerId cid) { + if (isNull(cid)) { + throw new IllegalArgumentException("ContainerId is not present"); + } + var grpcContainerId = ContainerIdMapper.toGrpcMessage(cid); + var body = Service.DeleteRequest.Body.newBuilder() + .setContainerId(grpcContainerId) + .setSignature(RequestSigner.signRFC6979(getContext().getKey(), grpcContainerId.getValue())) + .build(); var request = Service.DeleteRequest.newBuilder() - .setBody( - Service.DeleteRequest.Body.newBuilder() - .setContainerId(grpcContainerId) - .setSignature(RequestSigner.signRFC6979( - getContext().getKey(), grpcContainerId.getValue() - )) - .build() - ); + .setBody(body); - RequestConstructor.addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); RequestSigner.sign(request, getContext().getKey()); var response = serviceBlockingStub.delete(request.build()); diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/NetmapService.java b/client/src/main/java/info/frostfs/sdk/services/impl/NetmapClientImpl.java similarity index 91% rename from client/src/main/java/info/frostfs/sdk/services/impl/NetmapService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/NetmapClientImpl.java index 19c5995..b38624c 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/NetmapService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/NetmapClientImpl.java @@ -11,25 +11,27 @@ import info.frostfs.sdk.mappers.netmap.NetmapSnapshotMapper; import info.frostfs.sdk.mappers.netmap.NodeInfoMapper; import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.NetmapClient; +import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.Verifier; import java.nio.charset.StandardCharsets; -import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; import static info.frostfs.sdk.tools.RequestSigner.sign; import static java.util.Objects.nonNull; -public class NetmapService extends ContextAccessor implements NetmapClient { +public class NetmapClientImpl extends ContextAccessor implements NetmapClient { private final NetmapServiceGrpc.NetmapServiceBlockingStub netmapServiceClient; - public NetmapService(ClientEnvironment clientEnvironment) { + public NetmapClientImpl(ClientEnvironment clientEnvironment) { super(clientEnvironment); this.netmapServiceClient = NetmapServiceGrpc.newBlockingStub(getContext().getChannel()); } private static boolean getBoolValue(byte[] bytes) { for (var byteValue : bytes) { - if (byteValue != 0) return true; + if (byteValue != 0) { + return true; + } } return false; @@ -115,7 +117,7 @@ public class NetmapService extends ContextAccessor implements NetmapClient { var request = Service.LocalNodeInfoRequest.newBuilder() .setBody(Service.LocalNodeInfoRequest.Body.newBuilder().build()); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); var response = netmapServiceClient.localNodeInfo(request.build()); @@ -128,7 +130,7 @@ public class NetmapService extends ContextAccessor implements NetmapClient { var request = Service.NetworkInfoRequest.newBuilder() .setBody(Service.NetworkInfoRequest.Body.newBuilder().build()); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); var response = netmapServiceClient.networkInfo(request.build()); @@ -143,7 +145,7 @@ public class NetmapService extends ContextAccessor implements NetmapClient { var request = Service.NetmapSnapshotRequest.newBuilder() .setBody(Service.NetmapSnapshotRequest.Body.newBuilder().build()); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); var response = netmapServiceClient.netmapSnapshot(request.build()); diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectService.java b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectClientImpl.java similarity index 81% rename from client/src/main/java/info/frostfs/sdk/services/impl/ObjectService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ObjectClientImpl.java index ca2652b..69046d6 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectClientImpl.java @@ -20,6 +20,10 @@ import info.frostfs.sdk.mappers.object.ObjectHeaderMapper; import info.frostfs.sdk.mappers.object.ObjectIdMapper; import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.ObjectClient; +import info.frostfs.sdk.services.impl.rwhelper.ObjectReader; +import info.frostfs.sdk.services.impl.rwhelper.ObjectWriter; +import info.frostfs.sdk.services.impl.rwhelper.SearchReader; +import info.frostfs.sdk.tools.RequestConstructor; import info.frostfs.sdk.tools.Verifier; import org.apache.commons.collections4.CollectionUtils; @@ -30,39 +34,37 @@ import java.util.Arrays; import java.util.List; import static info.frostfs.sdk.Helper.getSha256; -import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; import static info.frostfs.sdk.tools.RequestConstructor.addObjectSessionToken; import static info.frostfs.sdk.tools.RequestSigner.sign; import static java.util.Objects.nonNull; -public class ObjectService extends ContextAccessor implements ObjectClient { +public class ObjectClientImpl extends ContextAccessor implements ObjectClient { private static final String ERROR_PAYLOAD = "PayloadLength must be specified"; private final ObjectServiceGrpc.ObjectServiceBlockingStub objectServiceBlockingClient; private final ObjectServiceGrpc.ObjectServiceStub objectServiceClient; - private final ObjectTools objectTools; + private final ObjectToolsImpl objectToolsImpl; - public ObjectService(ClientEnvironment clientEnvironment) { + public ObjectClientImpl(ClientEnvironment clientEnvironment) { super(clientEnvironment); this.objectServiceBlockingClient = ObjectServiceGrpc.newBlockingStub(getContext().getChannel()); this.objectServiceClient = ObjectServiceGrpc.newStub(getContext().getChannel()); - this.objectTools = new ObjectTools(clientEnvironment); + this.objectToolsImpl = new ObjectToolsImpl(clientEnvironment); } @Override public ObjectHeader getObjectHead(ContainerId cid, ObjectId oid) { + var address = Types.Address.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) + .build(); + var body = Service.HeadRequest.Body.newBuilder() + .setAddress(address) + .build(); var request = Service.HeadRequest.newBuilder() - .setBody( - Service.HeadRequest.Body.newBuilder() - .setAddress( - Types.Address.newBuilder() - .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) - .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) - .build() - ).build() - ); + .setBody(body); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); var response = objectServiceBlockingClient.head(request.build()); @@ -75,19 +77,17 @@ public class ObjectService extends ContextAccessor implements ObjectClient { public ObjectFrostFS getObject(ContainerId cid, ObjectId oid) { var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1); + var address = Types.Address.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) + .build(); + var body = Service.GetRequest.Body.newBuilder() + .setAddress(address) + .build(); var request = Service.GetRequest.newBuilder() - .setBody( - Service.GetRequest.Body.newBuilder() - .setAddress( - Types.Address.newBuilder() - .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) - .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) - .build() - ) - .build() - ); + .setBody(body); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); addObjectSessionToken( request, sessionToken, ContainerIdMapper.toGrpcMessage(cid), ObjectIdMapper.toGrpcMessage(oid), frostfs.session.Types.ObjectSessionContext.Verb.GET, getContext().getKey() @@ -101,18 +101,17 @@ public class ObjectService extends ContextAccessor implements ObjectClient { @Override public void deleteObject(ContainerId cid, ObjectId oid) { + var address = Types.Address.newBuilder() + .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) + .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) + .build(); + var body = Service.DeleteRequest.Body.newBuilder() + .setAddress(address) + .build(); var request = Service.DeleteRequest.newBuilder() - .setBody( - Service.DeleteRequest.Body.newBuilder() - .setAddress( - Types.Address.newBuilder() - .setContainerId(ContainerIdMapper.toGrpcMessage(cid)) - .setObjectId(ObjectIdMapper.toGrpcMessage(oid)) - .build() - ) - .build()); + .setBody(body); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); var response = objectServiceBlockingClient.delete(request.build()); @@ -132,12 +131,12 @@ public class ObjectService extends ContextAccessor implements ObjectClient { var request = Service.SearchRequest.newBuilder() .setBody(body.build()); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); var objectsIds = searchObjects(request.build()); - return Iterables.transform(objectsIds, input -> ObjectId.fromHash(input.getValue().toByteArray())); + return Iterables.transform(objectsIds, input -> new ObjectId(input.getValue().toByteArray())); } @Override @@ -150,13 +149,13 @@ public class ObjectService extends ContextAccessor implements ObjectClient { public ObjectId putSingleObject(ObjectFrostFS modelObject) { var sessionToken = getContext().getFrostFSClient().createSessionInternal(-1); - var grpcObject = objectTools.createObject(modelObject); + var grpcObject = objectToolsImpl.createObject(modelObject); var request = Service.PutSingleRequest.newBuilder() .setBody(Service.PutSingleRequest.Body.newBuilder().setObject(grpcObject).build()); - addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); addObjectSessionToken( request, sessionToken, grpcObject.getHeader().getContainerId(), grpcObject.getObjectId(), frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() @@ -167,7 +166,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { Verifier.checkResponse(response); - return ObjectId.fromHash(grpcObject.getObjectId().getValue().toByteArray()); + return new ObjectId(grpcObject.getObjectId().getValue().toByteArray()); } private frostfs.object.Types.Object getObject(Service.GetRequest request) { @@ -215,7 +214,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { ).build() ); - addMetaHeader(initRequest); + RequestConstructor.addDefaultMetaHeader(initRequest); addObjectSessionToken( initRequest, sessionToken, hdr.getContainerId(), oid, frostfs.session.Types.ObjectSessionContext.Verb.PUT, getContext().getKey() @@ -232,8 +231,9 @@ public class ObjectService extends ContextAccessor implements ObjectClient { var buffer = new byte[bufferSize]; while (true) { var bytesCount = readNBytes(parameters.getPayload(), buffer, bufferSize); - if (bytesCount <= 0) + if (bytesCount <= 0) { break; + } var chunkRequest = Service.PutRequest.newBuilder(initRequest.build()) .setBody( @@ -249,7 +249,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { var response = writer.complete(); Verifier.checkResponse(response); - return ObjectId.fromHash(response.getBody().getObjectId().getValue().toByteArray()); + return new ObjectId(response.getBody().getObjectId().getValue().toByteArray()); } private ObjectId putClientCutObject(PutObjectParameters parameters) { @@ -285,8 +285,9 @@ public class ObjectService extends ContextAccessor implements ObjectClient { ); currentObject.setSplit(split); - if (largeObject.getPayloadLength() == fullLength) + if (largeObject.getPayloadLength() == fullLength) { break; + } objectId = putSingleObject(currentObject); @@ -314,7 +315,7 @@ public class ObjectService extends ContextAccessor implements ObjectClient { putSingleObject(linkObject); - return objectTools.calculateObjectId(largeObject.getHeader()); + return objectToolsImpl.calculateObjectId(largeObject.getHeader()); } private ObjectWriter putObjectInit(Service.PutRequest initRequest) { diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectTools.java b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectToolsImpl.java similarity index 79% rename from client/src/main/java/info/frostfs/sdk/services/impl/ObjectTools.java rename to client/src/main/java/info/frostfs/sdk/services/impl/ObjectToolsImpl.java index 5eb0680..b68a26e 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectTools.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/ObjectToolsImpl.java @@ -18,8 +18,8 @@ import static info.frostfs.sdk.Helper.getSha256; import static info.frostfs.sdk.tools.RequestSigner.signData; import static java.util.Objects.nonNull; -public class ObjectTools extends ContextAccessor implements ToolsClient { - public ObjectTools(ClientEnvironment context) { +public class ObjectToolsImpl extends ContextAccessor implements ToolsClient { + public ObjectToolsImpl(ClientEnvironment context) { super(context); } @@ -59,15 +59,13 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { if (nonNull(split.getParentHeader())) { var grpcParentHeader = createHeader(split.getParentHeader(), new byte[]{}); var parent = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcParentHeader)).build(); + var parentSig = frostfs.refs.Types.Signature.newBuilder() + .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) + .setSign(ByteString.copyFrom(signData(getContext().getKey(), parent.toByteArray()))); - splitGrpc - .setParent(parent) + splitGrpc.setParent(parent) .setParentHeader(grpcParentHeader) - .setParentSignature( - frostfs.refs.Types.Signature.newBuilder() - .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) - .setSign(ByteString.copyFrom(signData(getContext().getKey(), parent.toByteArray()))) - ); + .setParentSignature(parentSig); split.setParent(ObjectIdMapper.toModel(parent)); } @@ -79,15 +77,14 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { var grpcHeader = grpcHeaderBuilder.build(); var objectId = frostfs.refs.Types.ObjectID.newBuilder().setValue(getSha256(grpcHeader)).build(); + var sig = frostfs.refs.Types.Signature.newBuilder() + .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) + .setSign(ByteString.copyFrom(signData(getContext().getKey(), objectId.toByteArray()))); return Types.Object.newBuilder() .setHeader(grpcHeader) .setObjectId(objectId) .setPayload(ByteString.copyFrom(objectFrostFs.getPayload())) - .setSignature( - frostfs.refs.Types.Signature.newBuilder() - .setKey(ByteString.copyFrom(getContext().getKey().getPublicKeyByte())) - .setSign(ByteString.copyFrom(signData(getContext().getKey(), objectId.toByteArray()))) - ) + .setSignature(sig) .build(); } @@ -96,10 +93,11 @@ public class ObjectTools extends ContextAccessor implements ToolsClient { .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) .setVersion(VersionMapper.toGrpcMessage(getContext().getVersion())); - if (header.getPayloadCheckSum() != null) + if (header.getPayloadCheckSum() != null) { grpcHeader.setPayloadHash(sha256Checksum(header.getPayloadCheckSum())); - else if (payload != null) + } else if (payload != null) { grpcHeader.setPayloadHash(sha256Checksum(payload)); + } return grpcHeader.build(); } diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/SessionService.java b/client/src/main/java/info/frostfs/sdk/services/impl/SessionClientImpl.java similarity index 79% rename from client/src/main/java/info/frostfs/sdk/services/impl/SessionService.java rename to client/src/main/java/info/frostfs/sdk/services/impl/SessionClientImpl.java index d6bf950..137c178 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/SessionService.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/SessionClientImpl.java @@ -11,13 +11,12 @@ import info.frostfs.sdk.services.ContextAccessor; import info.frostfs.sdk.services.SessionClient; import info.frostfs.sdk.tools.RequestConstructor; -import static info.frostfs.sdk.tools.RequestConstructor.addMetaHeader; import static info.frostfs.sdk.tools.RequestSigner.sign; -public class SessionService extends ContextAccessor implements SessionClient { +public class SessionClientImpl extends ContextAccessor implements SessionClient { private final SessionServiceGrpc.SessionServiceBlockingStub serviceBlockingStub; - public SessionService(ClientEnvironment clientEnvironment) { + public SessionClientImpl(ClientEnvironment clientEnvironment) { super(clientEnvironment); this.serviceBlockingStub = SessionServiceGrpc.newBlockingStub(getContext().getChannel()); } @@ -30,14 +29,14 @@ public class SessionService extends ContextAccessor implements SessionClient { } public Types.SessionToken createSessionInternal(long expiration) { + var body = Service.CreateRequest.Body.newBuilder() + .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) + .setExpiration(expiration) + .build(); var request = Service.CreateRequest.newBuilder() - .setBody( - Service.CreateRequest.Body.newBuilder() - .setOwnerId(OwnerIdMapper.toGrpcMessage(getContext().getOwnerId())) - .setExpiration(expiration).build() - ); + .setBody(body); - RequestConstructor.addMetaHeader(request); + RequestConstructor.addDefaultMetaHeader(request); sign(request, getContext().getKey()); return createSession(request.build()); diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectReader.java b/client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/ObjectReader.java similarity index 96% rename from client/src/main/java/info/frostfs/sdk/services/impl/ObjectReader.java rename to client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/ObjectReader.java index 62a9a70..d686921 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectReader.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/ObjectReader.java @@ -1,4 +1,4 @@ -package info.frostfs.sdk.services.impl; +package info.frostfs.sdk.services.impl.rwhelper; import frostfs.object.Service; import frostfs.object.Types; diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectWriter.java b/client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/ObjectWriter.java similarity index 97% rename from client/src/main/java/info/frostfs/sdk/services/impl/ObjectWriter.java rename to client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/ObjectWriter.java index 8642dc8..7d6271b 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/ObjectWriter.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/ObjectWriter.java @@ -1,4 +1,4 @@ -package info.frostfs.sdk.services.impl; +package info.frostfs.sdk.services.impl.rwhelper; import frostfs.object.ObjectServiceGrpc; import frostfs.object.Service; diff --git a/client/src/main/java/info/frostfs/sdk/services/impl/SearchReader.java b/client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/SearchReader.java similarity index 91% rename from client/src/main/java/info/frostfs/sdk/services/impl/SearchReader.java rename to client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/SearchReader.java index 873d48b..ec42c05 100644 --- a/client/src/main/java/info/frostfs/sdk/services/impl/SearchReader.java +++ b/client/src/main/java/info/frostfs/sdk/services/impl/rwhelper/SearchReader.java @@ -1,4 +1,4 @@ -package info.frostfs.sdk.services.impl; +package info.frostfs.sdk.services.impl.rwhelper; import frostfs.object.Service; import info.frostfs.sdk.tools.Verifier; diff --git a/client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java b/client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java index 729d3e5..96ef9b2 100644 --- a/client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java +++ b/client/src/main/java/info/frostfs/sdk/tools/GrpcClient.java @@ -12,6 +12,9 @@ import static java.util.Objects.isNull; public class GrpcClient { private static final String ERROR_INVALID_HOST_TEMPLATE = "Host %s has invalid format. Error: %s"; + private GrpcClient() { + } + public static Channel initGrpcChannel(String host, ChannelCredentials creds) { try { URI uri = new URI(host); diff --git a/client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java b/client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java index 00f87c4..cb0005f 100644 --- a/client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java +++ b/client/src/main/java/info/frostfs/sdk/tools/MessageHelper.java @@ -5,6 +5,9 @@ import com.google.protobuf.MessageOrBuilder; public class MessageHelper { + private MessageHelper() { + } + public static Message getField(MessageOrBuilder messageOrBuilder, String fieldName) { return (Message) messageOrBuilder.getField(messageOrBuilder.getDescriptorForType().findFieldByName(fieldName)); } diff --git a/client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java b/client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java index 9660de5..047d146 100644 --- a/client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java +++ b/client/src/main/java/info/frostfs/sdk/tools/RequestConstructor.java @@ -14,13 +14,20 @@ import static java.util.Objects.isNull; public class RequestConstructor { - public static void addMetaHeader(Message.Builder request) { + private RequestConstructor() { + } + + public static void addDefaultMetaHeader(Message.Builder request) { addMetaHeader(request, null); } public static void addMetaHeader(Message.Builder request, Types.RequestMetaHeader metaHeader) { + if (isNull(request)) { + return; + } + if (isNull(metaHeader) || metaHeader.getSerializedSize() == 0) { - metaHeader = MetaHeaderMapper.toGrpcMessage(MetaHeader.getDefault()); + metaHeader = MetaHeaderMapper.toGrpcMessage(new MetaHeader()); setField(request, META_HEADER_FIELD_NAME, metaHeader); } } @@ -31,6 +38,10 @@ public class RequestConstructor { frostfs.refs.Types.ObjectID oid, Types.ObjectSessionContext.Verb verb, ECDsa key) { + if (isNull(request) || isNull(sessionToken)) { + return; + } + var header = (Types.RequestMetaHeader) getField(request, META_HEADER_FIELD_NAME); if (header.getSessionToken().getSerializedSize() > 0) { return; diff --git a/client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java b/client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java index 315af58..ea7d828 100644 --- a/client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java +++ b/client/src/main/java/info/frostfs/sdk/tools/RequestSigner.java @@ -3,8 +3,8 @@ package info.frostfs.sdk.tools; import com.google.protobuf.ByteString; import com.google.protobuf.Message; import frostfs.session.Types; -import info.frostfs.sdk.jdo.ECDsa; import info.frostfs.sdk.constants.CryptoConst; +import info.frostfs.sdk.jdo.ECDsa; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -24,6 +24,9 @@ public class RequestSigner { public static final String ERROR_UNSUPPORTED_TYPE_TEMPLATE = "Unsupported message type: %s"; public static final int RFC6979_SIGNATURE_SIZE = 64; + private RequestSigner() { + } + public static byte[] signData(ECDsa key, byte[] data) { var hash = new byte[65]; hash[0] = 0x04; diff --git a/client/src/main/java/info/frostfs/sdk/tools/Verifier.java b/client/src/main/java/info/frostfs/sdk/tools/Verifier.java index 8fed127..48a2afc 100644 --- a/client/src/main/java/info/frostfs/sdk/tools/Verifier.java +++ b/client/src/main/java/info/frostfs/sdk/tools/Verifier.java @@ -2,8 +2,8 @@ package info.frostfs.sdk.tools; import com.google.protobuf.Message; import frostfs.session.Types; -import info.frostfs.sdk.mappers.StatusMapper; import info.frostfs.sdk.constants.CryptoConst; +import info.frostfs.sdk.mappers.StatusMapper; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; @@ -28,12 +28,17 @@ public class Verifier { public static final String ERROR_INVALID_RESPONSE = "Invalid response"; public static final int RFC6979_SIG_SIZE = 64; + private Verifier() { + } + public static boolean verifyRFC6979(frostfs.refs.Types.SignatureRFC6979 signature, Message data) { return verifyRFC6979(signature.getKey().toByteArray(), data.toByteArray(), signature.getSign().toByteArray()); } public static boolean verifyRFC6979(byte[] publicKey, byte[] data, byte[] sig) { - if (isNull(publicKey) || isNull(data) || isNull(sig)) return false; + if (isNull(publicKey) || isNull(data) || isNull(sig)) { + return false; + } var rs = decodeSignature(sig); var digest = createSHA256(); @@ -85,9 +90,15 @@ public class Verifier { public static boolean verifyMatryoshkaLevel(Message data, frostfs.session.Types.ResponseMetaHeader meta, frostfs.session.Types.ResponseVerificationHeader verification) { - if (!verifyMessagePart(verification.getMetaSignature(), meta)) return false; + if (!verifyMessagePart(verification.getMetaSignature(), meta)) { + return false; + } + var origin = verification.getOrigin(); - if (!verifyMessagePart(verification.getOriginSignature(), origin)) return false; + if (!verifyMessagePart(verification.getOriginSignature(), origin)) { + return false; + } + if (origin.getSerializedSize() == 0) { return verifyMessagePart(verification.getBodySignature(), data); } @@ -96,7 +107,9 @@ public class Verifier { } public static boolean verifyMessagePart(frostfs.refs.Types.Signature sig, Message data) { - if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) return false; + if (sig.getSerializedSize() == 0 || sig.getKey().isEmpty() || sig.getSign().isEmpty()) { + return false; + } var publicKey = getPublicKeyFromBytes(sig.getKey().toByteArray()); diff --git a/cryptography/pom.xml b/cryptography/pom.xml index 156b0bd..385a810 100644 --- a/cryptography/pom.xml +++ b/cryptography/pom.xml @@ -29,6 +29,11 @@ bcprov-jdk18on 1.78.1 + + org.apache.commons + commons-lang3 + 3.14.0 + \ No newline at end of file diff --git a/cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java b/cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java index ae43afd..915f202 100644 --- a/cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java +++ b/cryptography/src/main/java/info/frostfs/sdk/ArrayHelper.java @@ -1,6 +1,8 @@ package info.frostfs.sdk; public class ArrayHelper { + private ArrayHelper() { + } public static byte[] concat(byte[] startArray, byte[] endArray) { byte[] result = new byte[startArray.length + endArray.length]; diff --git a/cryptography/src/main/java/info/frostfs/sdk/Base58.java b/cryptography/src/main/java/info/frostfs/sdk/Base58.java index f75d705..6321d58 100644 --- a/cryptography/src/main/java/info/frostfs/sdk/Base58.java +++ b/cryptography/src/main/java/info/frostfs/sdk/Base58.java @@ -1,5 +1,7 @@ package info.frostfs.sdk; +import org.apache.commons.lang3.StringUtils; + import java.util.Arrays; import static info.frostfs.sdk.ArrayHelper.concat; @@ -18,8 +20,11 @@ public class Base58 { } } + private Base58() { + } + public static byte[] base58CheckDecode(String input) { - if (isNull(input) || input.isEmpty()) { + if (StringUtils.isEmpty(input)) { throw new IllegalArgumentException("Input value is missing"); } @@ -30,10 +35,9 @@ public class Base58 { byte[] decode = Arrays.copyOfRange(buffer, 0, buffer.length - 4); byte[] checksum = getSha256(getSha256(decode)); - if (!Arrays.equals( - Arrays.copyOfRange(buffer, buffer.length - 4, buffer.length), - Arrays.copyOfRange(checksum, 0, 4) - )) { + var bufferEnd = Arrays.copyOfRange(buffer, buffer.length - 4, buffer.length); + var checksumStart = Arrays.copyOfRange(checksum, 0, 4); + if (!Arrays.equals(bufferEnd, checksumStart)) { throw new IllegalArgumentException(); } @@ -41,6 +45,10 @@ public class Base58 { } public static String base58CheckEncode(byte[] data) { + if (isNull(data)) { + throw new IllegalArgumentException("Input value is missing"); + } + byte[] checksum = getSha256(getSha256(data)); var buffer = concat(data, Arrays.copyOfRange(checksum, 0, 4)); var ret = encode(buffer); diff --git a/cryptography/src/main/java/info/frostfs/sdk/Helper.java b/cryptography/src/main/java/info/frostfs/sdk/Helper.java index a6068e2..58b8c1e 100644 --- a/cryptography/src/main/java/info/frostfs/sdk/Helper.java +++ b/cryptography/src/main/java/info/frostfs/sdk/Helper.java @@ -8,9 +8,17 @@ import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import static java.util.Objects.isNull; + public class Helper { + private Helper() { + } public static byte[] getRIPEMD160(byte[] value) { + if (isNull(value)) { + throw new IllegalArgumentException("Input value is missing"); + } + var hash = new byte[20]; var digest = new RIPEMD160Digest(); digest.update(value, 0, value.length); @@ -27,14 +35,26 @@ public class Helper { } public static byte[] getSha256(byte[] value) { + if (isNull(value)) { + throw new IllegalArgumentException("Input value is missing"); + } + return getSha256Instance().digest(value); } public static ByteString getSha256(Message value) { + if (isNull(value)) { + throw new IllegalArgumentException("Input value is missing"); + } + return ByteString.copyFrom(getSha256(value.toByteArray())); } - public static String getHexString(byte[] array) { - return String.format("%0" + (array.length << 1) + "x", new BigInteger(1, array)); + public static String getHexString(byte[] value) { + if (isNull(value)) { + throw new IllegalArgumentException("Input value is missing"); + } + + return String.format("%0" + (value.length << 1) + "x", new BigInteger(1, value)); } } diff --git a/cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java b/cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java index 4ef8ffe..40affe5 100644 --- a/cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java +++ b/cryptography/src/main/java/info/frostfs/sdk/KeyExtension.java @@ -1,5 +1,6 @@ package info.frostfs.sdk; +import org.apache.commons.lang3.StringUtils; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.sec.SECObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ECParameters; @@ -25,19 +26,23 @@ import java.util.Arrays; import static info.frostfs.sdk.Helper.getRIPEMD160; import static info.frostfs.sdk.Helper.getSha256; +import static java.util.Objects.isNull; import static org.bouncycastle.util.BigIntegers.fromUnsignedByteArray; public class KeyExtension { public static final byte NEO_ADDRESS_VERSION = 0x35; + private static final int DECODE_ADDRESS_LENGTH = 21; private static final int COMPRESSED_PUBLIC_KEY_LENGTH = 33; private static final int UNCOMPRESSED_PUBLIC_KEY_LENGTH = 65; - private static final int CHECK_SIG_DESCRIPTOR = ByteBuffer .wrap(getSha256("System.Crypto.CheckSig".getBytes(StandardCharsets.US_ASCII))) .order(ByteOrder.LITTLE_ENDIAN).getInt(); + private KeyExtension() { + } public static byte[] compress(byte[] publicKey) { + checkInputValue(publicKey); if (publicKey.length != UNCOMPRESSED_PUBLIC_KEY_LENGTH) { throw new IllegalArgumentException( String.format("Compress argument isn't uncompressed public key. Expected length=%s, actual=%s", @@ -51,11 +56,17 @@ public class KeyExtension { } public static byte[] getPrivateKeyFromWIF(String wif) { + if (StringUtils.isEmpty(wif)) { + throw new IllegalArgumentException("Input value is missing"); + } + var data = Base58.base58CheckDecode(wif); return Arrays.copyOfRange(data, 1, data.length - 1); } public static byte[] loadPublicKey(byte[] privateKey) { + checkInputValue(privateKey); + X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); ECDomainParameters domain = new ECDomainParameters( params.getCurve(), params.getG(), params.getN(), params.getH() @@ -66,6 +77,8 @@ public class KeyExtension { } public static PrivateKey loadPrivateKey(byte[] privateKey) { + checkInputValue(privateKey); + X9ECParameters params = SECNamedCurves.getByOID(SECObjectIdentifiers.secp256r1); ECDomainParameters domain = new ECDomainParameters( params.getCurve(), params.getG(), params.getN(), params.getH() @@ -85,6 +98,8 @@ public class KeyExtension { } public static PublicKey getPublicKeyFromBytes(byte[] publicKey) { + checkInputValue(publicKey); + if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { throw new IllegalArgumentException( String.format("Decompress argument isn't compressed public key. Expected length=%s, actual=%s", @@ -116,12 +131,14 @@ public class KeyExtension { } public static byte[] getScriptHash(byte[] publicKey) { - var script = createSignatureRedeemScript(publicKey); + checkInputValue(publicKey); + var script = createSignatureRedeemScript(publicKey); return getRIPEMD160(getSha256(script)); } public static String publicKeyToAddress(byte[] publicKey) { + checkInputValue(publicKey); if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { throw new IllegalArgumentException( String.format("PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s", @@ -133,7 +150,8 @@ public class KeyExtension { } private static String toAddress(byte[] scriptHash, byte version) { - byte[] data = new byte[21]; + checkInputValue(scriptHash); + byte[] data = new byte[DECODE_ADDRESS_LENGTH]; data[0] = version; System.arraycopy(scriptHash, 0, data, 1, scriptHash.length); return Base58.base58CheckEncode(data); @@ -150,6 +168,7 @@ public class KeyExtension { } private static byte[] createSignatureRedeemScript(byte[] publicKey) { + checkInputValue(publicKey); if (publicKey.length != COMPRESSED_PUBLIC_KEY_LENGTH) { throw new IllegalArgumentException( String.format("PublicKey isn't encoded compressed public key. Expected length=%s, actual=%s", @@ -164,4 +183,10 @@ public class KeyExtension { script = ArrayHelper.concat(script, getBytes(CHECK_SIG_DESCRIPTOR)); //Neo_Crypto_CheckSig return script; } + + private static void checkInputValue(byte[] data) { + if (isNull(data)) { + throw new IllegalArgumentException("Input value is missing"); + } + } } diff --git a/models/pom.xml b/models/pom.xml index e9dd655..edc1c26 100644 --- a/models/pom.xml +++ b/models/pom.xml @@ -18,11 +18,6 @@ - - org.apache.commons - commons-lang3 - 3.14.0 - info.frostfs.sdk cryptography @@ -33,6 +28,16 @@ protos 0.1.0 + + org.apache.commons + commons-lang3 + 3.14.0 + + + org.apache.commons + commons-collections4 + 4.4 + \ No newline at end of file diff --git a/models/src/main/java/info/frostfs/sdk/UUIDExtension.java b/models/src/main/java/info/frostfs/sdk/UUIDExtension.java index 7edc01c..730a1a5 100644 --- a/models/src/main/java/info/frostfs/sdk/UUIDExtension.java +++ b/models/src/main/java/info/frostfs/sdk/UUIDExtension.java @@ -3,19 +3,33 @@ package info.frostfs.sdk; import java.nio.ByteBuffer; import java.util.UUID; +import static java.util.Objects.isNull; + public class UUIDExtension { + private static final int UUID_BYTE_ARRAY_LENGTH = 16; + + private UUIDExtension() { + } public static UUID asUuid(byte[] bytes) { + if (isNull(bytes) || bytes.length != UUID_BYTE_ARRAY_LENGTH) { + throw new IllegalArgumentException("Uuid byte array length must be " + UUID_BYTE_ARRAY_LENGTH); + } + ByteBuffer bb = ByteBuffer.wrap(bytes); long firstLong = bb.getLong(); long secondLong = bb.getLong(); return new UUID(firstLong, secondLong); } - public static byte[] asBytes(UUID id) { + public static byte[] asBytes(UUID uuid) { + if (isNull(uuid)) { + throw new IllegalArgumentException("Uuid is not present"); + } + ByteBuffer bb = ByteBuffer.allocate(16); - bb.putLong(id.getMostSignificantBits()); - bb.putLong(id.getLeastSignificantBits()); + bb.putLong(uuid.getMostSignificantBits()); + bb.putLong(uuid.getLeastSignificantBits()); return bb.array(); } } diff --git a/models/src/main/java/info/frostfs/sdk/constants/AppConst.java b/models/src/main/java/info/frostfs/sdk/constants/AppConst.java index ea60f0e..a823466 100644 --- a/models/src/main/java/info/frostfs/sdk/constants/AppConst.java +++ b/models/src/main/java/info/frostfs/sdk/constants/AppConst.java @@ -1,6 +1,11 @@ package info.frostfs.sdk.constants; public class AppConst { + public static final int DEFAULT_MAJOR_VERSION = 2; + public static final int DEFAULT_MINOR_VERSION = 13; public static final int OBJECT_CHUNK_SIZE = 3 * (1 << 20); public static final int SHA256_HASH_LENGTH = 32; + + private AppConst() { + } } diff --git a/models/src/main/java/info/frostfs/sdk/constants/FieldConst.java b/models/src/main/java/info/frostfs/sdk/constants/FieldConst.java index fe85aad..636df86 100644 --- a/models/src/main/java/info/frostfs/sdk/constants/FieldConst.java +++ b/models/src/main/java/info/frostfs/sdk/constants/FieldConst.java @@ -8,4 +8,8 @@ public class FieldConst { public static final String ORIGIN_FIELD_NAME = "origin"; public static final String ORIGIN_SIGNATURE_FIELD_NAME = "origin_signature"; public static final String VERIFY_HEADER_FIELD_NAME = "verify_header"; + public static final String EMPTY_STRING = ""; + + private FieldConst() { + } } diff --git a/models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java b/models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java index c1cc83c..e8b2c72 100644 --- a/models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java +++ b/models/src/main/java/info/frostfs/sdk/constants/XHeaderConst.java @@ -4,4 +4,7 @@ public class XHeaderConst { public static final String RESERVED_XHEADER_PREFIX = "__SYSTEM__"; public static final String XHEADER_NETMAP_EPOCH = RESERVED_XHEADER_PREFIX + "NETMAP_EPOCH"; public static final String XHEADER_NETMAP_LOOKUP_DEPTH = RESERVED_XHEADER_PREFIX + "NETMAP_LOOKUP_DEPTH"; + + private XHeaderConst() { + } } diff --git a/models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java b/models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java index 4e22f46..9d6735e 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java +++ b/models/src/main/java/info/frostfs/sdk/dto/MetaHeader.java @@ -1,18 +1,28 @@ package info.frostfs.sdk.dto; +import static info.frostfs.sdk.constants.AppConst.DEFAULT_MAJOR_VERSION; +import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION; +import static java.util.Objects.isNull; + public class MetaHeader { private Version version; private int epoch; private int ttl; public MetaHeader(Version version, int epoch, int ttl) { + if (isNull(version) || epoch < 0 || ttl <= 0) { + throw new IllegalArgumentException("One of the input attributes is invalid or missing"); + } + this.version = version; this.epoch = epoch; this.ttl = ttl; } - public static MetaHeader getDefault() { - return new MetaHeader(new Version(2, 13), 0, 2); + public MetaHeader() { + this.version = new Version(DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION); + this.epoch = 0; + this.ttl = 2; } public Version getVersion() { @@ -20,6 +30,10 @@ public class MetaHeader { } public void setVersion(Version version) { + if (isNull(version)) { + throw new IllegalArgumentException("Version is missing."); + } + this.version = version; } @@ -28,6 +42,10 @@ public class MetaHeader { } public void setEpoch(int epoch) { + if (epoch < 0) { + throw new IllegalArgumentException("The epoch must be greater than or equal to zero."); + } + this.epoch = epoch; } @@ -36,6 +54,10 @@ public class MetaHeader { } public void setTtl(int ttl) { + if (ttl <= 0) { + throw new IllegalArgumentException("The ttl must be greater than zero."); + } + this.ttl = ttl; } } diff --git a/models/src/main/java/info/frostfs/sdk/dto/OwnerId.java b/models/src/main/java/info/frostfs/sdk/dto/OwnerId.java index d4a173b..1603e21 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/OwnerId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/OwnerId.java @@ -3,6 +3,7 @@ package info.frostfs.sdk.dto; import info.frostfs.sdk.Base58; import static info.frostfs.sdk.KeyExtension.publicKeyToAddress; +import static java.util.Objects.isNull; public class OwnerId { private final String value; @@ -11,8 +12,12 @@ public class OwnerId { this.value = value; } - public static OwnerId fromKey(byte[] publicKey) { - return new OwnerId(publicKeyToAddress(publicKey)); + public OwnerId(byte[] publicKey) { + if (isNull(publicKey) || publicKey.length == 0) { + throw new IllegalArgumentException("PublicKey is invalid"); + } + + this.value = publicKeyToAddress(publicKey); } public String getValue() { diff --git a/models/src/main/java/info/frostfs/sdk/dto/Split.java b/models/src/main/java/info/frostfs/sdk/dto/Split.java index 2b5726a..642ed58 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/Split.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Split.java @@ -6,9 +6,11 @@ import info.frostfs.sdk.dto.object.ObjectId; import java.util.ArrayList; import java.util.List; +import static java.util.Objects.isNull; + public class Split { private final List children; - private SplitId splitId; + private final SplitId splitId; private ObjectId parent; private ObjectId previous; private Signature parentSignature; @@ -19,6 +21,10 @@ public class Split { } public Split(SplitId splitId) { + if (isNull(splitId)) { + throw new IllegalArgumentException("SplitId is not present"); + } + this.splitId = splitId; this.children = new ArrayList<>(); } @@ -27,10 +33,6 @@ public class Split { return splitId; } - private void setSplitId(SplitId splitId) { - this.splitId = splitId; - } - public ObjectId getParent() { return parent; } diff --git a/models/src/main/java/info/frostfs/sdk/dto/SplitId.java b/models/src/main/java/info/frostfs/sdk/dto/SplitId.java index 6ecc031..3ced690 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/SplitId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/SplitId.java @@ -9,30 +9,22 @@ import static java.util.Objects.isNull; public class SplitId { private final UUID id; - public SplitId(UUID uuid) { - this.id = uuid; - } - public SplitId() { this.id = UUID.randomUUID(); } - private SplitId(byte[] binary) { + public SplitId(UUID uuid) { + this.id = uuid; + } + + public SplitId(byte[] binary) { this.id = asUuid(binary); } - private SplitId(String str) { + public SplitId(String str) { this.id = UUID.fromString(str); } - public static SplitId createFromBinary(byte[] binaryData) { - return new SplitId(binaryData); - } - - public static SplitId createFromString(String stringData) { - return new SplitId(stringData); - } - @Override public String toString() { return id.toString(); diff --git a/models/src/main/java/info/frostfs/sdk/dto/Status.java b/models/src/main/java/info/frostfs/sdk/dto/Status.java index dd242a3..e1075b5 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/Status.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Status.java @@ -2,6 +2,7 @@ package info.frostfs.sdk.dto; import info.frostfs.sdk.enums.StatusCode; +import static info.frostfs.sdk.constants.FieldConst.EMPTY_STRING; import static java.util.Objects.isNull; public class Status { @@ -10,12 +11,12 @@ public class Status { public Status(StatusCode code, String message) { this.code = code; - this.message = isNull(message) ? "" : message; + this.message = isNull(message) ? EMPTY_STRING : message; } public Status(StatusCode code) { this.code = code; - this.message = ""; + this.message = EMPTY_STRING; } public StatusCode getCode() { diff --git a/models/src/main/java/info/frostfs/sdk/dto/Version.java b/models/src/main/java/info/frostfs/sdk/dto/Version.java index 563d8b6..0222922 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/Version.java +++ b/models/src/main/java/info/frostfs/sdk/dto/Version.java @@ -1,36 +1,41 @@ package info.frostfs.sdk.dto; +import static info.frostfs.sdk.constants.AppConst.DEFAULT_MAJOR_VERSION; +import static info.frostfs.sdk.constants.AppConst.DEFAULT_MINOR_VERSION; +import static java.util.Objects.isNull; + public class Version { - private int major; - private int minor; + private final int major; + private final int minor; public Version(int major, int minor) { this.major = major; this.minor = minor; } + public Version() { + this.major = DEFAULT_MAJOR_VERSION; + this.minor = DEFAULT_MINOR_VERSION; + } + public int getMajor() { return major; } - public void setMajor(int major) { - this.major = major; - } - public int getMinor() { return minor; } - public void setMinor(int minor) { - this.minor = minor; - } - @Override public String toString() { return "v" + major + "." + minor; } public boolean isSupported(Version version) { + if (isNull(version)) { + return false; + } + return major == version.getMajor(); } } diff --git a/models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java b/models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java index b24a069..1cd39b2 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/container/ContainerId.java @@ -2,29 +2,33 @@ package info.frostfs.sdk.dto.container; import info.frostfs.sdk.Base58; import info.frostfs.sdk.constants.AppConst; +import org.apache.commons.lang3.StringUtils; + +import static java.util.Objects.isNull; public class ContainerId { - private String value; + private final String value; public ContainerId(String value) { + if (StringUtils.isEmpty(value)) { + throw new IllegalArgumentException("ContainerId value is missing"); + } + this.value = value; } - public static ContainerId fromHash(byte[] hash) { - if (hash.length != AppConst.SHA256_HASH_LENGTH) { - throw new IllegalArgumentException("ContainerID must be a sha256 hash."); + public ContainerId(byte[] hash) { + if (isNull(hash) || hash.length != AppConst.SHA256_HASH_LENGTH) { + throw new IllegalArgumentException("ContainerId must be a sha256 hash."); } - return new ContainerId(Base58.encode(hash)); + + this.value = Base58.encode(hash); } public String getValue() { return value; } - public void setValue(String value) { - this.value = value; - } - @Override public String toString() { return value; diff --git a/models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java b/models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java index 235d288..74e3886 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java +++ b/models/src/main/java/info/frostfs/sdk/dto/netmap/Replica.java @@ -1,34 +1,36 @@ package info.frostfs.sdk.dto.netmap; -import static java.util.Objects.isNull; +import org.apache.commons.lang3.StringUtils; + +import static info.frostfs.sdk.constants.FieldConst.EMPTY_STRING; public class Replica { - private int count; - private String selector; + private final int count; + private final String selector; public Replica(int count, String selector) { + if (count <= 0) { + throw new IllegalArgumentException("Replica count must be positive"); + } + this.count = count; - this.selector = isNull(selector) ? "" : selector; + this.selector = StringUtils.isEmpty(selector) ? EMPTY_STRING : selector; } public Replica(int count) { + if (count <= 0) { + throw new IllegalArgumentException("Replica count must be positive"); + } + this.count = count; - this.selector = ""; + this.selector = EMPTY_STRING; } public int getCount() { return count; } - public void setCount(int count) { - this.count = count; - } - public String getSelector() { return selector; } - - public void setSelector(String selector) { - this.selector = selector; - } } diff --git a/models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java b/models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java index 4cab2ed..915b745 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/LargeObject.java @@ -5,6 +5,7 @@ import info.frostfs.sdk.dto.container.ContainerId; import java.security.MessageDigest; import static info.frostfs.sdk.Helper.getSha256Instance; +import static java.util.Objects.isNull; public class LargeObject extends ObjectFrostFS { private final MessageDigest payloadHash; @@ -15,6 +16,10 @@ public class LargeObject extends ObjectFrostFS { } public void appendBlock(byte[] bytes, int count) { + if (count == 0 || isNull(bytes) || bytes.length == 0) { + return; + } + this.getHeader().increasePayloadLength(count); this.payloadHash.update(bytes, 0, count); } diff --git a/models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java b/models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java index b641888..d7a7091 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/LinkObject.java @@ -3,6 +3,7 @@ package info.frostfs.sdk.dto.object; import info.frostfs.sdk.dto.Split; import info.frostfs.sdk.dto.SplitId; import info.frostfs.sdk.dto.container.ContainerId; +import org.apache.commons.collections4.CollectionUtils; import java.util.List; @@ -16,6 +17,10 @@ public class LinkObject extends ObjectFrostFS { } public void addChildren(List objectIds) { + if (CollectionUtils.isEmpty(objectIds)) { + return; + } + this.getHeader().getSplit().getChildren().addAll(objectIds); } } diff --git a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java index 0c2554b..60a3ede 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectAttribute.java @@ -1,10 +1,16 @@ package info.frostfs.sdk.dto.object; +import org.apache.commons.lang3.StringUtils; + public class ObjectAttribute { - private String key; - private String value; + private final String key; + private final String value; public ObjectAttribute(String key, String value) { + if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + throw new IllegalArgumentException("One of the input attributes is missing"); + } + this.key = key; this.value = value; } @@ -13,15 +19,7 @@ public class ObjectAttribute { return key; } - public void setKey(String key) { - this.key = key; - } - public String getValue() { return value; } - - public void setValue(String value) { - this.value = value; - } } diff --git a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java index 5001161..af5f463 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectFrostFS.java @@ -10,34 +10,34 @@ import java.util.List; import static java.util.Objects.isNull; public class ObjectFrostFS { - private ObjectHeader header; + private final ObjectHeader header; private ObjectId objectId; private byte[] payload; public ObjectFrostFS(ObjectHeader header, ObjectId objectId, byte[] payload) { + if (isNull(header)) { + throw new IllegalArgumentException("Object header is missing"); + } + this.header = header; this.objectId = objectId; this.payload = payload; } - public ObjectFrostFS(ContainerId container, byte[] payload) { + public ObjectFrostFS(ContainerId containerId, byte[] payload) { this.payload = payload; - this.header = new ObjectHeader(container, new ArrayList<>()); + this.header = new ObjectHeader(containerId, new ArrayList<>()); } - public ObjectFrostFS(ContainerId container, byte[] payload, ObjectType objectType) { + public ObjectFrostFS(ContainerId containerId, byte[] payload, ObjectType objectType) { this.payload = payload; - this.header = new ObjectHeader(container, objectType, new ArrayList<>()); + this.header = new ObjectHeader(containerId, objectType, new ArrayList<>()); } public ObjectHeader getHeader() { return header; } - public void setHeader(ObjectHeader header) { - this.header = header; - } - public ObjectId getObjectId() { return objectId; } diff --git a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java index 147ec4e..208b936 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectHeader.java @@ -8,11 +8,13 @@ import info.frostfs.sdk.enums.ObjectType; import java.util.List; +import static java.util.Objects.isNull; + public class ObjectHeader { + private final ContainerId containerId; + private final ObjectType objectType; private List attributes; - private ContainerId containerId; private long size; - private ObjectType objectType; private Version version; private OwnerId ownerId; private long payloadLength; @@ -21,6 +23,10 @@ public class ObjectHeader { public ObjectHeader(ContainerId containerId, ObjectType objectType, List attributes, long size, Version version) { + if (isNull(containerId) || isNull(objectType)) { + throw new IllegalArgumentException("ContainerId or objectType is not present"); + } + this.attributes = attributes; this.containerId = containerId; this.size = size; @@ -28,13 +34,21 @@ public class ObjectHeader { this.version = version; } - public ObjectHeader(ContainerId containerId, ObjectType type, List attributes) { + public ObjectHeader(ContainerId containerId, ObjectType objectType, List attributes) { + if (isNull(containerId) || isNull(objectType)) { + throw new IllegalArgumentException("ContainerId or objectType is not present"); + } + this.attributes = attributes; this.containerId = containerId; - this.objectType = type; + this.objectType = objectType; } public ObjectHeader(ContainerId containerId, List attributes) { + if (isNull(containerId)) { + throw new IllegalArgumentException("ContainerId is not present"); + } + this.attributes = attributes; this.containerId = containerId; this.objectType = ObjectType.REGULAR; @@ -73,6 +87,10 @@ public class ObjectHeader { } public void setSplit(Split split) { + if (isNull(split)) { + throw new IllegalArgumentException("Split is not present"); + } + this.split = split; } @@ -88,10 +106,6 @@ public class ObjectHeader { return containerId; } - public void setContainerId(ContainerId containerId) { - this.containerId = containerId; - } - public long getSize() { return size; } @@ -104,10 +118,6 @@ public class ObjectHeader { return objectType; } - public void setObjectType(ObjectType objectType) { - this.objectType = objectType; - } - public Version getVersion() { return version; } diff --git a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java index 3c9965a..7c6bffb 100644 --- a/models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java +++ b/models/src/main/java/info/frostfs/sdk/dto/object/ObjectId.java @@ -2,19 +2,27 @@ package info.frostfs.sdk.dto.object; import info.frostfs.sdk.Base58; import info.frostfs.sdk.constants.AppConst; +import org.apache.commons.lang3.StringUtils; + +import static java.util.Objects.isNull; public class ObjectId { private final String value; - public ObjectId(String id) { - this.value = id; + public ObjectId(String value) { + if (StringUtils.isEmpty(value)) { + throw new IllegalArgumentException("ObjectId value is missing"); + } + + this.value = value; } - public static ObjectId fromHash(byte[] hash) { - if (hash.length != AppConst.SHA256_HASH_LENGTH) { + public ObjectId(byte[] hash) { + if (isNull(hash) || hash.length != AppConst.SHA256_HASH_LENGTH) { throw new IllegalArgumentException("ObjectId must be a sha256 hash."); } - return new ObjectId(Base58.encode(hash)); + + this.value = Base58.encode(hash); } public String getValue() { diff --git a/models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java index 736871c..0b90453 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/MetaHeaderMapper.java @@ -3,9 +3,18 @@ package info.frostfs.sdk.mappers; import frostfs.session.Types; import info.frostfs.sdk.dto.MetaHeader; +import static java.util.Objects.isNull; + public class MetaHeaderMapper { + private MetaHeaderMapper() { + } + public static Types.RequestMetaHeader toGrpcMessage(MetaHeader metaHeader) { + if (isNull(metaHeader)) { + return null; + } + return Types.RequestMetaHeader.newBuilder() .setVersion(VersionMapper.toGrpcMessage(metaHeader.getVersion())) .setEpoch(metaHeader.getEpoch()) diff --git a/models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java index 69cb6e8..a0a6b64 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/OwnerIdMapper.java @@ -4,9 +4,18 @@ import com.google.protobuf.ByteString; import frostfs.refs.Types; import info.frostfs.sdk.dto.OwnerId; +import static java.util.Objects.isNull; + public class OwnerIdMapper { + private OwnerIdMapper() { + } + public static Types.OwnerID toGrpcMessage(OwnerId ownerId) { + if (isNull(ownerId)) { + return null; + } + return Types.OwnerID.newBuilder() .setValue(ByteString.copyFrom(ownerId.toHash())) .build(); diff --git a/models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java index c13a61e..45331cf 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/SessionMapper.java @@ -6,9 +6,18 @@ import frostfs.session.Types; import java.io.IOException; +import static java.util.Objects.isNull; + public class SessionMapper { + private SessionMapper() { + } + public static byte[] serialize(Types.SessionToken token) { + if (isNull(token)) { + throw new IllegalArgumentException("Token is not present"); + } + try { byte[] bytes = new byte[token.getSerializedSize()]; CodedOutputStream stream = CodedOutputStream.newInstance(bytes); @@ -20,6 +29,10 @@ public class SessionMapper { } public static Types.SessionToken deserializeSessionToken(byte[] bytes) { + if (isNull(bytes) || bytes.length == 0) { + throw new IllegalArgumentException("Token is not present"); + } + try { return Types.SessionToken.newBuilder().mergeFrom(bytes).build(); } catch (InvalidProtocolBufferException exp) { diff --git a/models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java index 1a62bfd..5f14f4a 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/SignatureMapper.java @@ -8,7 +8,14 @@ import static java.util.Objects.isNull; public class SignatureMapper { - public static Types.Signature ToGrpcMessage(Signature signature) { + private SignatureMapper() { + } + + public static Types.Signature toGrpcMessage(Signature signature) { + if (isNull(signature)) { + return null; + } + var scheme = Types.SignatureScheme.forNumber(signature.getScheme().value); if (isNull(scheme)) { throw new IllegalArgumentException( diff --git a/models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java index 7c6f3b1..2bfa717 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/StatusMapper.java @@ -8,8 +8,13 @@ import static java.util.Objects.isNull; public class StatusMapper { + private StatusMapper() { + } + public static Status toModel(Types.Status status) { - if (isNull(status)) return new Status(StatusCode.SUCCESS); + if (isNull(status)) { + return new Status(StatusCode.SUCCESS); + } var statusCode = StatusCode.get(status.getCode()); if (isNull(statusCode)) { diff --git a/models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java index 7888a67..13e7a0d 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/VersionMapper.java @@ -3,9 +3,18 @@ package info.frostfs.sdk.mappers; import frostfs.refs.Types; import info.frostfs.sdk.dto.Version; +import static java.util.Objects.isNull; + public class VersionMapper { + private VersionMapper() { + } + public static Types.Version toGrpcMessage(Version version) { + if (isNull(version)) { + return null; + } + return Types.Version.newBuilder() .setMajor(version.getMajor()) .setMinor(version.getMinor()) @@ -13,6 +22,10 @@ public class VersionMapper { } public static Version toModel(Types.Version version) { + if (isNull(version)) { + return null; + } + return new Version(version.getMajor(), version.getMinor()); } } diff --git a/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java index cbe7237..26e941c 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerIdMapper.java @@ -4,9 +4,18 @@ import com.google.protobuf.ByteString; import frostfs.refs.Types; import info.frostfs.sdk.dto.container.ContainerId; +import static java.util.Objects.isNull; + public class ContainerIdMapper { + private ContainerIdMapper() { + } + public static Types.ContainerID toGrpcMessage(ContainerId containerId) { + if (isNull(containerId)) { + return null; + } + return Types.ContainerID.newBuilder() .setValue(ByteString.copyFrom(containerId.toHash())) .build(); diff --git a/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java index ff36486..9aa1741 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/container/ContainerMapper.java @@ -13,7 +13,14 @@ import static java.util.Objects.isNull; public class ContainerMapper { + private ContainerMapper() { + } + public static Types.Container toGrpcMessage(Container container) { + if (isNull(container)) { + return null; + } + return Types.Container.newBuilder() .setBasicAcl(container.getBasicAcl().value) .setPlacementPolicy(PlacementPolicyMapper.toGrpcMessage(container.getPlacementPolicy())) @@ -22,6 +29,10 @@ public class ContainerMapper { } public static Container toModel(Types.Container containerGrpc) { + if (isNull(containerGrpc)) { + return null; + } + var basicAcl = BasicAcl.get(containerGrpc.getBasicAcl()); if (isNull(basicAcl)) { throw new IllegalArgumentException( diff --git a/models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java index a396f58..f911e74 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NetmapSnapshotMapper.java @@ -5,9 +5,18 @@ import info.frostfs.sdk.dto.netmap.NetmapSnapshot; import java.util.stream.Collectors; +import static java.util.Objects.isNull; + public class NetmapSnapshotMapper { + private NetmapSnapshotMapper() { + } + public static NetmapSnapshot toModel(Service.NetmapSnapshotResponse netmap) { + if (isNull(netmap)) { + return null; + } + return new NetmapSnapshot( netmap.getBody().getNetmap().getEpoch(), netmap.getBody().getNetmap().getNodesList().stream() diff --git a/models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java index c2bd9b7..d91dcd1 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/NodeInfoMapper.java @@ -13,11 +13,22 @@ import static java.util.Objects.isNull; public class NodeInfoMapper { + private NodeInfoMapper() { + } + public static NodeInfo toModel(Service.LocalNodeInfoResponse.Body nodeInfo) { + if (isNull(nodeInfo)) { + return null; + } + return toModel(nodeInfo.getNodeInfo(), nodeInfo.getVersion()); } public static NodeInfo toModel(frostfs.netmap.Types.NodeInfo nodeInfo, Types.Version version) { + if (isNull(nodeInfo)) { + return null; + } + NodeState nodeState = NodeState.get(nodeInfo.getState().getNumber()); if (isNull(nodeState)) { throw new IllegalArgumentException( diff --git a/models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java index 4a6675c..f5bdaef 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/PlacementPolicyMapper.java @@ -4,9 +4,18 @@ import frostfs.netmap.Types; import info.frostfs.sdk.dto.netmap.PlacementPolicy; import info.frostfs.sdk.dto.netmap.Replica; +import static java.util.Objects.isNull; + public class PlacementPolicyMapper { + private PlacementPolicyMapper() { + } + public static Types.PlacementPolicy toGrpcMessage(PlacementPolicy placementPolicy) { + if (isNull(placementPolicy)) { + return null; + } + var pp = Types.PlacementPolicy.newBuilder() .setUnique(placementPolicy.isUnique()); @@ -18,6 +27,10 @@ public class PlacementPolicyMapper { } public static PlacementPolicy toModel(Types.PlacementPolicy placementPolicy) { + if (isNull(placementPolicy)) { + return null; + } + return new PlacementPolicy( placementPolicy.getUnique(), placementPolicy.getReplicasList().stream().map(ReplicaMapper::toModel).toArray(Replica[]::new) diff --git a/models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java index eef3e70..e25ec21 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/netmap/ReplicaMapper.java @@ -3,9 +3,18 @@ package info.frostfs.sdk.mappers.netmap; import frostfs.netmap.Types; import info.frostfs.sdk.dto.netmap.Replica; +import static java.util.Objects.isNull; + public class ReplicaMapper { + private ReplicaMapper() { + } + public static Types.Replica toGrpcMessage(Replica replica) { + if (isNull(replica)) { + return null; + } + return Types.Replica.newBuilder() .setCount(replica.getCount()) .setSelector(replica.getSelector()) @@ -13,6 +22,10 @@ public class ReplicaMapper { } public static Replica toModel(Types.Replica replica) { + if (isNull(replica)) { + return null; + } + return new Replica(replica.getCount(), replica.getSelector()); } } diff --git a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java index 62c67cb..17c3e94 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectAttributeMapper.java @@ -3,9 +3,18 @@ package info.frostfs.sdk.mappers.object; import frostfs.object.Types; import info.frostfs.sdk.dto.object.ObjectAttribute; +import static java.util.Objects.isNull; + public class ObjectAttributeMapper { + private ObjectAttributeMapper() { + } + public static Types.Header.Attribute toGrpcMessage(ObjectAttribute attribute) { + if (isNull(attribute)) { + return null; + } + return Types.Header.Attribute.newBuilder() .setKey(attribute.getKey()) .setValue(attribute.getValue()) @@ -13,6 +22,10 @@ public class ObjectAttributeMapper { } public static ObjectAttribute toModel(Types.Header.Attribute attribute) { + if (isNull(attribute)) { + return null; + } + return new ObjectAttribute(attribute.getKey(), attribute.getValue()); } } diff --git a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java index 8bbe23e..b1c121d 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFilterMapper.java @@ -8,7 +8,14 @@ import static java.util.Objects.isNull; public class ObjectFilterMapper { + private ObjectFilterMapper() { + } + public static Service.SearchRequest.Body.Filter toGrpcMessage(ObjectFilter filter) { + if (isNull(filter)) { + return null; + } + var objectMatchType = Types.MatchType.forNumber(filter.getMatchType().value); if (isNull(objectMatchType)) { throw new IllegalArgumentException( diff --git a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java index 28b8332..aa5f698 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectFrostFSMapper.java @@ -4,13 +4,22 @@ import frostfs.object.Types; import info.frostfs.sdk.dto.object.ObjectFrostFS; import info.frostfs.sdk.dto.object.ObjectId; +import static java.util.Objects.isNull; + public class ObjectFrostFSMapper { - public static ObjectFrostFS toModel(Types.Object obj) { + private ObjectFrostFSMapper() { + } + + public static ObjectFrostFS toModel(Types.Object object) { + if (isNull(object)) { + return null; + } + return new ObjectFrostFS( - ObjectHeaderMapper.toModel(obj.getHeader()), - ObjectId.fromHash(obj.getObjectId().getValue().toByteArray()), - obj.getPayload().toByteArray() + ObjectHeaderMapper.toModel(object.getHeader()), + new ObjectId(object.getObjectId().getValue().toByteArray()), + object.getPayload().toByteArray() ); } } diff --git a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java index 6b8bc91..fc5b4cc 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectHeaderMapper.java @@ -14,7 +14,14 @@ import static java.util.Objects.isNull; public class ObjectHeaderMapper { + private ObjectHeaderMapper() { + } + public static Types.Header toGrpcMessage(ObjectHeader header) { + if (isNull(header)) { + return null; + } + var objectType = Types.ObjectType.forNumber(header.getObjectType().value); if (isNull(objectType)) { throw new IllegalArgumentException( @@ -34,6 +41,10 @@ public class ObjectHeaderMapper { } public static ObjectHeader toModel(Types.Header header) { + if (isNull(header)) { + return null; + } + var objectType = ObjectType.get(header.getObjectTypeValue()); if (isNull(objectType)) { throw new IllegalArgumentException( @@ -42,7 +53,7 @@ public class ObjectHeaderMapper { } return new ObjectHeader( - ContainerId.fromHash(header.getContainerId().getValue().toByteArray()), + new ContainerId(header.getContainerId().getValue().toByteArray()), objectType, header.getAttributesList().stream().map(ObjectAttributeMapper::toModel).collect(Collectors.toList()), header.getPayloadLength(), diff --git a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java index 62ca7c5..af51095 100644 --- a/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java +++ b/models/src/main/java/info/frostfs/sdk/mappers/object/ObjectIdMapper.java @@ -4,15 +4,24 @@ import com.google.protobuf.ByteString; import frostfs.refs.Types; import info.frostfs.sdk.dto.object.ObjectId; +import static java.util.Objects.isNull; + public class ObjectIdMapper { + private ObjectIdMapper() { + } + public static Types.ObjectID toGrpcMessage(ObjectId objectId) { + if (isNull(objectId)) { + return null; + } + return Types.ObjectID.newBuilder() .setValue(ByteString.copyFrom(objectId.toHash())) .build(); } public static ObjectId toModel(Types.ObjectID objectId) { - return ObjectId.fromHash(objectId.getValue().toByteArray()); + return new ObjectId(objectId.getValue().toByteArray()); } } -- 2.45.2 From 75188933889846e7dd3196754bfe03e27576536a Mon Sep 17 00:00:00 2001 From: Bruk Ori Date: Thu, 25 Jul 2024 12:24:05 +0300 Subject: [PATCH 7/7] [#1] update README.md Signed-off-by: Ori Bruk --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bd5444b..fe3c04f 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ neo-go wallet export -w -d ## Example usage -### Container +### Container operations ```java import info.frostfs.sdk.dto.container.Container; @@ -50,7 +50,7 @@ public class ContainerExample { } ``` -### Object +### Object operations ```java import info.frostfs.sdk.enums.ObjectType; @@ -58,6 +58,7 @@ import info.frostfs.sdk.dto.container.ContainerId; import info.frostfs.sdk.dto.object.ObjectAttribute; import info.frostfs.sdk.dto.object.ObjectFilter; import info.frostfs.sdk.dto.object.ObjectHeader; +import info.frostfs.sdk.dto.object.ObjectId; import info.frostfs.sdk.jdo.PutObjectParameters; import info.frostfs.sdk.FrostFSClient; @@ -71,7 +72,7 @@ public class ObjectExample { FrostFSClient frostFSClient = new FrostFSClient(clientSettings); // Put object - info.frostfs.sdk.dto.object.ObjectId objectId; + ObjectId objectId; try (FileInputStream fis = new FileInputStream("cat.jpg")) { var cat = new ObjectHeader( containerId, ObjectType.REGULAR, new ObjectAttribute[]{new ObjectAttribute("Filename", "cat.jpg")} -- 2.45.2