org.springframework.cloud.dataflow.server.service.impl.AbstractStreamService.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.cloud.dataflow.server.service.impl.AbstractStreamService.java

Source

/*
 * Copyright 2017 the original author or authors.
 *
 * Licensed 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.springframework.cloud.dataflow.server.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.cloud.dataflow.core.ApplicationType;
import org.springframework.cloud.dataflow.core.StreamAppDefinition;
import org.springframework.cloud.dataflow.core.StreamDefinition;
import org.springframework.cloud.dataflow.core.dsl.ParseException;
import org.springframework.cloud.dataflow.core.dsl.StreamNode;
import org.springframework.cloud.dataflow.core.dsl.StreamParser;
import org.springframework.cloud.dataflow.registry.AppRegistryCommon;
import org.springframework.cloud.dataflow.server.DataFlowServerUtil;
import org.springframework.cloud.dataflow.server.controller.StreamAlreadyDeployedException;
import org.springframework.cloud.dataflow.server.controller.StreamAlreadyDeployingException;
import org.springframework.cloud.dataflow.server.controller.support.InvalidStreamDefinitionException;
import org.springframework.cloud.dataflow.server.repository.NoSuchStreamDefinitionException;
import org.springframework.cloud.dataflow.server.repository.StreamDefinitionRepository;
import org.springframework.cloud.dataflow.server.repository.support.SearchPageable;
import org.springframework.cloud.dataflow.server.service.StreamService;
import org.springframework.cloud.dataflow.server.stream.StreamDeploymentRequest;
import org.springframework.cloud.dataflow.server.support.CannotDetermineApplicationTypeException;
import org.springframework.cloud.deployer.spi.app.DeploymentState;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * Performs manipulation on application and deployment properties, expanding shorthand
 * application property values, resolving wildcard deployment properties, and creates a
 * {@link StreamDeploymentRequest}.
 * </p>
 * The {@link AbstractStreamService} deployer is agnostic. For deploying streams on
 * Skipper use the {@link DefaultSkipperStreamService} and for the AppDeploy stream
 * deployment use the {@link AppDeployerStreamService}.
 * </p>
 *
 * @author Mark Pollack
 * @author Ilayaperumal Gopinathan
 * @author Christian Tzolov
 */
@Transactional
public abstract class AbstractStreamService implements StreamService {

    private static Log logger = LogFactory.getLog(AbstractStreamService.class);

    /**
     * The repository this controller will use for stream CRUD operations.
     */
    protected final StreamDefinitionRepository streamDefinitionRepository;

    /**
     * The app registry this controller will use to lookup apps.
     */
    private final AppRegistryCommon appRegistry;

    /**
     * Constructor for implementations of the {@link StreamService}.
     * @param streamDefinitionRepository the stream definition repository to use
     * @param appRegistry the application registry to use
     */
    public AbstractStreamService(StreamDefinitionRepository streamDefinitionRepository,
            AppRegistryCommon appRegistry) {
        Assert.notNull(streamDefinitionRepository, "StreamDefinitionRepository must not be null");
        Assert.notNull(appRegistry, "AppRegistryCommon must not be null");
        this.streamDefinitionRepository = streamDefinitionRepository;
        this.appRegistry = appRegistry;
    }

    public StreamDefinition createStream(String streamName, String dsl, boolean deploy) {
        StreamDefinition streamDefinition = createStreamDefinition(streamName, dsl);

        List<String> errorMessages = new ArrayList<>();

        for (StreamAppDefinition streamAppDefinition : streamDefinition.getAppDefinitions()) {
            final String appName = streamAppDefinition.getRegisteredAppName();
            try {
                final ApplicationType appType = DataFlowServerUtil.determineApplicationType(streamAppDefinition);
                if (!appRegistry.appExist(appName, appType)) {
                    errorMessages.add(String.format(
                            "Application name '%s' with type '%s' does not exist in the app registry.", appName,
                            appType));
                }
            } catch (CannotDetermineApplicationTypeException e) {
                errorMessages.add(String.format("Cannot determine application type for application '%s': %s",
                        appName, e.getMessage()));
                continue;
            }
        }

        if (!errorMessages.isEmpty()) {
            throw new InvalidStreamDefinitionException(
                    StringUtils.collectionToDelimitedString(errorMessages, "\n"));
        }

        this.streamDefinitionRepository.save(streamDefinition);
        if (deploy) {
            this.deployStream(streamName, new HashMap<>());
        }

        return streamDefinition;
    }

