Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/consume/InlongConsumeProcessService.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.inlong.manager.service.consume;

import lombok.extern.slf4j.Slf4j;
import org.apache.inlong.manager.common.enums.ConsumeStatus;
import org.apache.inlong.manager.common.enums.ProcessName;
import org.apache.inlong.manager.pojo.workflow.WorkflowResult;
import org.apache.inlong.manager.pojo.workflow.form.process.ApplyConsumeProcessForm;
import org.apache.inlong.manager.service.workflow.WorkflowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Operation to the inlong consume process.
 */
@Slf4j
@Service
public class InlongConsumeProcessService {

    @Autowired
    private InlongConsumeService consumeService;
    @Autowired
    private WorkflowService workflowService;

    /**
     * Start the process for the specified ID.
     *
     * @param id inlong consume id
     * @param operator name of operator
     * @return workflow result
     */
    public WorkflowResult startProcess(Integer id, String operator) {
        consumeService.updateStatus(id, ConsumeStatus.TO_BE_APPROVAL.getCode(), operator);
        return workflowService.start(ProcessName.APPLY_CONSUME_PROCESS, operator, genApplyConsumeProcessForm(id));
    }

    private ApplyConsumeProcessForm genApplyConsumeProcessForm(Integer id) {
        ApplyConsumeProcessForm form = new ApplyConsumeProcessForm();
        form.setConsumeInfo(consumeService.get(id));
        return form;
    }

}

## 内容2
### 文件路径：
inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/consume/InlongConsumeService.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.inlong.manager.service.consume;

import org.apache.inlong.manager.pojo.common.PageResult;
import org.apache.inlong.manager.pojo.consume.InlongConsumeBriefInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumeCountInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumeInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumePageRequest;
import org.apache.inlong.manager.pojo.consume.InlongConsumeRequest;
import org.apache.inlong.manager.pojo.group.InlongGroupInfo;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

/**
 * Inlong consume service layer interface
 */
public interface InlongConsumeService {

    /**
     * Save inlong consume info.
     *
     * @param request consume request need to save
     * @param operator name of operator
     * @return inlong consume id after saving
     */
    Integer save(InlongConsumeRequest request, String operator);

    /**
     * Save the consumer group by InLong system, and not start the workflow process.
     *
     * @return inlong consume id after saving
     */
    Integer saveBySystem(InlongGroupInfo groupInfo, String topic, String consumerGroup);

    /**
     * Get inlong consume info based on ID
     *
     * @param id inlong consume id
     * @return detail of inlong group
     */
    InlongConsumeInfo get(Integer id);

    /**
     * Check whether the consumer group exists or not
     *
     * @param consumerGroup consumer group
     * @param excludeSelfId exclude the ID of this record
     * @return true if exists, false if not exists
     */
    boolean consumerGroupExists(String consumerGroup, Integer excludeSelfId);

    /**
     * Paging query inlong consume info list
     *
     * @param request pagination query request
     * @return inlong consume list
     */
    PageResult<InlongConsumeBriefInfo> list(InlongConsumePageRequest request);

    /**
     * Query the inlong consume statistics info via the username
     *
     * @param username username
     * @return inlong consume status statistics
     */
    InlongConsumeCountInfo countStatus(String username);

    /**
     * Update the inlong consume
     *
     * @param request inlong consume request that needs to be updated
     * @param operator name of operator
     * @return inlong consume id after saving
     */
    Integer update(@Valid @NotNull(message = "inlong consume request cannot be null") InlongConsumeRequest request,
            String operator);

    /**
     * Update the inlong consume status to the specified status
     *
     * @param id inlong consume id
     * @param status modified status
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean updateStatus(Integer id, Integer status, String operator);

    /**
     * Delete the inlong consume by the id
     *
     * @param id inlong consume id that needs to be deleted
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean delete(Integer id, String operator);

}

## 内容3
### 文件路径：
inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/consume/InlongConsumeServiceImpl.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.inlong.manager.service.consume;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.inlong.manager.common.consts.InlongConstants;
import org.apache.inlong.manager.common.enums.ConsumeStatus;
import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
import org.apache.inlong.manager.common.exceptions.BusinessException;
import org.apache.inlong.manager.common.util.Preconditions;
import org.apache.inlong.manager.dao.entity.InlongConsumeEntity;
import org.apache.inlong.manager.dao.mapper.InlongConsumeEntityMapper;
import org.apache.inlong.manager.pojo.common.CountInfo;
import org.apache.inlong.manager.pojo.common.OrderFieldEnum;
import org.apache.inlong.manager.pojo.common.OrderTypeEnum;
import org.apache.inlong.manager.pojo.common.PageResult;
import org.apache.inlong.manager.pojo.consume.InlongConsumeBriefInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumeCountInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumeInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumePageRequest;
import org.apache.inlong.manager.pojo.consume.InlongConsumeRequest;
import org.apache.inlong.manager.pojo.group.InlongGroupInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.apache.inlong.manager.pojo.common.PageRequest.MAX_PAGE_SIZE;

/**
 * Inlong consume service layer implementation
 */
@Service
public class InlongConsumeServiceImpl implements InlongConsumeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(InlongConsumeServiceImpl.class);
    private static final String AUTO_CREATE_MSG = "auto_create_by_system";

    @Autowired
    private InlongConsumeEntityMapper consumeMapper;
    @Autowired
    private InlongConsumeOperatorFactory consumeOperatorFactory;

    @Override
    public Integer save(InlongConsumeRequest request, String operator) {
        LOGGER.debug("begin to save inlong consume={} by user={}", request, operator);
        Preconditions.expectNotNull(request, "inlong consume request cannot be null");
        Preconditions.expectNotBlank(request.getTopic(), ErrorCodeEnum.INVALID_PARAMETER,
                "inlong consume topic cannot be null");
        String consumerGroup = request.getConsumerGroup();
        Preconditions.expectNotBlank(consumerGroup, ErrorCodeEnum.INVALID_PARAMETER,
                "inlong consume topic cannot be null");
        if (consumerGroupExists(consumerGroup, request.getId())) {
            throw new BusinessException(String.format("consumer group %s already exist", consumerGroup));
        }

        InlongConsumeOperator consumeOperator = consumeOperatorFactory.getInstance(request.getMqType());
        Integer id = consumeOperator.saveOpt(request, operator);

        LOGGER.info("success to save inlong consume for consumer group={} by user={}", consumerGroup, operator);
        return id;
    }

    @Override
    public Integer saveBySystem(InlongGroupInfo groupInfo, String topic, String consumerGroup) {
        String groupId = groupInfo.getInlongGroupId();
        InlongConsumeEntity existEntity = consumeMapper.selectExists(consumerGroup, topic, groupId);
        if (existEntity != null) {
            LOGGER.warn("inlong consume already exists for groupId={} topic={} consumerGroup={}, skip to create",
                    groupId, topic, consumerGroup);
            return existEntity.getId();
        }

        LOGGER.debug("begin to save inlong consume for groupId={} topic={} group={}", groupId, topic, consumerGroup);
        InlongConsumeEntity entity = new InlongConsumeEntity();
        entity.setConsumerGroup(consumerGroup);
        entity.setDescription(AUTO_CREATE_MSG);
        entity.setMqType(groupInfo.getMqType());
        entity.setTopic(topic);
        entity.setInlongGroupId(groupId);
        entity.setFilterEnabled(0);

        entity.setInCharges(groupInfo.getInCharges());
        entity.setStatus(ConsumeStatus.APPROVE_PASSED.getCode());
        String operator = groupInfo.getCreator();
        entity.setCreator(operator);
        entity.setModifier(operator);

        consumeMapper.insert(entity);
        LOGGER.debug("success save inlong consume for groupId={} topic={} group={}", groupId, topic, consumerGroup);
        return entity.getId();
    }

    @Override
    public boolean consumerGroupExists(String consumerGroup, Integer excludeSelfId) {
        InlongConsumePageRequest request = InlongConsumePageRequest.builder()
                .consumerGroup(consumerGroup)
                .isAdminRole(true)
                .build();
        List<InlongConsumeEntity> result = consumeMapper.selectByCondition(request);
        if (excludeSelfId != null) {
            result = result.stream()
                    .filter(consumer -> !excludeSelfId.equals(consumer.getId()))
                    .collect(Collectors.toList());
        }
        return CollectionUtils.isNotEmpty(result);
    }

    @Override
    public InlongConsumeInfo get(Integer id) {
        Preconditions.expectNotNull(id, "inlong consume id cannot be null");
        InlongConsumeEntity entity = consumeMapper.selectById(id);
        if (entity == null) {
            LOGGER.error("inlong consume not found with id={}", id);
            throw new BusinessException(ErrorCodeEnum.CONSUME_NOT_FOUND);
        }

        InlongConsumeOperator consumeOperator = consumeOperatorFactory.getInstance(entity.getMqType());
        InlongConsumeInfo consumeInfo = consumeOperator.getFromEntity(entity);

        LOGGER.debug("success to get inlong consume for id={}", id);
        return consumeInfo;
    }

    @Override
    public InlongConsumeCountInfo countStatus(String username) {
        List<CountInfo> countInfoList = consumeMapper.countByUser(username);
        InlongConsumeCountInfo result = new InlongConsumeCountInfo();
        for (CountInfo countInfo : countInfoList) {
            int status = Integer.parseInt(countInfo.getKey());
            int count = countInfo.getValue();
            result.setTotalCount(result.getTotalCount() + count);
            if (status == ConsumeStatus.TO_BE_SUBMIT.getCode()) {
                result.setWaitAssignCount(result.getWaitAssignCount() + count);
            } else if (status == ConsumeStatus.TO_BE_APPROVAL.getCode()) {
                result.setWaitApproveCount(result.getWaitApproveCount() + count);
            } else if (status == ConsumeStatus.APPROVE_REJECTED.getCode()) {
                result.setRejectCount(result.getRejectCount() + count);
            }
        }

        LOGGER.debug("success to count inlong consume for user={}", username);
        return result;
    }

