<commit_before>package org.yamcs.web.rest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.protobuf.Rest.BucketInfo;
import org.yamcs.protobuf.Rest.CreateBucketRequest;
import org.yamcs.protobuf.Rest.ListBucketsResponse;
import org.yamcs.protobuf.Rest.ListObjectsResponse;
import org.yamcs.protobuf.Rest.ObjectInfo;
import org.yamcs.security.SystemPrivilege;
import org.yamcs.security.User;
import org.yamcs.utils.TimeEncoding;
import org.yamcs.web.BadRequestException;
import org.yamcs.web.HttpException;
import org.yamcs.web.InternalServerErrorException;
import org.yamcs.web.NotFoundException;
import org.yamcs.web.ServiceUnavailableException;
import org.yamcs.yarch.Bucket;
import org.yamcs.yarch.BucketDatabase;
import org.yamcs.yarch.YarchDatabase;
import org.yamcs.yarch.YarchDatabaseInstance;
import org.yamcs.yarch.YarchException;
import org.yamcs.yarch.rocksdb.protobuf.Tablespace.BucketProperties;
import org.yamcs.yarch.rocksdb.protobuf.Tablespace.ObjectProperties;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;

/**
 * Implements object storage
 */
public class BucketRestHandler extends RestHandler {
    private static final Logger log = LoggerFactory.getLogger(BucketRestHandler.class);
    static String BUCKET_NAME_PARAM = "bucketName";
    static String OBJECT_NAME_PARAM = "objectName";

    // max body size used for upload object (this includes both data and metadata).
    static final int MAX_BODY_SIZE = 5 * 1024 * 1024;
    static final int MAX_METADATA_SIZE = 16 * 1024;

    static final Pattern BUCKET_NAME_REGEXP = Pattern.compile("\\w+");
    static final Pattern OBJ_NAME_REGEXP = Pattern.compile("[\\w\\-\\./]+");

    @Route(path = "/api/buckets/:instance", method = "GET")
    public void listBuckets(RestRequest req) throws HttpException {
        checkSystemPrivilege(req, SystemPrivilege.ManageAnyBucket);

        BucketDatabase bdb = getBucketDb(req);
        try {
            List<BucketProperties> l = bdb.listBuckets();
            ListBucketsResponse.Builder lbr = ListBucketsResponse.newBuilder();
            for (BucketProperties bp : l) {
                lbr.addBucket(BucketInfo.newBuilder().setName(bp.getName()).setSize(bp.getSize())<commit_msg>Allow spaces in object names<commit_after>package org.yamcs.web.rest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.protobuf.Rest.BucketInfo;
import org.yamcs.protobuf.Rest.CreateBucketRequest;
import org.yamcs.protobuf.Rest.ListBucketsResponse;
import org.yamcs.protobuf.Rest.ListObjectsResponse;
import org.yamcs.protobuf.Rest.ObjectInfo;
import org.yamcs.security.SystemPrivilege;
import org.yamcs.security.User;
import org.yamcs.utils.TimeEncoding;
import org.yamcs.web.BadRequestException;
import org.yamcs.web.HttpException;
import org.yamcs.web.InternalServerErrorException;
import org.yamcs.web.NotFoundException;
import org.yamcs.web.ServiceUnavailableException;
import org.yamcs.yarch.Bucket;
import org.yamcs.yarch.BucketDatabase;
import org.yamcs.yarch.YarchDatabase;
import org.yamcs.yarch.YarchDatabaseInstance;
import org.yamcs.yarch.YarchException;
import org.yamcs.yarch.rocksdb.protobuf.Tablespace.BucketProperties;
import org.yamcs.yarch.rocksdb.protobuf.Tablespace.ObjectProperties;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;

/**
 * Implements object storage
 */
public class BucketRestHandler extends RestHandler {
    private static final Logger log = LoggerFactory.getLogger(BucketRestHandler.class);
    static String BUCKET_NAME_PARAM = "bucketName";
    static String OBJECT_NAME_PARAM = "objectName";

    // max body size used for upload object (this includes both data and metadata).
    static final int MAX_BODY_SIZE = 5 * 1024 * 1024;
    static final int MAX_METADATA_SIZE = 16 * 1024;

    static final Pattern BUCKET_NAME_REGEXP = Pattern.compile("\\w+");
    static final Pattern OBJ_NAME_REGEXP = Pattern.compile("[ \\w\\s\\-\\./]+");

    @Route(path = "/api/buckets/:instance", method = "GET")
    public void listBuckets(RestRequest req) throws HttpException {
        checkSystemPrivilege(req, SystemPrivilege.ManageAnyBucket);

        BucketDatabase bdb = getBucketDb(req);
        try {
            List<BucketProperties> l = bdb.listBuckets();
            ListBucketsResponse.Builder lbr = ListBucketsResponse.newBuilder();
            for (BucketProperties bp : l) {
                lbr.addBucket(BucketInfo.newBuilder().setName(bp.getName()).setSize(bp.getSize())
{'fraction_non_alphanumeric': 0.10623047233964344, 'fraction_numerical': 0.006248851314096674, 'mean_word_length': 4.801705756929637, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3750917', 'n_tokens_mistral': 1755, 'n_tokens_neox': 1704, 'n_words': 318}