    private StreamDefinition createStreamDefinition(String streamName, String dsl) {
        try {
            return new StreamDefinition(streamName, dsl);
        } catch (ParseException ex) {
            throw new InvalidStreamDefinitionException(ex.getMessage());
        }
    }

    @Override
    public void deployStream(String name, Map<String, String> deploymentProperties) {
        if (deploymentProperties == null) {
            deploymentProperties = new HashMap<>();
        }
        StreamDefinition streamDefinition = this.streamDefinitionRepository.findOne(name);
        if (streamDefinition == null) {
            throw new NoSuchStreamDefinitionException(name);
        }

        DeploymentState status = this.doCalculateStreamState(name);

        if (DeploymentState.deployed == status) {
            throw new StreamAlreadyDeployedException(name);
        } else if (DeploymentState.deploying == status) {
            throw new StreamAlreadyDeployingException(name);
        }
        doDeployStream(streamDefinition, deploymentProperties);
    }

    protected abstract void doDeployStream(StreamDefinition streamDefinition,
            Map<String, String> deploymentProperties);

    protected abstract DeploymentState doCalculateStreamState(String name);

    @Override
    public void deleteStream(String name) {
        if (this.streamDefinitionRepository.findOne(name) == null) {
            throw new NoSuchStreamDefinitionException(name);
        }
        this.undeployStream(name);
        this.streamDefinitionRepository.delete(name);
    }

    @Override
    public void deleteAll() {
        for (StreamDefinition streamDefinition : this.streamDefinitionRepository.findAll()) {
            this.undeployStream(streamDefinition.getName());
        }
        this.streamDefinitionRepository.deleteAll();
    }

    @Override
    public List<StreamDefinition> findRelatedStreams(String name, boolean nested) {
        Set<StreamDefinition> relatedDefinitions = new LinkedHashSet<>();
        StreamDefinition currentStreamDefinition = streamDefinitionRepository.findOne(name);
        if (currentStreamDefinition == null) {
            throw new NoSuchStreamDefinitionException(name);
        }
        Iterable<StreamDefinition> definitions = streamDefinitionRepository.findAll();
        List<StreamDefinition> result = new ArrayList<>(
                findRelatedDefinitions(currentStreamDefinition, definitions, relatedDefinitions, nested));
        return result;
    }

    private Set<StreamDefinition> findRelatedDefinitions(StreamDefinition currentStreamDefinition,
            Iterable<StreamDefinition> definitions, Set<StreamDefinition> relatedDefinitions, boolean nested) {
        relatedDefinitions.add(currentStreamDefinition);
        String currentStreamName = currentStreamDefinition.getName();
        String indexedStreamName = currentStreamName + ".";
        for (StreamDefinition definition : definitions) {
            StreamNode sn = new StreamParser(definition.getName(), definition.getDslText()).parse();
            if (sn.getSourceDestinationNode() != null) {
                String nameComponent = sn.getSourceDestinationNode().getDestinationName();
                if (nameComponent.equals(currentStreamName) || nameComponent.startsWith(indexedStreamName)) {
                    boolean isNewEntry = relatedDefinitions.add(definition);
                    if (nested && isNewEntry) {
                        findRelatedDefinitions(definition, definitions, relatedDefinitions, true);
                    }
                }
            }
        }
        return relatedDefinitions;
    }

    @Override
    public Page<StreamDefinition> findDefinitionByNameLike(Pageable pageable, String search) {
        Page<StreamDefinition> streamDefinitions;
        if (search != null) {
            final SearchPageable searchPageable = new SearchPageable(pageable, search);
            searchPageable.addColumns("DEFINITION_NAME", "DEFINITION");
            streamDefinitions = streamDefinitionRepository.findByNameLike(searchPageable);
            long count = streamDefinitions.getContent().size();
            long to = Math.min(count, pageable.getOffset() + pageable.getPageSize());
            streamDefinitions = new PageImpl<>(streamDefinitions.getContent(), pageable,
                    streamDefinitions.getTotalElements());
        } else {
            streamDefinitions = streamDefinitionRepository.findAll(pageable);
        }
        return streamDefinitions;
    }

    @Override
    public StreamDefinition findOne(String streamDefinitionName) {
        StreamDefinition definition = streamDefinitionRepository.findOne(streamDefinitionName);
        if (definition == null) {
            throw new NoSuchStreamDefinitionException(streamDefinitionName);
        }
        return definition;
    }
}