    @Override
    public PageResult<InlongConsumeBriefInfo> list(InlongConsumePageRequest request) {
        if (request.getPageSize() > MAX_PAGE_SIZE) {
            LOGGER.warn("list inlong consumes, change page size from {} to {}", request.getPageSize(), MAX_PAGE_SIZE);
            request.setPageSize(MAX_PAGE_SIZE);
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        OrderFieldEnum.checkOrderField(request);
        OrderTypeEnum.checkOrderType(request);
        Page<InlongConsumeBriefInfo> briefInfos = (Page<InlongConsumeBriefInfo>) consumeMapper.selectBriefList(request);
        PageResult<InlongConsumeBriefInfo> pageResult = new PageResult<>(briefInfos,
                briefInfos.getTotal(), briefInfos.getPageNum(), briefInfos.getPageSize());

        LOGGER.debug("success to list inlong consume for {}", request);
        return pageResult;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
    public Integer update(InlongConsumeRequest request, String operator) {
        LOGGER.debug("begin to update inlong consume={} by user={}", request, operator);
        Preconditions.expectNotNull(request, "inlong consume request cannot be null");

        // check if it can be modified
        Integer consumeId = request.getId();
        InlongConsumeEntity existEntity = consumeMapper.selectById(consumeId);
        Preconditions.expectNotNull(existEntity, "inlong consume not exist with id " + consumeId);
        Preconditions.expectTrue(existEntity.getInCharges().contains(operator),
                "operator" + operator + " has no privilege for the inlong consume");

        if (!Objects.equals(existEntity.getVersion(), request.getVersion())) {
            LOGGER.error(String.format("inlong consume has already updated, id=%s, curVersion=%s",
                    existEntity.getId(), request.getVersion()));
            throw new BusinessException(ErrorCodeEnum.CONFIG_EXPIRED);
        }

        ConsumeStatus consumeStatus = ConsumeStatus.forCode(existEntity.getStatus());
        Preconditions.expectTrue(ConsumeStatus.allowedUpdate(consumeStatus),
                "inlong consume not allowed update when status is " + consumeStatus.name());

        InlongConsumeOperator consumeOperator = consumeOperatorFactory.getInstance(request.getMqType());
        consumeOperator.updateOpt(request, operator);

        LOGGER.info("success to update inlong consume={} by user={}", request, operator);
        return consumeId;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
    public Boolean updateStatus(Integer id, Integer status, String operator) {
        LOGGER.info("begin to update consume status to [{}] for id={} by user={}", status, id, operator);
        Preconditions.expectNotNull(id, ErrorCodeEnum.ID_IS_EMPTY.getMessage());
        InlongConsumeEntity entity = consumeMapper.selectById(id);
        if (entity == null) {
            LOGGER.error("inlong consume not found by id={}", id);
            throw new BusinessException(ErrorCodeEnum.CONSUME_NOT_FOUND);
        }

        ConsumeStatus curStatus = ConsumeStatus.forCode(entity.getStatus());
        ConsumeStatus nextStatus = ConsumeStatus.forCode(status);
        if (ConsumeStatus.notAllowedTransfer(curStatus, nextStatus)) {
            String errorMsg = String.format("Current status=%s cannot transfer to status=%s", curStatus, nextStatus);
            LOGGER.error(errorMsg);
            throw new BusinessException(errorMsg);
        }

        consumeMapper.updateStatus(id, status, operator);
        LOGGER.info("success to update consume status to [{}] for id={} by user={}", status, id, operator);
        return true;
    }

    @Override
    public Boolean delete(Integer id, String operator) {
        LOGGER.info("begin to delete inlong consume for id={} by user={}", id, operator);
        Preconditions.expectNotNull(id, "inlong consume id cannot be null");
        InlongConsumeEntity entity = consumeMapper.selectById(id);
        Preconditions.expectNotNull(entity, "inlong consume not exist with id " + id);

        entity.setIsDeleted(id);
        entity.setStatus(ConsumeStatus.DELETED.getCode());
        entity.setModifier(operator);

        int rowCount = consumeMapper.updateByIdSelective(entity);
        if (rowCount != InlongConstants.AFFECTED_ONE_ROW) {
            LOGGER.error("inlong consume has already updated with id={}, curVersion={}", id, entity.getVersion());
            throw new BusinessException(ErrorCodeEnum.CONFIG_EXPIRED);
        }

        LOGGER.info("success to delete inlong consume for id={} by user={}", id, operator);
        return true;
    }

}

## 内容4
### 文件路径：
inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/StreamSinkService.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.inlong.manager.service.sink;

import org.apache.inlong.manager.pojo.common.PageResult;
import org.apache.inlong.manager.pojo.common.UpdateResult;
import org.apache.inlong.manager.pojo.group.InlongGroupInfo;
import org.apache.inlong.manager.pojo.sink.ParseFieldRequest;
import org.apache.inlong.manager.pojo.sink.SinkApproveDTO;
import org.apache.inlong.manager.pojo.sink.SinkBriefInfo;
import org.apache.inlong.manager.pojo.sink.SinkField;
import org.apache.inlong.manager.pojo.sink.SinkPageRequest;
import org.apache.inlong.manager.pojo.sink.SinkRequest;
import org.apache.inlong.manager.pojo.sink.StreamSink;
import org.apache.inlong.manager.pojo.stream.InlongStreamInfo;
import org.apache.inlong.manager.pojo.user.UserInfo;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;

/**
 * Service layer interface for stream sink
 */
public interface StreamSinkService {

    /**
     * Save the sink info.
     *
     * @param request sink request need to save
     * @param operator name of operator
     * @return sink id after saving
     */
    Integer save(SinkRequest request, String operator);

    /**
     * Save the sink info.
     *
     * @param request sink request need to save
     * @param opInfo userinfo of operator
     * @return sink id after saving
     */
    Integer save(SinkRequest request, UserInfo opInfo);

    /**
     * Get stream sink info based on id.
     *
     * @param id sink id
     * @return detail of stream sink info
     */
    StreamSink get(Integer id);

    /**
     * Get stream sink info based on id.
     *
     * @param id sink id
     * @param opInfo userinfo of operator
     * @return detail of stream sink info
     */
    StreamSink get(Integer id, UserInfo opInfo);

    /**
     * List the stream sinks based on inlong group id and inlong stream id.
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id, can be null
     * @return sink info list
     */
    List<StreamSink> listSink(String groupId, @Nullable String streamId);

    /**
     * Query sink brief info based on inlong group id and inlong stream id.
     * <p/>
     * The result will include sink cluster info.
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id
     * @return stream sink brief info list
     */
    List<SinkBriefInfo> listBrief(String groupId, String streamId);

    /**
     * Get the StreamSink Map by the inlong group info and inlong stream info list.
     *
     * @param groupInfo inlong group info
     * @param streamInfos inlong stream info list
     * @return map of StreamSink list, key-inlongStreamId, value-StreamSinkList
     */
    Map<String, List<StreamSink>> getSinksMap(InlongGroupInfo groupInfo, List<InlongStreamInfo> streamInfos);

    /**
     * Query the number of undeleted sink info based on inlong group and inlong stream id.
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id
     * @return count of sink info
     */
    Integer getCount(String groupId, String streamId);

    /**
     * Paging query stream sink info based on conditions.
     *
     * @param request paging request
     * @return sink page list
     */
    PageResult<? extends StreamSink> listByCondition(SinkPageRequest request);

    /**
     * Paging query stream sink info based on conditions.
     *
     * @param request paging request
     * @param opInfo userinfo of operator
     * @return sink page list
     */
    List<? extends StreamSink> listByCondition(SinkPageRequest request, UserInfo opInfo);

    /**
     * Modify stream sink info by id.
     *
     * @param sinkRequest stream sink request that needs to be modified
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean update(SinkRequest sinkRequest, String operator);

    /**
     * Modify stream sink info by id.
     *
     * @param sinkRequest stream sink request that needs to be modified
     * @param opInfo userinfo of operator
     * @return whether succeed
     */
    Boolean update(SinkRequest sinkRequest, UserInfo opInfo);

    /**
     * Modify stream sink info by key.
     *
     * @param sinkRequest stream sink request that needs to be modified
     * @param operator name of operator
     * @return update result
     */
    UpdateResult updateByKey(SinkRequest sinkRequest, String operator);

    /**
     * Modify stream sink status.
     *
     * @param id stream sink id
     * @param status target status
     * @param log log info of this modification
     */
    void updateStatus(Integer id, int status, String log);

    /**
     * Delete the stream sink by the given id and sink type.
     *
     * @param id stream sink id
     * @param startProcess whether to start the process after saving or updating
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean delete(Integer id, Boolean startProcess, String operator);

    /**
     * Delete the stream sink by the given id and sink type.
     *
     * @param id stream sink id
     * @param startProcess whether to start the process after saving or updating
     * @param opInfo userinfo of operator
     * @return whether succeed
     */
    Boolean delete(Integer id, Boolean startProcess, UserInfo opInfo);

    /**
     * Delete the stream sink by given group id, stream id, and sink name.
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id
     * @param name stream sink name
     * @param startProcess whether to start the process after saving or updating
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean deleteByKey(String groupId, String streamId, String name, Boolean startProcess, String operator);

    /**
     * Logically delete stream sink with the given conditions.
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean logicDeleteAll(String groupId, String streamId, String operator);

    /**
     * Physically delete stream sink with the given conditions.
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean deleteAll(String groupId, String streamId, String operator);

    /**
     * According to the existing inlong stream ID list, filter out the inlong stream id list
     * containing the specified sink type.
     *
     * @param groupId inlong group id
     * @param sinkType stream sink type
     * @param streamIdList inlong stream id list
     * @return list of filtered inlong stream ids
     */
    List<String> getExistsStreamIdList(String groupId, String sinkType, List<String> streamIdList);

    /**
     * According to the inlong stream id, query the list of sink types owned by it
     *
     * @param groupId inlong group id
     * @param streamId inlong stream id
     * @return list of sink types
     */
    List<String> getSinkTypeList(String groupId, String streamId);

    /**
     * Save the information modified when the approval is passed
     *
     * @param sinkApproveList stream sink approval information
     * @param operator name of operator
     * @return whether succeed
     */
    Boolean updateAfterApprove(List<SinkApproveDTO> sinkApproveList, String operator);

    /**
     * Converts a statement to a sinkFields
     *
     * @param parseFieldRequest the request for parse field
     * @return list of sink field
     */
    List<SinkField> parseFields(ParseFieldRequest parseFieldRequest);
}

## 内容5
### 文件路径：
inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/StreamSinkServiceImpl.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.inlong.manager.service.sink;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.inlong.manager.common.consts.InlongConstants;
import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
import org.apache.inlong.manager.common.enums.GroupStatus;
import org.apache.inlong.manager.common.enums.SinkStatus;
import org.apache.inlong.manager.common.enums.StreamStatus;
import org.apache.inlong.manager.common.enums.UserTypeEnum;
import org.apache.inlong.manager.common.exceptions.BusinessException;
import org.apache.inlong.manager.common.util.Preconditions;
import org.apache.inlong.manager.dao.entity.InlongGroupEntity;
import org.apache.inlong.manager.dao.entity.InlongStreamEntity;
import org.apache.inlong.manager.dao.entity.StreamSinkEntity;
import org.apache.inlong.manager.dao.mapper.InlongGroupEntityMapper;
import org.apache.inlong.manager.dao.mapper.InlongStreamEntityMapper;
import org.apache.inlong.manager.dao.mapper.StreamSinkEntityMapper;
import org.apache.inlong.manager.dao.mapper.StreamSinkFieldEntityMapper;
import org.apache.inlong.manager.pojo.common.OrderFieldEnum;
import org.apache.inlong.manager.pojo.common.OrderTypeEnum;
import org.apache.inlong.manager.pojo.common.PageResult;
import org.apache.inlong.manager.pojo.common.UpdateResult;
import org.apache.inlong.manager.pojo.group.InlongGroupInfo;
import org.apache.inlong.manager.pojo.sink.ParseFieldRequest;
import org.apache.inlong.manager.pojo.sink.SinkApproveDTO;
import org.apache.inlong.manager.pojo.sink.SinkBriefInfo;
import org.apache.inlong.manager.pojo.sink.SinkField;
import org.apache.inlong.manager.pojo.sink.SinkPageRequest;
import org.apache.inlong.manager.pojo.sink.SinkRequest;
import org.apache.inlong.manager.pojo.sink.StreamSink;
import org.apache.inlong.manager.pojo.stream.InlongStreamInfo;
import org.apache.inlong.manager.pojo.user.UserInfo;
import org.apache.inlong.manager.service.group.GroupCheckService;
import org.apache.inlong.manager.service.stream.InlongStreamProcessService;
import org.apache.inlong.manager.service.user.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.table.ColDataType;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.apache.inlong.manager.common.consts.InlongConstants.LEFT_BRACKET;
import static org.apache.inlong.manager.common.consts.InlongConstants.PATTERN_NORMAL_CHARACTERS;
import static org.apache.inlong.manager.common.consts.InlongConstants.STATEMENT_TYPE_CSV;
import static org.apache.inlong.manager.common.consts.InlongConstants.STATEMENT_TYPE_JSON;
import static org.apache.inlong.manager.common.consts.InlongConstants.STATEMENT_TYPE_SQL;
import static org.apache.inlong.manager.common.consts.InlongConstants.BATCH_PARSING_FILED_JSON_COMMENT_PROP;
import static org.apache.inlong.manager.common.consts.InlongConstants.BATCH_PARSING_FILED_JSON_NAME_PROP;
import static org.apache.inlong.manager.common.consts.InlongConstants.BATCH_PARSING_FILED_JSON_TYPE_PROP;

/**
 * Implementation of sink service interface
 */
@Service
public class StreamSinkServiceImpl implements StreamSinkService {

    private static final Logger LOGGER = LoggerFactory.getLogger(StreamSinkServiceImpl.class);
    private static final Pattern PARSE_FIELD_CSV_SPLITTER = Pattern.compile("[\t\\s,]");
    private static final int PARSE_FIELD_CSV_MAX_COLUMNS = 3;
    private static final int PARSE_FIELD_CSV_MIN_COLUMNS = 2;

    @Autowired
    private SinkOperatorFactory operatorFactory;
    @Autowired
    private GroupCheckService groupCheckService;
    @Autowired
    private InlongStreamEntityMapper streamMapper;
    @Autowired
    private InlongGroupEntityMapper groupMapper;
    @Autowired
    private StreamSinkEntityMapper sinkMapper;
    @Autowired
    private StreamSinkFieldEntityMapper sinkFieldMapper;
    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;
    @Autowired
    private UserService userService;
    @Autowired
    private ObjectMapper objectMapper;

    // To avoid circular dependencies, you cannot use @Autowired, it will be injected by AutowireCapableBeanFactory
    private InlongStreamProcessService streamProcessOperation;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Integer save(SinkRequest request, String operator) {
        LOGGER.info("begin to save sink info: {}", request);
        this.checkParams(request);

        // Check if it can be added
        String groupId = request.getInlongGroupId();
        groupCheckService.checkGroupStatus(groupId, operator);

        // Make sure that there is no same sink name under the current groupId and streamId
        String streamId = request.getInlongStreamId();
        String sinkName = request.getSinkName();
        // Check whether the stream exist or not
        InlongStreamEntity streamEntity = streamMapper.selectByIdentifier(groupId, streamId);
        Preconditions.expectNotNull(streamEntity, ErrorCodeEnum.STREAM_NOT_FOUND.getMessage());

        // Check whether the sink name exists with the same groupId and streamId
        StreamSinkEntity exists = sinkMapper.selectByUniqueKey(groupId, streamId, sinkName);
        if (exists != null && exists.getSinkName().equals(sinkName)) {
            String err = "sink name=%s already exists with the groupId=%s streamId=%s";
            throw new BusinessException(String.format(err, sinkName, groupId, streamId));
        }

        // According to the sink type, save sink information
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(request.getSinkType());
        List<SinkField> fields = request.getSinkFieldList();
        // Remove id in sinkField when save
        if (CollectionUtils.isNotEmpty(fields)) {
            fields.forEach(sinkField -> sinkField.setId(null));
        }
        int id = sinkOperator.saveOpt(request, operator);
        boolean streamSuccess = StreamStatus.CONFIG_SUCCESSFUL.getCode().equals(streamEntity.getStatus());
        if (streamSuccess || StreamStatus.CONFIG_FAILED.getCode().equals(streamEntity.getStatus())) {
            boolean enableCreateResource = InlongConstants.ENABLE_CREATE_RESOURCE.equals(
                    request.getEnableCreateResource());
            SinkStatus nextStatus = request.getStartProcess() ? SinkStatus.CONFIG_ING : SinkStatus.NEW;
            if (!enableCreateResource) {
                nextStatus = SinkStatus.CONFIG_SUCCESSFUL;
            }
            StreamSinkEntity sinkEntity = sinkMapper.selectByPrimaryKey(id);
            sinkEntity.setStatus(nextStatus.getCode());
            sinkMapper.updateStatus(sinkEntity);
        }

        // If the stream is [CONFIG_SUCCESSFUL], then asynchronously start the [CREATE_STREAM_RESOURCE] process
        if (streamSuccess && request.getStartProcess()) {
            this.startProcessForSink(groupId, streamId, operator);
        }

        LOGGER.info("success to save sink info: {}", request);
        return id;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Integer save(SinkRequest request, UserInfo opInfo) {
        // check request parameter
        checkSinkRequestParams(request);
        InlongGroupEntity entity = groupMapper.selectByGroupId(request.getInlongGroupId());
        if (entity == null) {
            throw new BusinessException(ErrorCodeEnum.GROUP_NOT_FOUND,
                    String.format("InlongGroup does not exist with InlongGroupId=%s", request.getInlongGroupId()));
        }
        // only the person in charges can query
        userService.checkUser(entity.getInCharges(), opInfo.getName(),
                ErrorCodeEnum.GROUP_PERMISSION_DENIED.getMessage());
        // check group status
        GroupStatus curState = GroupStatus.forCode(entity.getStatus());
        if (GroupStatus.notAllowedUpdate(curState)) {
            throw new BusinessException(String.format(ErrorCodeEnum.OPT_NOT_ALLOWED_BY_STATUS.getMessage(), curState));
        }
        // Check whether the stream exist or not
        InlongStreamEntity streamEntity =
                streamMapper.selectByIdentifier(request.getInlongGroupId(), request.getInlongStreamId());
        if (streamEntity == null) {
            throw new BusinessException(ErrorCodeEnum.STREAM_NOT_FOUND);
        }
        // Check whether the sink name exists with the same groupId and streamId
        StreamSinkEntity exists = sinkMapper.selectByUniqueKey(
                request.getInlongGroupId(), request.getInlongStreamId(), request.getSinkName());
        if (exists != null && exists.getSinkName().equals(request.getSinkName())) {
            throw new BusinessException(ErrorCodeEnum.RECORD_DUPLICATE,
                    String.format("sink name=%s already exists with the groupId=%s streamId=%s",
                            request.getSinkName(), request.getInlongGroupId(), request.getInlongStreamId()));
        }
        // According to the sink type, save sink information
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(request.getSinkType());
        List<SinkField> fields = request.getSinkFieldList();
        // Remove id in sinkField when save
        if (CollectionUtils.isNotEmpty(fields)) {
            fields.forEach(sinkField -> sinkField.setId(null));
        }
        int id = sinkOperator.saveOpt(request, opInfo.getName());
        boolean streamSuccess = StreamStatus.CONFIG_SUCCESSFUL.getCode().equals(streamEntity.getStatus());
        if (streamSuccess || StreamStatus.CONFIG_FAILED.getCode().equals(streamEntity.getStatus())) {
            boolean enableCreateResource = InlongConstants.ENABLE_CREATE_RESOURCE.equals(
                    request.getEnableCreateResource());
            SinkStatus nextStatus = request.getStartProcess() ? SinkStatus.CONFIG_ING : SinkStatus.NEW;
            if (!enableCreateResource) {
                nextStatus = SinkStatus.CONFIG_SUCCESSFUL;
            }
            StreamSinkEntity sinkEntity = sinkMapper.selectByPrimaryKey(id);
            sinkEntity.setStatus(nextStatus.getCode());
            sinkMapper.updateStatus(sinkEntity);
        }
        // If the stream is [CONFIG_SUCCESSFUL], then asynchronously start the [CREATE_STREAM_RESOURCE] process
        if (streamSuccess && request.getStartProcess()) {
            this.startProcessForSink(request.getInlongGroupId(), request.getInlongStreamId(), opInfo.getName());
        }
        return id;
    }

    @Override
    public StreamSink get(Integer id) {
        if (id == null) {
            throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER, "sink id is empty");
        }
        StreamSinkEntity entity = sinkMapper.selectByPrimaryKey(id);
        if (entity == null) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_NOT_FOUND,
                    String.format("sink not found by id=%s", id));
        }
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(entity.getSinkType());
        return sinkOperator.getFromEntity(entity);
    }

    @Override
    public StreamSink get(Integer id, UserInfo opInfo) {
        StreamSinkEntity entity = sinkMapper.selectByPrimaryKey(id);
        if (entity == null) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_NOT_FOUND);
        }
        InlongGroupEntity groupEntity =
                groupMapper.selectByGroupId(entity.getInlongGroupId());
        if (groupEntity == null) {
            throw new BusinessException(ErrorCodeEnum.GROUP_NOT_FOUND);
        }
        // only the person in charges can query
        userService.checkUser(groupEntity.getInCharges(), opInfo.getName(),
                ErrorCodeEnum.GROUP_PERMISSION_DENIED.getMessage());
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(entity.getSinkType());
        return sinkOperator.getFromEntity(entity);
    }

    @Override
    public Integer getCount(String groupId, String streamId) {
        Integer count = sinkMapper.selectCount(groupId, streamId);
        LOGGER.debug("sink count={} with groupId={}, streamId={}", count, groupId, streamId);
        return count;
    }

    @Override
    public List<StreamSink> listSink(String groupId, String streamId) {
        if (StringUtils.isBlank(groupId)) {
            throw new BusinessException(ErrorCodeEnum.GROUP_ID_IS_EMPTY, "groupId id is blank");
        }
        List<StreamSinkEntity> entityList = sinkMapper.selectByRelatedId(groupId, streamId);
        if (CollectionUtils.isEmpty(entityList)) {
            return Collections.emptyList();
        }
        List<StreamSink> responseList = new ArrayList<>();
        entityList.forEach(entity -> responseList.add(this.get(entity.getId())));
        return responseList;
    }

    @Override
    public List<SinkBriefInfo> listBrief(String groupId, String streamId) {
        Preconditions.expectNotBlank(groupId, ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        Preconditions.expectNotBlank(streamId, ErrorCodeEnum.STREAM_ID_IS_EMPTY);

        List<SinkBriefInfo> summaryList = sinkMapper.selectSummary(groupId, streamId);
        LOGGER.debug("success to list sink summary by groupId={}, streamId={}", groupId, streamId);

        return summaryList;
    }

    @Override
    public Map<String, List<StreamSink>> getSinksMap(InlongGroupInfo groupInfo, List<InlongStreamInfo> streamInfos) {
        String groupId = groupInfo.getInlongGroupId();
        LOGGER.debug("begin to get sink map for groupId={}", groupId);

        List<StreamSink> streamSinks = this.listSink(groupId, null);
        Map<String, List<StreamSink>> result = streamSinks.stream()
                .collect(Collectors.groupingBy(StreamSink::getInlongStreamId, HashMap::new,
                        Collectors.toCollection(ArrayList::new)));

        LOGGER.debug("success to get sink map, size={}, groupInfo={}", result.size(), groupInfo);
        return result;
    }

    @Override
    public PageResult<? extends StreamSink> listByCondition(SinkPageRequest request) {
        Preconditions.expectNotBlank(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY);

        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        OrderFieldEnum.checkOrderField(request);
        OrderTypeEnum.checkOrderType(request);
        List<StreamSinkEntity> entityPage = sinkMapper.selectByCondition(request);
        Map<String, Page<StreamSinkEntity>> sinkMap = Maps.newHashMap();
        for (StreamSinkEntity streamSink : entityPage) {
            sinkMap.computeIfAbsent(streamSink.getSinkType(), k -> new Page<>()).add(streamSink);
        }
        List<StreamSink> responseList = Lists.newArrayList();
        for (Map.Entry<String, Page<StreamSinkEntity>> entry : sinkMap.entrySet()) {
            StreamSinkOperator sinkOperator = operatorFactory.getInstance(entry.getKey());
            PageResult<? extends StreamSink> pageInfo = sinkOperator.getPageInfo(entry.getValue());
            responseList.addAll(pageInfo.getList());
        }
        // Encapsulate the paging query results into the PageInfo object to obtain related paging information
        PageResult<StreamSink> pageResult = new PageResult<>(responseList);

        LOGGER.debug("success to list sink page, result size {}", pageResult.getList().size());
        return pageResult;
    }

    @Override
    public List<? extends StreamSink> listByCondition(SinkPageRequest request, UserInfo opInfo) {
        // check sink id
        if (StringUtils.isBlank(request.getInlongGroupId())) {
            throw new BusinessException(ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        }
        // query result
        OrderFieldEnum.checkOrderField(request);
        OrderTypeEnum.checkOrderType(request);
        List<StreamSinkEntity> sinkEntityList = sinkMapper.selectByCondition(request);
        Map<String, Page<StreamSinkEntity>> sinkMap = Maps.newHashMap();
        for (StreamSinkEntity streamSink : sinkEntityList) {
            sinkMap.computeIfAbsent(streamSink.getSinkType(), k -> new Page<>()).add(streamSink);
        }
        List<StreamSink> filterResult = Lists.newArrayList();
        for (Map.Entry<String, Page<StreamSinkEntity>> entry : sinkMap.entrySet()) {
            StreamSinkOperator sinkOperator = operatorFactory.getInstance(entry.getKey());
            PageResult<? extends StreamSink> pageInfo = sinkOperator.getPageInfo(entry.getValue());
            for (StreamSink streamSink : pageInfo.getList()) {
                InlongGroupEntity groupEntity =
                        groupMapper.selectByGroupId(streamSink.getInlongGroupId());
                if (groupEntity == null) {
                    continue;
                }
                // only the person in charges can query
                if (!opInfo.getAccountType().equals(UserTypeEnum.ADMIN.getCode())) {
                    List<String> inCharges = Arrays.asList(groupEntity.getInCharges().split(InlongConstants.COMMA));
                    if (!inCharges.contains(opInfo.getName())) {
                        continue;
                    }
                }
                filterResult.add(streamSink);
            }
        }
        return filterResult;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean update(SinkRequest request, String operator) {
        LOGGER.info("begin to update sink by id: {}", request);
        if (request == null) {
            throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                    "inlong sink request is empty");
        }
        if (request.getId() == null) {
            throw new BusinessException(ErrorCodeEnum.ID_IS_EMPTY);
        }
        StreamSinkEntity curEntity = sinkMapper.selectByPrimaryKey(request.getId());
        if (curEntity == null) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_NOT_FOUND);
        }
        chkUnmodifiableParams(curEntity, request);
        groupCheckService.checkGroupStatus(request.getInlongGroupId(), operator);
        // Check whether the stream exist or not
        InlongStreamEntity streamEntity = streamMapper.selectByIdentifier(
                request.getInlongGroupId(), request.getInlongStreamId());
        Preconditions.expectNotNull(streamEntity, ErrorCodeEnum.STREAM_NOT_FOUND.getMessage());

        // Check whether the sink name exists with the same groupId and streamId
        StreamSinkEntity existEntity = sinkMapper.selectByUniqueKey(
                request.getInlongGroupId(), request.getInlongStreamId(), request.getSinkName());
        if (existEntity != null && !existEntity.getId().equals(request.getId())) {
            String errMsg = "sink name=%s already exists with the groupId=%s streamId=%s";
            throw new BusinessException(String.format(errMsg,
                    request.getSinkName(), request.getInlongGroupId(), request.getInlongStreamId()));
        }

        SinkStatus nextStatus = null;
        boolean enableConfig = StreamStatus.CONFIG_SUCCESSFUL.getCode().equals(streamEntity.getStatus())
                || StreamStatus.CONFIG_FAILED.getCode().equals(streamEntity.getStatus());
        if (enableConfig) {
            boolean enableCreateResource = InlongConstants.ENABLE_CREATE_RESOURCE.equals(
                    request.getEnableCreateResource());
            nextStatus = enableCreateResource ? SinkStatus.CONFIG_ING : SinkStatus.CONFIG_SUCCESSFUL;
        }
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(request.getSinkType());
        sinkOperator.updateOpt(request, nextStatus, operator);

        // If the stream is [CONFIG_SUCCESSFUL] or [CONFIG_FAILED], then asynchronously start the
        // [CREATE_STREAM_RESOURCE] process
        if (enableConfig && request.getStartProcess()) {
            this.startProcessForSink(request.getInlongGroupId(), request.getInlongStreamId(), operator);
        }

        LOGGER.info("success to update sink by id: {}", request);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean update(SinkRequest request, UserInfo opInfo) {
        if (request.getId() == null) {
            throw new BusinessException(ErrorCodeEnum.ID_IS_EMPTY);
        }
        StreamSinkEntity curEntity = sinkMapper.selectByPrimaryKey(request.getId());
        if (curEntity == null) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_NOT_FOUND);
        }
        chkUnmodifiableParams(curEntity, request);
        // check group record
        InlongGroupEntity curGroupEntity = groupMapper.selectByGroupId(curEntity.getInlongGroupId());
        if (curGroupEntity == null) {
            throw new BusinessException(ErrorCodeEnum.ILLEGAL_RECORD_FIELD_VALUE,
                    String.format("InlongGroup does not exist with InlongGroupId=%s", curEntity.getInlongGroupId()));
        }
        // only the person in charges can query
        userService.checkUser(curGroupEntity.getInCharges(), opInfo.getName(),
                ErrorCodeEnum.GROUP_PERMISSION_DENIED.getMessage());
        // Check if group status can be modified
        GroupStatus curState = GroupStatus.forCode(curEntity.getStatus());
        if (GroupStatus.notAllowedUpdate(curState)) {
            throw new BusinessException(String.format(ErrorCodeEnum.OPT_NOT_ALLOWED_BY_STATUS.getMessage(), curState));
        }
        // Check whether the stream exist or not
        InlongStreamEntity streamEntity = streamMapper.selectByIdentifier(
                request.getInlongGroupId(), request.getInlongStreamId());
        if (streamEntity == null) {
            throw new BusinessException(ErrorCodeEnum.ILLEGAL_RECORD_FIELD_VALUE,
                    String.format("stream record not found with the groupId=%s streamId=%s",
                            curEntity.getInlongGroupId(), curEntity.getInlongStreamId()));
        }
        // Check whether the sink name exists with the same groupId and streamId
        StreamSinkEntity existEntity = sinkMapper.selectByUniqueKey(
                request.getInlongGroupId(), request.getInlongStreamId(), request.getSinkName());
        if (existEntity != null && !existEntity.getId().equals(request.getId())) {
            throw new BusinessException(ErrorCodeEnum.RECORD_DUPLICATE,
                    String.format("sink name=%s already exists with the groupId=%s streamId=%s",
                            request.getSinkName(), request.getInlongGroupId(), request.getInlongStreamId()));
        }
        // update record
        SinkStatus nextStatus = null;
        boolean enableConfig = StreamStatus.CONFIG_SUCCESSFUL.getCode().equals(streamEntity.getStatus())
                || StreamStatus.CONFIG_FAILED.getCode().equals(streamEntity.getStatus());
        if (enableConfig) {
            boolean enableCreateResource = InlongConstants.ENABLE_CREATE_RESOURCE.equals(
                    request.getEnableCreateResource());
            nextStatus = enableCreateResource ? SinkStatus.CONFIG_ING : SinkStatus.CONFIG_SUCCESSFUL;
        }
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(request.getSinkType());
        sinkOperator.updateOpt(request, nextStatus, opInfo.getName());
        // If the stream is [CONFIG_SUCCESSFUL] or [CONFIG_FAILED], then asynchronously start the
        // [CREATE_STREAM_RESOURCE] process
        if (enableConfig && request.getStartProcess()) {
            this.startProcessForSink(request.getInlongGroupId(), request.getInlongStreamId(), opInfo.getName());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public UpdateResult updateByKey(SinkRequest request, String operator) {
        LOGGER.info("begin to update sink by key: {}", request);

        // Check whether the stream sink exists
        String groupId = request.getInlongGroupId();
        String streamId = request.getInlongStreamId();
        String sinkName = request.getSinkName();
        StreamSinkEntity entity = sinkMapper.selectByUniqueKey(groupId, streamId, sinkName);
        if (entity == null) {
            String errMsg = String.format("stream sink not found with groupId=%s, streamId=%s, sinkName=%s",
                    groupId, streamId, sinkName);
            LOGGER.error(errMsg);
            throw new BusinessException(errMsg);
        }
        request.setId(entity.getId());
        Boolean result = this.update(request, operator);
        LOGGER.info("success to update sink by key: {}", request);
        return new UpdateResult(entity.getId(), result, request.getVersion() + 1);
    }

    @Override
    public void updateStatus(Integer id, int status, String log) {
        StreamSinkEntity entity = new StreamSinkEntity();
        entity.setId(id);
        entity.setStatus(status);
        entity.setOperateLog(log);
        sinkMapper.updateStatus(entity);

        LOGGER.info("success to update sink status={} for id={} with log: {}", status, id, log);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean delete(Integer id, Boolean startProcess, String operator) {
        LOGGER.info("begin to delete sink by id={}", id);
        Preconditions.expectNotNull(id, ErrorCodeEnum.ID_IS_EMPTY.getMessage());
        StreamSinkEntity entity = sinkMapper.selectByPrimaryKey(id);
        Preconditions.expectNotNull(entity, ErrorCodeEnum.SINK_INFO_NOT_FOUND.getMessage());

        groupCheckService.checkGroupStatus(entity.getInlongGroupId(), operator);

        StreamSinkOperator sinkOperator = operatorFactory.getInstance(entity.getSinkType());
        sinkOperator.deleteOpt(entity, operator);

        if (startProcess) {
            this.deleteProcessForSink(entity.getInlongGroupId(), entity.getInlongStreamId(), operator);
        }

        LOGGER.info("success to delete sink by id: {}", entity);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean delete(Integer id, Boolean startProcess, UserInfo opInfo) {
        // check stream sink record
        StreamSinkEntity sinkEntity = sinkMapper.selectByPrimaryKey(id);
        if (sinkEntity == null) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_NOT_FOUND);
        }
        // check group record
        InlongGroupEntity groupEntity = groupMapper.selectByGroupId(sinkEntity.getInlongGroupId());
        if (groupEntity == null) {
            throw new BusinessException(ErrorCodeEnum.GROUP_NOT_FOUND,
                    String.format("InlongGroup does not exist with InlongGroupId=%s", sinkEntity.getInlongGroupId()));
        }
        // only the person in charges can query
        userService.checkUser(groupEntity.getInCharges(), opInfo.getName(),
                ErrorCodeEnum.GROUP_PERMISSION_DENIED.getMessage());
        // Check if group status can be modified
        GroupStatus curState = GroupStatus.forCode(groupEntity.getStatus());
        if (GroupStatus.notAllowedUpdate(curState)) {
            throw new BusinessException(String.format(ErrorCodeEnum.OPT_NOT_ALLOWED_BY_STATUS.getMessage(), curState));
        }
        // delete record
        StreamSinkOperator sinkOperator = operatorFactory.getInstance(sinkEntity.getSinkType());
        sinkOperator.deleteOpt(sinkEntity, opInfo.getName());
        if (startProcess) {
            this.deleteProcessForSink(sinkEntity.getInlongGroupId(), sinkEntity.getInlongStreamId(), opInfo.getName());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean deleteByKey(String groupId, String streamId, String sinkName,
            Boolean startProcess, String operator) {
        LOGGER.info("begin to delete sink by groupId={}, streamId={}, sinkName={}", groupId, streamId, sinkName);

        // Check whether the sink name exists with the same groupId and streamId
        Preconditions.expectNotBlank(groupId, ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        Preconditions.expectNotBlank(streamId, ErrorCodeEnum.STREAM_ID_IS_EMPTY);
        Preconditions.expectNotBlank(sinkName, ErrorCodeEnum.INVALID_PARAMETER, "stream sink name is empty or null");
        StreamSinkEntity entity = sinkMapper.selectByUniqueKey(groupId, streamId, sinkName);
        Preconditions.expectNotNull(entity, String.format("stream sink not exist by groupId=%s streamId=%s sinkName=%s",
                groupId, streamId, sinkName));

        groupCheckService.checkGroupStatus(entity.getInlongGroupId(), operator);

        StreamSinkOperator sinkOperator = operatorFactory.getInstance(entity.getSinkType());
        sinkOperator.deleteOpt(entity, operator);

        if (startProcess) {
            this.deleteProcessForSink(entity.getInlongGroupId(), entity.getInlongStreamId(), operator);
        }

        LOGGER.info("success to delete sink by key: {}", entity);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean logicDeleteAll(String groupId, String streamId, String operator) {
        LOGGER.info("begin to logic delete all sink info by groupId={}, streamId={}", groupId, streamId);
        Preconditions.expectNotBlank(groupId, ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        Preconditions.expectNotBlank(streamId, ErrorCodeEnum.STREAM_ID_IS_EMPTY);

        // Check if it can be deleted
        groupCheckService.checkGroupStatus(groupId, operator);

        List<StreamSinkEntity> entityList = sinkMapper.selectByRelatedId(groupId, streamId);
        if (CollectionUtils.isNotEmpty(entityList)) {
            entityList.forEach(entity -> {
                Integer id = entity.getId();
                entity.setPreviousStatus(entity.getStatus());
                entity.setStatus(InlongConstants.DELETED_STATUS);
                entity.setIsDeleted(id);
                entity.setModifier(operator);
                int rowCount = sinkMapper.updateByIdSelective(entity);
                if (rowCount != InlongConstants.AFFECTED_ONE_ROW) {
                    LOGGER.error("sink has already updated with groupId={}, streamId={}, name={}, curVersion={}",
                            entity.getInlongGroupId(), entity.getInlongStreamId(), entity.getSinkName(),
                            entity.getVersion());
                    throw new BusinessException(ErrorCodeEnum.CONFIG_EXPIRED);
                }
                sinkFieldMapper.logicDeleteAll(id);
            });
        }

        LOGGER.info("success to logic delete all sink by groupId={}, streamId={}", groupId, streamId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean deleteAll(String groupId, String streamId, String operator) {
        LOGGER.info("begin to delete all sink by groupId={}, streamId={}", groupId, streamId);
        Preconditions.expectNotBlank(groupId, ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        Preconditions.expectNotBlank(streamId, ErrorCodeEnum.STREAM_ID_IS_EMPTY);

        // Check if it can be deleted
        groupCheckService.checkGroupStatus(groupId, operator);

        List<StreamSinkEntity> entityList = sinkMapper.selectByRelatedId(groupId, streamId);
        if (CollectionUtils.isNotEmpty(entityList)) {
            entityList.forEach(entity -> {
                sinkMapper.deleteById(entity.getId());
                sinkFieldMapper.deleteAll(entity.getId());
            });
        }

        LOGGER.info("success to delete all sink by groupId={}, streamId={}", groupId, streamId);
        return true;
    }

    @Override
    public List<String> getExistsStreamIdList(String groupId, String sinkType, List<String> streamIdList) {
        LOGGER.debug("begin to filter stream by groupId={}, type={}, streamId={}", groupId, sinkType, streamIdList);
        if (StringUtils.isEmpty(sinkType) || CollectionUtils.isEmpty(streamIdList)) {
            return Collections.emptyList();
        }

        List<String> resultList = sinkMapper.selectExistsStreamId(groupId, sinkType, streamIdList);
        LOGGER.debug("success to filter stream id list, result streamId={}", resultList);
        return resultList;
    }

    @Override
    public List<String> getSinkTypeList(String groupId, String streamId) {
        if (StringUtils.isEmpty(streamId)) {
            return Collections.emptyList();
        }

        List<String> resultList = sinkMapper.selectSinkType(groupId, streamId);
        LOGGER.debug("success to get sink type by groupId={}, streamId={}, result={}", groupId, streamId, resultList);
        return resultList;
    }

    @Override
    public Boolean updateAfterApprove(List<SinkApproveDTO> approveList, String operator) {
        LOGGER.info("begin to update sink after approve: {}", approveList);
        if (CollectionUtils.isEmpty(approveList)) {
            return true;
        }

        for (SinkApproveDTO dto : approveList) {
            // According to the sink type, save sink information
            String sinkType = dto.getSinkType();
            Preconditions.expectNotBlank(sinkType, ErrorCodeEnum.SINK_TYPE_IS_NULL);

            StreamSinkEntity entity = sinkMapper.selectByPrimaryKey(dto.getId());

            int status = (dto.getStatus() == null) ? SinkStatus.CONFIG_ING.getCode() : dto.getStatus();
            entity.setPreviousStatus(entity.getStatus());
            entity.setStatus(status);
            entity.setModifier(operator);
            int rowCount = sinkMapper.updateByIdSelective(entity);
            if (rowCount != InlongConstants.AFFECTED_ONE_ROW) {
                LOGGER.error("sink has already updated with groupId={}, streamId={}, name={}, curVersion={}",
                        entity.getInlongGroupId(), entity.getInlongStreamId(), entity.getSinkName(),
                        entity.getVersion());
                throw new BusinessException(ErrorCodeEnum.CONFIG_EXPIRED);
            }
        }

        LOGGER.info("success to update sink after approve: {}", approveList);
        return true;
    }

    @Override
    public List<SinkField> parseFields(ParseFieldRequest parseFieldRequest) {
        try {
            String method = parseFieldRequest.getMethod();
            String statement = parseFieldRequest.getStatement();

            switch (method) {
                case STATEMENT_TYPE_JSON:
                    return parseFieldsByJson(statement);
                case STATEMENT_TYPE_SQL:
                    return parseFieldsBySql(statement);
                case STATEMENT_TYPE_CSV:
                    return parseFieldsByCsv(statement);
                default:
                    throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                            String.format("Unsupported parse mode: %s", method));
            }

        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                    String.format("parse sink fields error: %s", e.getMessage()));
        }
    }

    private List<SinkField> parseFieldsByCsv(String statement) {
        String[] lines = statement.split(InlongConstants.NEW_LINE);
        List<SinkField> fields = new ArrayList<>();
        for (int i = 0; i < lines.length; i++) {
            String line = lines[i];
            if (StringUtils.isBlank(line)) {
                continue;
            }

            String[] cols = PARSE_FIELD_CSV_SPLITTER.split(line, PARSE_FIELD_CSV_MAX_COLUMNS);
            if (cols.length < PARSE_FIELD_CSV_MIN_COLUMNS) {
                throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                        "At least two fields are required, line number is " + (i + 1));
            }
            String fieldName = cols[0];
            if (!PATTERN_NORMAL_CHARACTERS.matcher(fieldName).matches()) {
                throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER, "Field names in line " + (i + 1) +
                        " can only contain letters, underscores or numbers");
            }
            String fieldType = cols[1];

            String comment = null;
            if (cols.length == PARSE_FIELD_CSV_MAX_COLUMNS) {
                comment = cols[PARSE_FIELD_CSV_MAX_COLUMNS - 1];
            }

            SinkField field = new SinkField();
            field.setFieldName(fieldName);
            field.setFieldType(fieldType);
            field.setFieldComment(comment);
            fields.add(field);
        }
        return fields;
    }

    private List<SinkField> parseFieldsBySql(String sql) throws JSQLParserException {
        CCJSqlParserManager pm = new CCJSqlParserManager();
        Statement statement = pm.parse(new StringReader(sql));
        List<SinkField> fields = new ArrayList<>();
        if (!(statement instanceof CreateTable)) {
            throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                    "The SQL statement must be a table creation statement");
        }
        CreateTable createTable = (CreateTable) statement;
        List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();
        // get column definition
        for (ColumnDefinition definition : columnDefinitions) {
            // get field name
            String columnName = definition.getColumnName();
            ColDataType colDataType = definition.getColDataType();
            String sqlDataType = colDataType.getDataType();
            SinkField sinkField = new SinkField();
            sinkField.setFieldName(columnName);
            // get field type
            String realDataType = StringUtils.substringBefore(sqlDataType, LEFT_BRACKET).toLowerCase();
            sinkField.setFieldType(realDataType);
            // get field comment
            List<String> columnSpecs = definition.getColumnSpecs();
            if (CollectionUtils.isNotEmpty(columnSpecs)) {
                int commentIndex = -1;
                for (int csIndex = 0; csIndex < columnSpecs.size(); csIndex++) {
                    String spec = columnSpecs.get(csIndex);
                    if (spec.toUpperCase().startsWith("COMMENT")) {
                        commentIndex = csIndex;
                        break;
                    }
                }
                String comment = null;
                if (-1 != commentIndex && columnSpecs.size() > commentIndex + 1) {
                    comment = columnSpecs.get(commentIndex + 1).replaceAll("['\"]", "");
                }
                sinkField.setFieldComment(comment);
            }

            fields.add(sinkField);
        }
        return fields;
    }

    private List<SinkField> parseFieldsByJson(String statement) throws JsonProcessingException {
        return objectMapper.readValue(statement, new TypeReference<List<Map<String, String>>>() {
        }).stream().map(line -> {
            String name = line.get(BATCH_PARSING_FILED_JSON_NAME_PROP);
            String type = line.get(BATCH_PARSING_FILED_JSON_TYPE_PROP);
            String desc = line.get(BATCH_PARSING_FILED_JSON_COMMENT_PROP);
            SinkField sinkField = new SinkField();
            sinkField.setFieldName(name);
            sinkField.setFieldType(type);
            sinkField.setFieldComment(desc);
            return sinkField;
        }).collect(Collectors.toList());
    }

    private void checkSinkRequestParams(SinkRequest request) {
        // check request parameter
        // check group id
        String groupId = request.getInlongGroupId();
        if (StringUtils.isBlank(groupId)) {
            throw new BusinessException(ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        }
        // check stream id
        String streamId = request.getInlongStreamId();
        if (StringUtils.isBlank(streamId)) {
            throw new BusinessException(ErrorCodeEnum.STREAM_ID_IS_EMPTY);
        }
        // check sinkType
        String sinkType = request.getSinkType();
        if (StringUtils.isBlank(sinkType)) {
            throw new BusinessException(ErrorCodeEnum.SINK_TYPE_IS_NULL);
        }
        // check sinkName
        String sinkName = request.getSinkName();
        if (StringUtils.isBlank(sinkName)) {
            throw new BusinessException(ErrorCodeEnum.SINK_NAME_IS_NULL);
        }
    }

    private void checkParams(SinkRequest request) {
        Preconditions.expectNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
        String groupId = request.getInlongGroupId();
        Preconditions.expectNotBlank(groupId, ErrorCodeEnum.GROUP_ID_IS_EMPTY);
        String streamId = request.getInlongStreamId();
        Preconditions.expectNotBlank(streamId, ErrorCodeEnum.STREAM_ID_IS_EMPTY);
        String sinkType = request.getSinkType();
        Preconditions.expectNotBlank(sinkType, ErrorCodeEnum.SINK_TYPE_IS_NULL);
        String sinkName = request.getSinkName();
        Preconditions.expectNotBlank(sinkName, ErrorCodeEnum.SINK_NAME_IS_NULL);
    }

    private void startProcessForSink(String groupId, String streamId, String operator) {
        // to work around the circular reference check, manually instantiate and wire
        if (streamProcessOperation == null) {
            streamProcessOperation = new InlongStreamProcessService();
            autowireCapableBeanFactory.autowireBean(streamProcessOperation);
        }

        streamProcessOperation.startProcess(groupId, streamId, operator, false);
        LOGGER.info("success to start the start-stream-process for groupId={} streamId={}", groupId, streamId);
    }

    private void deleteProcessForSink(String groupId, String streamId, String operator) {
        // to work around the circular reference check, manually instantiate and wire
        if (streamProcessOperation == null) {
            streamProcessOperation = new InlongStreamProcessService();
            autowireCapableBeanFactory.autowireBean(streamProcessOperation);
        }

        streamProcessOperation.deleteProcess(groupId, streamId, operator, false);
        LOGGER.debug("success to start the delete-stream-process for groupId={} streamId={}", groupId, streamId);
    }

    private void chkUnmodifiableParams(StreamSinkEntity curEntity, SinkRequest request) {
        // check type
        Preconditions.expectEquals(curEntity.getSinkType(), request.getSinkType(),
                ErrorCodeEnum.INVALID_PARAMETER, "sinkType not allowed modify");
        // check record version
        Preconditions.expectEquals(curEntity.getVersion(), request.getVersion(),
                ErrorCodeEnum.CONFIG_EXPIRED,
                String.format("record has expired with record version=%d, request version=%d",
                        curEntity.getVersion(), request.getVersion()));
        if (StringUtils.isNotBlank(request.getInlongGroupId())
                && !curEntity.getInlongGroupId().equals(request.getInlongGroupId())) {
            throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                    "InlongGroupId not allowed modify");
        }
        if (StringUtils.isNotBlank(request.getInlongStreamId())
                && !curEntity.getInlongStreamId().equals(request.getInlongStreamId())) {
            throw new BusinessException(ErrorCodeEnum.INVALID_PARAMETER,
                    "InlongStreamId not allowed modify");
        }
        request.setInlongGroupId(curEntity.getInlongGroupId());
        request.setInlongStreamId(curEntity.getInlongStreamId());
    }
}

## 内容6
### 文件路径：
inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/InlongConsumeController.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.inlong.manager.web.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.inlong.manager.common.enums.OperationType;
import org.apache.inlong.manager.common.enums.UserTypeEnum;
import org.apache.inlong.manager.common.validation.UpdateValidation;
import org.apache.inlong.manager.pojo.common.PageResult;
import org.apache.inlong.manager.pojo.common.Response;
import org.apache.inlong.manager.pojo.consume.InlongConsumeBriefInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumeCountInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumeInfo;
import org.apache.inlong.manager.pojo.consume.InlongConsumePageRequest;
import org.apache.inlong.manager.pojo.consume.InlongConsumeRequest;
import org.apache.inlong.manager.pojo.workflow.WorkflowResult;
import org.apache.inlong.manager.service.consume.InlongConsumeProcessService;
import org.apache.inlong.manager.service.consume.InlongConsumeService;
import org.apache.inlong.manager.service.operationlog.OperationLog;
import org.apache.inlong.manager.service.user.LoginUserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * Inlong consume control layer
 */
@RestController
@RequestMapping("/api")
@Api(tags = "Inlong-Consume-API")
public class InlongConsumeController {

    @Autowired
    private InlongConsumeService consumeService;
    @Autowired
    private InlongConsumeProcessService consumeProcessService;

    @RequestMapping(value = "/consume/save", method = RequestMethod.POST)
    @OperationLog(operation = OperationType.CREATE)
    @ApiOperation(value = "Save inlong consume")
    public Response<Integer> save(@RequestBody InlongConsumeRequest request) {
        String operator = LoginUserUtils.getLoginUser().getName();
        return Response.success(consumeService.save(request, operator));
    }

    @GetMapping("/consume/get/{id}")
    @ApiOperation(value = "Get inlong consume")
    @ApiImplicitParam(name = "id", value = "Inlong consume ID", dataTypeClass = Integer.class, required = true)
    public Response<InlongConsumeInfo> get(@PathVariable(name = "id") Integer id) {
        return Response.success(consumeService.get(id));
    }

    @GetMapping(value = "/consume/countStatus")
    @ApiOperation(value = "Count inlong consume status by current user")
    public Response<InlongConsumeCountInfo> countStatusByUser() {
        return Response.success(consumeService.countStatus(LoginUserUtils.getLoginUser().getName()));
    }

    @GetMapping("/consume/list")
    @ApiOperation(value = "List inlong consume by pagination")
    public Response<PageResult<InlongConsumeBriefInfo>> list(InlongConsumePageRequest request) {
        request.setCurrentUser(LoginUserUtils.getLoginUser().getName());
        request.setIsAdminRole(LoginUserUtils.getLoginUser().getRoles().contains(UserTypeEnum.ADMIN.name()));
        return Response.success(consumeService.list(request));
    }

    @PostMapping("/consume/update")
    @OperationLog(operation = OperationType.UPDATE)
    @ApiOperation(value = "Update inlong consume")
    public Response<Integer> update(@Validated(UpdateValidation.class) @RequestBody InlongConsumeRequest request) {
        return Response.success(consumeService.update(request, LoginUserUtils.getLoginUser().getName()));
    }

    @DeleteMapping("/consume/delete/{id}")
    @OperationLog(operation = OperationType.DELETE)
    @ApiOperation(value = "Delete inlong consume by ID")
    @ApiImplicitParam(name = "id", value = "Inlong consume ID", dataTypeClass = Integer.class, required = true)
    public Response<Boolean> delete(@PathVariable(name = "id") Integer id) {
        return Response.success(consumeService.delete(id, LoginUserUtils.getLoginUser().getName()));
    }

    @PostMapping("/consume/startProcess/{id}")
    @OperationLog(operation = OperationType.UPDATE)
    @ApiOperation(value = "Start inlong consume process")
    @ApiImplicitParam(name = "id", value = "Inlong consume ID", dataTypeClass = Integer.class, required = true)
    public Response<WorkflowResult> startProcess(@PathVariable(name = "id") Integer id) {
        String username = LoginUserUtils.getLoginUser().getName();
        return Response.success(consumeProcessService.startProcess(id, username));
    }

}

## 内容7
### 文件路径：
inlong-manager/manager-web/src/main/java/org/apache/inlong/manager/web/controller/StreamSinkController.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.inlong.manager.web.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.inlong.manager.common.enums.OperationType;
import org.apache.inlong.manager.common.validation.UpdateByIdValidation;
import org.apache.inlong.manager.common.validation.UpdateByKeyValidation;
import org.apache.inlong.manager.pojo.common.PageResult;
import org.apache.inlong.manager.pojo.common.Response;
import org.apache.inlong.manager.pojo.common.UpdateResult;
import org.apache.inlong.manager.pojo.sink.ParseFieldRequest;
import org.apache.inlong.manager.pojo.sink.SinkField;
import org.apache.inlong.manager.pojo.sink.SinkPageRequest;
import org.apache.inlong.manager.pojo.sink.SinkRequest;
import org.apache.inlong.manager.pojo.sink.StreamSink;
import org.apache.inlong.manager.service.operationlog.OperationLog;
import org.apache.inlong.manager.service.sink.StreamSinkService;
import org.apache.inlong.manager.service.user.LoginUserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * Stream sink control layer
 */
@RestController
@RequestMapping("/api")
@Api(tags = "Stream-Sink-API")
public class StreamSinkController {

    @Autowired
    private StreamSinkService sinkService;

    @RequestMapping(value = "/sink/save", method = RequestMethod.POST)
    @OperationLog(operation = OperationType.CREATE)
    @ApiOperation(value = "Save stream sink")
    public Response<Integer> save(@Validated @RequestBody SinkRequest request) {
        return Response.success(sinkService.save(request, LoginUserUtils.getLoginUser().getName()));
    }

    @RequestMapping(value = "/sink/get/{id}", method = RequestMethod.GET)
    @ApiOperation(value = "Get stream sink")
    @ApiImplicitParam(name = "id", dataTypeClass = Integer.class, required = true)
    public Response<StreamSink> get(@PathVariable Integer id) {
        return Response.success(sinkService.get(id, LoginUserUtils.getLoginUser()));
    }

    @RequestMapping(value = "/sink/list", method = RequestMethod.POST)
    @ApiOperation(value = "List stream sinks by paginating")
    public Response<PageResult<? extends StreamSink>> listByCondition(@RequestBody SinkPageRequest request) {
        return Response.success(sinkService.listByCondition(request));
    }

    @RequestMapping(value = "/sink/update", method = RequestMethod.POST)
    @OperationLog(operation = OperationType.UPDATE)
    @ApiOperation(value = "Update stream sink")
    public Response<Boolean> update(@Validated(UpdateByIdValidation.class) @RequestBody SinkRequest request) {
        return Response.success(sinkService.update(request, LoginUserUtils.getLoginUser().getName()));
    }

    @RequestMapping(value = "/sink/updateByKey", method = RequestMethod.POST)
    @OperationLog(operation = OperationType.UPDATE)
    @ApiOperation(value = "Update stream sink by key")
    public Response<UpdateResult> updateByKey(
            @Validated(UpdateByKeyValidation.class) @RequestBody SinkRequest request) {
        return Response.success(sinkService.updateByKey(request, LoginUserUtils.getLoginUser().getName()));
    }

    @RequestMapping(value = "/sink/delete/{id}", method = RequestMethod.DELETE)
    @OperationLog(operation = OperationType.DELETE)
    @ApiOperation(value = "Delete stream sink")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startProcess", dataTypeClass = boolean.class),
            @ApiImplicitParam(name = "id", dataTypeClass = Integer.class, required = true)
    })
    public Response<Boolean> delete(@PathVariable Integer id,
            @RequestParam(required = false, defaultValue = "false") boolean startProcess) {
        return Response.success(sinkService.delete(id, startProcess, LoginUserUtils.getLoginUser().getName()));
    }

    @RequestMapping(value = "/sink/deleteByKey", method = RequestMethod.DELETE)
    @OperationLog(operation = OperationType.DELETE)
    @ApiOperation(value = "Delete stream sink by key")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startProcess", dataTypeClass = boolean.class),
            @ApiImplicitParam(name = "groupId", dataTypeClass = String.class, required = true),
            @ApiImplicitParam(name = "streamId", dataTypeClass = String.class, required = true),
            @ApiImplicitParam(name = "name", dataTypeClass = String.class, required = true)
    })
    public Response<Boolean> deleteByKey(@RequestParam(required = false, defaultValue = "false") boolean startProcess,
            @RequestParam String groupId, @RequestParam String streamId, @RequestParam String name) {
        String username = LoginUserUtils.getLoginUser().getName();
        return Response.success(sinkService.deleteByKey(groupId, streamId, name, startProcess, username));
    }

    @RequestMapping(value = "/sink/parseFields", method = RequestMethod.POST)
    @ApiOperation(value = "parse stream sink fields from statement")
    public Response<List<SinkField>> parseFields(@RequestBody ParseFieldRequest parseFieldRequest) {
        return Response.success(sinkService.parseFields(parseFieldRequest));
    }

}

