AbstractVendedCredentialsProvider.java

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package org.apache.doris.datasource.credentials;

import org.apache.doris.datasource.property.metastore.MetastoreProperties;
import org.apache.doris.datasource.property.storage.StorageProperties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public abstract class AbstractVendedCredentialsProvider {

    private static final Logger LOG = LogManager.getLogger(AbstractVendedCredentialsProvider.class);

    /**
     * Get temporary storage attribute maps containing vendor credentials
     * This is the core method: format conversion via StorageProperties.createAll()
     *
     * @param metastoreProperties Metastore properties
     * @param tableObject Table object (generics, support different data sources)
     * @return Storage attribute mapping containing temporary credentials
     */
    public final <T> Map<StorageProperties.Type, StorageProperties> getStoragePropertiesMapWithVendedCredentials(
            MetastoreProperties metastoreProperties,
            T tableObject) {

        try {
            if (!isVendedCredentialsEnabled(metastoreProperties) || tableObject == null) {
                return null;
            }

            // 1. Extract original vendored credentials from table objects (such as oss.xxx, s3.xxx format)
            Map<String, String> rawVendedCredentials = extractRawVendedCredentials(tableObject);
            if (rawVendedCredentials == null || rawVendedCredentials.isEmpty()) {
                return null;
            }

            // 2. Filter cloud storage properties before format conversion
            Map<String, String> filteredCredentials =
                    CredentialUtils.filterCloudStorageProperties(rawVendedCredentials);
            if (filteredCredentials.isEmpty()) {
                return null;
            }

            // 3. Key steps: Format conversion via StorageProperties.createAll()
            // This avoids writing duplicate transformation logic in the VendedCredentials class
            List<StorageProperties> vendedStorageProperties = StorageProperties.createAll(filteredCredentials);

            // 4. Convert to Map format
            Map<StorageProperties.Type, StorageProperties> vendedPropertiesMap = vendedStorageProperties.stream()
                    .collect(Collectors.toMap(StorageProperties::getType, Function.identity()));

            if (LOG.isDebugEnabled()) {
                LOG.debug("Successfully applied vended credentials for table: {}", getTableName(tableObject));
            }
            return vendedPropertiesMap;

        } catch (Exception e) {
            LOG.warn("Failed to get vended credentials, returning null", e);
            // Return null on failure, Fallback is handled by Factory
            return null;
        }
    }

    /**
     * Check whether to enable vendor credentials (subclass implementation)
     */
    protected abstract boolean isVendedCredentialsEnabled(MetastoreProperties metastoreProperties);

    /**
     * Extract original vendored credentials from table objects (subclass implementation)
     * Returns the original format attribute, which is responsible for the conversion by StorageProperties.createAll()
     */
    protected abstract <T> Map<String, String> extractRawVendedCredentials(T tableObject);

    /**
     * Get the table name (used for logs, subclasses can be rewritable���
     */
    protected <T> String getTableName(T tableObject) {
        return tableObject != null ? tableObject.toString() : "null";
    }

}