/* * 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.nifi.web.dao.impl; import org.apache.nifi.connectable.Port; import org.apache.nifi.connectable.Position; import org.apache.nifi.controller.FlowController; import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.controller.exception.ValidationException; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.web.NiFiCoreException; import org.apache.nifi.web.ResourceNotFoundException; import org.apache.nifi.web.api.dto.PortDTO; import org.apache.nifi.web.dao.PortDAO; import java.util.ArrayList; import java.util.List; import java.util.Set; public class StandardInputPortDAO extends ComponentDAO implements PortDAO { private FlowController flowController; private Port locatePort(final String portId) { final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId()); final Port port = rootGroup.findInputPort(portId); if (port == null) { throw new ResourceNotFoundException(String.format("Unable to find port with id '%s'.", portId)); } else { return port; } } @Override public boolean hasPort(String portId) { final ProcessGroup rootGroup = flowController.getGroup(flowController.getRootGroupId()); return rootGroup.findInputPort(portId) != null; } @Override public Port createPort(String groupId, PortDTO portDTO) { if (isNotNull(portDTO.getParentGroupId()) && !flowController.areGroupsSame(groupId, portDTO.getParentGroupId())) { throw new IllegalArgumentException("Cannot specify a different Parent Group ID than the Group to which the InputPort is being added."); } // ensure the name has been specified if (portDTO.getName() == null) { throw new IllegalArgumentException("Port name must be specified."); } // get the desired group ProcessGroup group = locateProcessGroup(flowController, groupId); // determine if this is the root group Port port; if (group.getParent() == null) { port = flowController.createRemoteInputPort(portDTO.getId(), portDTO.getName()); } else { port = flowController.createLocalInputPort(portDTO.getId(), portDTO.getName()); } // ensure we can perform the update before we add the processor to the flow verifyUpdate(port, portDTO); // configure if (portDTO.getPosition() != null) { port.setPosition(new Position(portDTO.getPosition().getX(), portDTO.getPosition().getY())); } port.setComments(portDTO.getComments()); // add the port group.addInputPort(port); return port; } @Override public Port getPort(String portId) { return locatePort(portId); } @Override public Set<Port> getPorts(String groupId) { ProcessGroup group = locateProcessGroup(flowController, groupId); return group.getInputPorts(); } @Override public void verifyUpdate(PortDTO portDTO) { final Port inputPort = locatePort(portDTO.getId()); verifyUpdate(inputPort, portDTO); } private void verifyUpdate(final Port inputPort, final PortDTO portDTO) { if (isNotNull(portDTO.getState())) { final ScheduledState purposedScheduledState = ScheduledState.valueOf(portDTO.getState()); // only attempt an action if it is changing if (!purposedScheduledState.equals(inputPort.getScheduledState())) { // perform the appropriate action switch (purposedScheduledState) { case RUNNING: inputPort.verifyCanStart(); break; case STOPPED: switch (inputPort.getScheduledState()) { case RUNNING: inputPort.verifyCanStop(); break; case DISABLED: inputPort.verifyCanEnable(); break; } break; case DISABLED: inputPort.verifyCanDisable(); break; } } } // see what's be modified if (isAnyNotNull(portDTO.getUserAccessControl(), portDTO.getGroupAccessControl(), portDTO.getConcurrentlySchedulableTaskCount(), portDTO.getName(), portDTO.getComments())) { // validate the request final List<String> requestValidation = validateProposedConfiguration(portDTO); // ensure there was no validation errors if (!requestValidation.isEmpty()) { throw new ValidationException(requestValidation); } // ensure the port can be updated inputPort.verifyCanUpdate(); } } private List<String> validateProposedConfiguration(PortDTO portDTO) { List<String> validationErrors = new ArrayList<>(); if (isNotNull(portDTO.getName()) && portDTO.getName().trim().isEmpty()) { validationErrors.add("Port name cannot be blank."); } if (isNotNull(portDTO.getConcurrentlySchedulableTaskCount()) && portDTO.getConcurrentlySchedulableTaskCount() <= 0) { validationErrors.add("Concurrent tasks must be a positive integer."); } return validationErrors; } @Override public Port updatePort(PortDTO portDTO) { Port inputPort = locatePort(portDTO.getId()); // ensure we can do this update verifyUpdate(inputPort, portDTO); // handle state transition if (isNotNull(portDTO.getState())) { final ScheduledState purposedScheduledState = ScheduledState.valueOf(portDTO.getState()); // only attempt an action if it is changing if (!purposedScheduledState.equals(inputPort.getScheduledState())) { try { // perform the appropriate action switch (purposedScheduledState) { case RUNNING: inputPort.getProcessGroup().startInputPort(inputPort); break; case STOPPED: switch (inputPort.getScheduledState()) { case RUNNING: inputPort.getProcessGroup().stopInputPort(inputPort); break; case DISABLED: inputPort.getProcessGroup().enableInputPort(inputPort); break; } break; case DISABLED: inputPort.getProcessGroup().disableInputPort(inputPort); break; } } catch (IllegalStateException ise) { throw new NiFiCoreException(ise.getMessage(), ise); } } } if (inputPort instanceof RootGroupPort) { final RootGroupPort rootPort = (RootGroupPort) inputPort; if (isNotNull(portDTO.getGroupAccessControl())) { rootPort.setGroupAccessControl(portDTO.getGroupAccessControl()); } if (isNotNull(portDTO.getUserAccessControl())) { rootPort.setUserAccessControl(portDTO.getUserAccessControl()); } } // update the port final String name = portDTO.getName(); final String comments = portDTO.getComments(); final Integer concurrentTasks = portDTO.getConcurrentlySchedulableTaskCount(); if (isNotNull(portDTO.getPosition())) { inputPort.setPosition(new Position(portDTO.getPosition().getX(), portDTO.getPosition().getY())); } if (isNotNull(name)) { inputPort.setName(name); } if (isNotNull(comments)) { inputPort.setComments(comments); } if (isNotNull(concurrentTasks)) { inputPort.setMaxConcurrentTasks(concurrentTasks); } return inputPort; } @Override public void verifyDelete(final String portId) { final Port inputPort = locatePort(portId); inputPort.verifyCanDelete(); } @Override public void deletePort(final String portId) { final Port inputPort = locatePort(portId); inputPort.getProcessGroup().removeInputPort(inputPort); } /* setters */ public void setFlowController(FlowController flowController) { this.flowController = flowController; } }