Output:
【漏洞类型】权限检查缺失
【严重性】Medium
【漏洞摘要】原始代码在获取、更新和删除InlongConsume和StreamSink信息时，缺少对当前用户的权限检查。具体表现为`InlongConsumeService`和`StreamSinkService`接口中没有包含当前用户的参数，导致任何用户都可以对这些资源进行操作，而不需要进行权限验证。
【关键代码模式】
- `InlongConsumeService.get(Integer id)`
- `InlongConsumeServiceImpl.get(Integer id)`
- `StreamSinkService.listByCondition(SinkPageRequest request)`
- `StreamSinkServiceImpl.listByCondition(SinkPageRequest request)`
【修复方法说明】修复方法通过在相关接口和实现类中添加当前用户的参数，并在获取、更新和删除操作中进行权限检查，确保只有具备相应权限的用户才能对资源进行操作。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
src-gwt/org/opencms/ade/galleries/client/ui/CmsResultItemWidget.java
### 代码内容：
package org.opencms.ade.galleries.client.ui;

import org.opencms.ade.galleries.client.ui.css.I_CmsLayoutBundle;
import org.opencms.ade.galleries.shared.CmsResultItemBean;
import org.opencms.gwt.client.CmsCoreProvider;
import org.opencms.gwt.client.dnd.I_CmsDragHandle;
import org.opencms.gwt.client.dnd.I_CmsDraggable;
import org.opencms.gwt.client.ui.CmsListItemWidget;
import org.opencms.gwt.client.ui.input.CmsLabel.I_TitleGenerator;
import org.opencms.gwt.client.util.CmsClientStringUtil;
import org.opencms.gwt.client.util.CmsToolTipHandler;
import org.opencms.gwt.shared.CmsAdditionalInfoBean;
import org.opencms.gwt.shared.CmsListInfoBean;

