private static ResourceDescriptor fromUrl(String url,
                                              @Nullable String expectedBucket,
                                              @Nullable String expectedLocation,
                                              @Nullable EncryptionService encryptionService) {
        String[] parts = url.split(ResourceDescriptor.PATH_SEPARATOR);

        if (parts.length < 2) {
            throw new IllegalArgumentException("Url has less than two segments: " + url);
        }

        if (url.startsWith(ResourceDescriptor.PATH_SEPARATOR)) {
            throw new IllegalArgumentException("Url must not start with " + ResourceDescriptor.PATH_SEPARATOR + ", but: " + url);
        }

        if (parts.length == 2 && !url.endsWith(ResourceDescriptor.PATH_SEPARATOR)) {
            throw new IllegalArgumentException("Url must start with resource/bucket/, but: " + url);
        }

        ResourceTypes resourceType = ResourceTypes.of(UrlUtil.decodePath(parts[0]));
        String bucket = UrlUtil.decodePath(parts[1]);
        String location = null;

        if (bucket.equals(ResourceDescriptor.PUBLIC_BUCKET)) {
            location = ResourceDescriptor.PUBLIC_LOCATION;
        } else if (expectedBucket != null) {
            location = expectedLocation;
        } else if (encryptionService != null) {
            location = encryptionService.decrypt(bucket);
        }

        if (expectedBucket != null && !expectedBucket.equals(bucket)) {
            throw new IllegalArgumentException("Url bucket does not match: " + url);
        }

        if (location == null) {
            throw new IllegalArgumentException("Url has invalid bucket: " + url);
        }

        String relativePath = url.substring(parts[0].length() + parts[1].length() + 2);
        return fromEncoded(resourceType, bucket, location, relativePath);
    }
@param url - resource url, e.g. files/bucket/folder/file.txt
@param expectedBucket - matched against the url's bucket if provided.
@param expectedLocation - used as bucket location if provided together with expected bucket.
@param encryptionService - used to decrypt bucket location if provided.
server/src/main/java/com/epam/aidial/core/server/util/ResourceDescriptorFactory.java