import com.google.gwt.user.client.ui.HTML;

/**
 * The result list item widget.

 *
 * Enabling the image tile view.

 *
 * @since 8.0.0
 */
public class CmsResultItemWidget extends CmsListItemWidget {

    /**
     * Widget containing the image(s) for a result list item..

     */
    public class ImageTile extends HTML implements I_CmsDragHandle {

        /** The draggable result list item. */
        private I_CmsDraggable m_draggable;

        /**
         * Creates a new instance with the given content.

         *
         * @param content the HTML content
         */
        public ImageTile(String content) {

            super(content);
        }

        /**
         * @see org.opencms.gwt.client.dnd.I_CmsDragHandle#getDraggable()
         */
        public I_CmsDraggable getDraggable() {

            return m_draggable;
        }

        /**
         * Sets the draggable widget.

         *
         * @param draggable the draggable widget
         */
        public void setDraggable(I_CmsDraggable draggable) {

            m_draggable = draggable;
        }

    }

    /** Standard image tile scale parameter. */
    private static final String IMAGE_SCALE_PARAM = "?__scale=t:1,c:ffffff,r:0";

    /** Tile view flag. */
    private boolean m_hasTileView;

    /** The image tile. */
    private ImageTile m_imageTile;

    /** The tool tip handler. */
    private CmsToolTipHandler m_tooltipHandler;

    /**
     * Constructor.

     *
     * @param infoBean the resource info bean
     * @param showPath true to show the resource path in sub title
     */
    public CmsResultItemWidget(CmsResultItemBean infoBean, boolean showPath) {

        super(infoBean);
        if (showPath) {
            setSubtitleLabel(infoBean.getPath());
            setSubtitleTitle(infoBean.getSubTitle());
        } else {
            setSubtitleTitle(infoBean.getPath());
        }

        // if resourceType=="image" prepare for tile view
        if (CmsResultsTab.isImagelikeType(infoBean.getType())) {
            m_hasTileView = true;
            // add tile view marker css classes
            String src = infoBean.getViewLink();
            if (src == null) {
                src = CmsCoreProvider.get().link(infoBean.getPath());
            }
            String timeParam = "&time=" + System.currentTimeMillis();
            // insert tile view image div
            ImageTile imageTile = new ImageTile(""
                // using a second image tag for the small thumbnail variant
                + ""
                + "
");
            imageTile.setStyleName(I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().imageTile());
            if (CmsClientStringUtil.checkIsPathOrLinkToSvg(infoBean.getPath())) {
                imageTile.addStyleName(I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().svg());
            }
            m_imageTile = imageTile;
            m_tooltipHandler = new CmsToolTipHandler(imageTile, generateTooltipHtml(infoBean));
            m_contentPanel.insert(imageTile, 0);
        }

    }

    /**
     * Gets the image tile.

     *
     * @return the image tile
     */
    public ImageTile getImageTile() {

        return m_imageTile;
    }

    /**
     * Indicates wther there is a tile view available for this widget.

     *
     * @return true if a tiled view is available
     */
    public boolean hasTileView() {

        return m_hasTileView;
    }

    /**
     * Initializes the title attribute of the subtitle line.

     *
     * @param subtitleTitle the value to set
     */
    public void setSubtitleTitle(final String subtitleTitle) {

        m_subtitle.setTitle(subtitleTitle);
        m_subtitle.setTitleGenerator(new I_TitleGenerator() {

            public String getTitle(String originalText) {

                return subtitleTitle;
            }
        });
    }

    /**
     * @see com.google.gwt.user.client.ui.Composite#onDetach()
     */
    @Override
    protected void onDetach() {

        if (m_tooltipHandler != null) {
            m_tooltipHandler.clearShowing();
        }
        super.onDetach();
    }

    /**
     * Generates the HTML for the item tool-tip.

     *
     * @param infoBean the item info
     *
     * @return the generated HTML
     */
    private String generateTooltipHtml(CmsListInfoBean infoBean) {

        StringBuffer result = new StringBuffer();
        result.append("
").append(CmsClientStringUtil.shortenString(infoBean.getTitle(), 70)).append("
");
        if (infoBean.hasAdditionalInfo()) {
            for (CmsAdditionalInfoBean additionalInfo : infoBean.getAdditionalInfo()) {
                result.append("
").append(additionalInfo.getName()).append(": ");
                // shorten the value to max 45 characters
                result.append(CmsClientStringUtil.shortenString(additionalInfo.getValue(), 45)).append("
");
            }
        }
        return result.toString();
    }

    /**
     * Returns the scale parameter for big thumbnail images.

     *
     * @return the scale parameter
     */
    private String getBigImageScaleParam() {

        return IMAGE_SCALE_PARAM
            + ",w:"
            + I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().bigImageWidth()
            + ",h:"
            + I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().bigImageHeight();
    }

    /**
     * Returns the scale parameter for small thumbnail images.

     *
     * @param infoBean the resource info
     *
     * @return the scale parameter
     */
    private String getSmallImageScaleParam(CmsResultItemBean infoBean) {

        String result = null;
        if (infoBean.getDimension() != null) {
            String[] sizes = infoBean.getDimension().split("x");
            try {
                int width = Integer.parseInt(sizes[0].trim());
                int height = Integer.parseInt(sizes[1].trim());
                // only use the small image dimensions in case of dimensions smaller than the big thumbnail
                if ((I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().bigImageWidth() > width)
                    || (I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().bigImageHeight() > height)) {
                    result = IMAGE_SCALE_PARAM
                        + ",w:"
                        + I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().smallImageWidth()
                        + ",h:"
                        + I_CmsLayoutBundle.INSTANCE.galleryResultItemCss().smallImageHeight();
                }
            } catch (Exception e) {
                // failed parsing the dimensions, will use big image
            }
        }
        if (result == null) {
            result = getBigImageScaleParam();
        }
        return result;
    }
}

Output:
【漏洞类型】跨站脚本（XSS）漏洞
【严重性】High
【漏洞摘要】在生成工具提示的HTML内容时，未对用户输入或可能包含HTML的字段进行适当的转义。具体表现为在`generateTooltipHtml`函数中，直接将`infoBean.getTitle()`和`additionalInfo.getValue()`插入到HTML字符串中，而没有对他们进行HTML转义。这可能导致攻击者通过注入恶意代码（如`<script>`标签）来执行脚本，从而在用户浏览器中执行任意JavaScript代码。
【关键代码模式】`generateTooltipHtml`函数中的字符串拼接，特别是涉及到`infoBean.getTitle()`和`additionalInfo.getValue()`的拼接操作。
【修复方法说明】修复方法通过使用GWT的DOM API来创建HTML元素，并使用`setInnerText`方法来插入文本内容，从而自动进行HTML转义。这种方法确保了用户输入的内容不会被解释为HTML代码，从而防止了XSS攻击。