You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2015/04/10 15:43:47 UTC
[12/62] [abbrv] incubator-nifi git commit: Squashed commit of the
following:
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
new file mode 100644
index 0000000..38ddc36
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ReportingTaskResource.java
@@ -0,0 +1,663 @@
+/*
+ * 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.api;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import org.apache.nifi.cluster.manager.impl.WebClusterManager;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.ConfigurationSnapshot;
+import org.apache.nifi.web.NiFiServiceFacade;
+import org.apache.nifi.web.Revision;
+import org.apache.nifi.web.api.dto.RevisionDTO;
+import org.apache.nifi.web.api.request.ClientIdParameter;
+import org.apache.nifi.web.api.request.LongParameter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.ui.extension.UiExtension;
+import org.apache.nifi.ui.extension.UiExtensionMapping;
+import org.apache.nifi.web.UiExtensionType;
+import static org.apache.nifi.web.api.ApplicationResource.CLIENT_ID;
+import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
+import org.apache.nifi.web.api.dto.ReportingTaskDTO;
+import org.apache.nifi.web.api.entity.PropertyDescriptorEntity;
+import org.apache.nifi.web.api.entity.ReportingTaskEntity;
+import org.apache.nifi.web.api.entity.ReportingTasksEntity;
+import org.apache.nifi.web.util.Availability;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+
+/**
+ * RESTful endpoint for managing a Reporting Task.
+ */
+public class ReportingTaskResource extends ApplicationResource {
+
+ private static final Logger logger = LoggerFactory.getLogger(ReportingTaskResource.class);
+
+ private NiFiServiceFacade serviceFacade;
+ private WebClusterManager clusterManager;
+ private NiFiProperties properties;
+
+ @Context
+ private ServletContext servletContext;
+
+ /**
+ * Populates the uri for the specified reporting task.
+ *
+ * @param reportingTasks
+ * @return
+ */
+ private Set<ReportingTaskDTO> populateRemainingReportingTasksContent(final String availability, final Set<ReportingTaskDTO> reportingTasks) {
+ for (ReportingTaskDTO reportingTask : reportingTasks) {
+ populateRemainingReportingTaskContent(availability, reportingTask);
+ }
+ return reportingTasks;
+ }
+
+ /**
+ * Populates the uri for the specified reporting task.
+ */
+ private ReportingTaskDTO populateRemainingReportingTaskContent(final String availability, final ReportingTaskDTO reportingTask) {
+ // populate the reporting task href
+ reportingTask.setUri(generateResourceUri("controller", "reporting-tasks", availability, reportingTask.getId()));
+ reportingTask.setAvailability(availability);
+
+ // see if this processor has any ui extensions
+ final UiExtensionMapping uiExtensionMapping = (UiExtensionMapping) servletContext.getAttribute("nifi-ui-extensions");
+ if (uiExtensionMapping.hasUiExtension(reportingTask.getType())) {
+ final List<UiExtension> uiExtensions = uiExtensionMapping.getUiExtension(reportingTask.getType());
+ for (final UiExtension uiExtension : uiExtensions) {
+ if (UiExtensionType.ReportingTaskConfiguration.equals(uiExtension.getExtensionType())) {
+ reportingTask.setCustomUiUrl(uiExtension.getContextPath() + "/configure");
+ }
+ }
+ }
+
+ return reportingTask;
+ }
+
+ /**
+ * Parses the availability and ensure that the specified availability makes sense for the
+ * given NiFi instance.
+ *
+ * @param availability
+ * @return
+ */
+ private Availability parseAvailability(final String availability) {
+ final Availability avail;
+ try {
+ avail = Availability.valueOf(availability.toUpperCase());
+ } catch (IllegalArgumentException iae) {
+ throw new IllegalArgumentException(String.format("Availability: Value must be one of [%s]", StringUtils.join(Availability.values(), ", ")));
+ }
+
+ // ensure this nifi is an NCM is specifying NCM availability
+ if (!properties.isClusterManager() && Availability.NCM.equals(avail)) {
+ throw new IllegalArgumentException("Availability of NCM is only applicable when the NiFi instance is the cluster manager.");
+ }
+
+ return avail;
+ }
+
+ /**
+ * Retrieves all the of reporting tasks in this NiFi.
+ *
+ * @param clientId Optional client id. If the client id is not specified, a
+ * new one will be generated. This value (whether specified or generated) is
+ * included in the response.
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @return A reportingTasksEntity.
+ */
+ @GET
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}")
+ @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+ @TypeHint(ReportingTasksEntity.class)
+ public Response getReportingTasks(@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId, @PathParam("availability") String availability) {
+ final Availability avail = parseAvailability(availability);
+
+ // replicate if cluster manager
+ if (properties.isClusterManager() && Availability.NODE.equals(avail)) {
+ return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse();
+ }
+
+ // get all the reporting tasks
+ final Set<ReportingTaskDTO> reportingTasks = populateRemainingReportingTasksContent(availability, serviceFacade.getReportingTasks());
+
+ // create the revision
+ final RevisionDTO revision = new RevisionDTO();
+ revision.setClientId(clientId.getClientId());
+
+ // create the response entity
+ final ReportingTasksEntity entity = new ReportingTasksEntity();
+ entity.setRevision(revision);
+ entity.setReportingTasks(reportingTasks);
+
+ // generate the response
+ return clusterContext(generateOkResponse(entity)).build();
+ }
+
+ /**
+ * Creates a new reporting task.
+ *
+ * @param httpServletRequest
+ * @param version The revision is used to verify the client is working with
+ * the latest version of the flow.
+ * @param clientId Optional client id. If the client id is not specified, a
+ * new one will be generated. This value (whether specified or generated) is
+ * included in the response.
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @param type The type of reporting task to create.
+ * @return A reportingTaskEntity.
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}")
+ @PreAuthorize("hasRole('ROLE_DFM')")
+ @TypeHint(ReportingTaskEntity.class)
+ public Response createReportingTask(
+ @Context HttpServletRequest httpServletRequest,
+ @FormParam(VERSION) LongParameter version,
+ @FormParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId,
+ @PathParam("availability") String availability,
+ @FormParam("type") String type) {
+
+ // create the reporting task DTO
+ final ReportingTaskDTO reportingTaskDTO = new ReportingTaskDTO();
+ reportingTaskDTO.setType(type);
+
+ // create the revision
+ final RevisionDTO revision = new RevisionDTO();
+ revision.setClientId(clientId.getClientId());
+ if (version != null) {
+ revision.setVersion(version.getLong());
+ }
+
+ // create the reporting task entity
+ final ReportingTaskEntity reportingTaskEntity = new ReportingTaskEntity();
+ reportingTaskEntity.setRevision(revision);
+ reportingTaskEntity.setReportingTask(reportingTaskDTO);
+
+ return createReportingTask(httpServletRequest, availability, reportingTaskEntity);
+ }
+
+ /**
+ * Creates a new Reporting Task.
+ *
+ * @param httpServletRequest
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @param reportingTaskEntity A reportingTaskEntity.
+ * @return A reportingTaskEntity.
+ */
+ @POST
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}")
+ @PreAuthorize("hasRole('ROLE_DFM')")
+ @TypeHint(ReportingTaskEntity.class)
+ public Response createReportingTask(
+ @Context HttpServletRequest httpServletRequest,
+ @PathParam("availability") String availability,
+ ReportingTaskEntity reportingTaskEntity) {
+
+ final Availability avail = parseAvailability(availability);
+
+ if (reportingTaskEntity == null || reportingTaskEntity.getReportingTask()== null) {
+ throw new IllegalArgumentException("Reporting task details must be specified.");
+ }
+
+ if (reportingTaskEntity.getRevision() == null) {
+ throw new IllegalArgumentException("Revision must be specified.");
+ }
+
+ if (reportingTaskEntity.getReportingTask().getId() != null) {
+ throw new IllegalArgumentException("Reporting task ID cannot be specified.");
+ }
+
+ if (StringUtils.isBlank(reportingTaskEntity.getReportingTask().getType())) {
+ throw new IllegalArgumentException("The type of reporting task to create must be specified.");
+ }
+
+ // get the revision
+ final RevisionDTO revision = reportingTaskEntity.getRevision();
+
+ // if cluster manager, convert POST to PUT (to maintain same ID across nodes) and replicate
+ if (properties.isClusterManager() && Availability.NODE.equals(avail)) {
+ // create ID for resource
+ final String id = UUID.randomUUID().toString();
+
+ // set ID for resource
+ reportingTaskEntity.getReportingTask().setId(id);
+
+ // convert POST request to PUT request to force entity ID to be the same across nodes
+ URI putUri = null;
+ try {
+ putUri = new URI(getAbsolutePath().toString() + "/" + id);
+ } catch (final URISyntaxException e) {
+ throw new WebApplicationException(e);
+ }
+
+ // change content type to JSON for serializing entity
+ final Map<String, String> headersToOverride = new HashMap<>();
+ headersToOverride.put("content-type", MediaType.APPLICATION_JSON);
+
+ // replicate put request
+ return (Response) clusterManager.applyRequest(HttpMethod.PUT, putUri, updateClientId(reportingTaskEntity), getHeaders(headersToOverride)).getResponse();
+ }
+
+ // handle expects request (usually from the cluster manager)
+ final String expects = httpServletRequest.getHeader(WebClusterManager.NCM_EXPECTS_HTTP_HEADER);
+ if (expects != null) {
+ return generateContinueResponse().build();
+ }
+
+ // create the reporting task and generate the json
+ final ConfigurationSnapshot<ReportingTaskDTO> controllerResponse = serviceFacade.createReportingTask(
+ new Revision(revision.getVersion(), revision.getClientId()), reportingTaskEntity.getReportingTask());
+ final ReportingTaskDTO reportingTask = controllerResponse.getConfiguration();
+
+ // get the updated revision
+ final RevisionDTO updatedRevision = new RevisionDTO();
+ updatedRevision.setClientId(revision.getClientId());
+ updatedRevision.setVersion(controllerResponse.getVersion());
+
+ // build the response entity
+ final ReportingTaskEntity entity = new ReportingTaskEntity();
+ entity.setRevision(updatedRevision);
+ entity.setReportingTask(populateRemainingReportingTaskContent(availability, reportingTask));
+
+ // build the response
+ return clusterContext(generateCreatedResponse(URI.create(reportingTask.getUri()), entity)).build();
+ }
+
+ /**
+ * Retrieves the specified reporting task.
+ *
+ * @param clientId Optional client id. If the client id is not specified, a
+ * new one will be generated. This value (whether specified or generated) is
+ * included in the response.
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @param id The id of the reporting task to retrieve
+ * @return A reportingTaskEntity.
+ */
+ @GET
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}/{id}")
+ @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+ @TypeHint(ReportingTaskEntity.class)
+ public Response getReportingTask(@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId,
+ @PathParam("availability") String availability, @PathParam("id") String id) {
+
+ final Availability avail = parseAvailability(availability);
+
+ // replicate if cluster manager
+ if (properties.isClusterManager() && Availability.NODE.equals(avail)) {
+ return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse();
+ }
+
+ // get the reporting task
+ final ReportingTaskDTO reportingTask = serviceFacade.getReportingTask(id);
+
+ // create the revision
+ final RevisionDTO revision = new RevisionDTO();
+ revision.setClientId(clientId.getClientId());
+
+ // create the response entity
+ final ReportingTaskEntity entity = new ReportingTaskEntity();
+ entity.setRevision(revision);
+ entity.setReportingTask(populateRemainingReportingTaskContent(availability, reportingTask));
+
+ return clusterContext(generateOkResponse(entity)).build();
+ }
+
+ /**
+ * Returns the descriptor for the specified property.
+ *
+ * @param clientId Optional client id. If the client id is not specified, a
+ * new one will be generated. This value (whether specified or generated) is
+ * included in the response.
+ * @param availability
+ * @param id The id of the reporting task.
+ * @param propertyName The property
+ * @return a propertyDescriptorEntity
+ */
+ @GET
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}/{id}/descriptors")
+ @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+ @TypeHint(PropertyDescriptorEntity.class)
+ public Response getPropertyDescriptor(
+ @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId,
+ @PathParam("availability") String availability, @PathParam("id") String id,
+ @QueryParam("propertyName") String propertyName) {
+
+ final Availability avail = parseAvailability(availability);
+
+ // ensure the property name is specified
+ if (propertyName == null) {
+ throw new IllegalArgumentException("The property name must be specified.");
+ }
+
+ // replicate if cluster manager and task is on node
+ if (properties.isClusterManager() && Availability.NODE.equals(avail)) {
+ return clusterManager.applyRequest(HttpMethod.GET, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse();
+ }
+
+ // get the property descriptor
+ final PropertyDescriptorDTO descriptor = serviceFacade.getReportingTaskPropertyDescriptor(id, propertyName);
+
+ // create the revision
+ final RevisionDTO revision = new RevisionDTO();
+ revision.setClientId(clientId.getClientId());
+
+ // generate the response entity
+ final PropertyDescriptorEntity entity = new PropertyDescriptorEntity();
+ entity.setRevision(revision);
+ entity.setPropertyDescriptor(descriptor);
+
+ // generate the response
+ return clusterContext(generateOkResponse(entity)).build();
+ }
+
+ /**
+ * Updates the specified reporting task.
+ *
+ * @param httpServletRequest
+ * @param version The revision is used to verify the client is working with
+ * the latest version of the flow.
+ * @param clientId Optional client id. If the client id is not specified, a
+ * new one will be generated. This value (whether specified or generated) is
+ * included in the response.
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @param id The id of the reporting task to update.
+ * @param name The name of the reporting task
+ * @param annotationData The annotation data for the reporting task
+ * @param markedForDeletion Array of property names whose value should be removed.
+ * @param state The updated scheduled state
+ * @param schedulingStrategy The scheduling strategy for this reporting task
+ * @param schedulingPeriod The scheduling period for this reporting task
+ * @param comments The comments for this reporting task
+ * @param formParams Additionally, the processor properties and styles are
+ * specified in the form parameters. Because the property names and styles
+ * differ from processor to processor they are specified in a map-like
+ * fashion:
+ * <br>
+ * <ul>
+ * <li>properties[required.file.path]=/path/to/file</li>
+ * <li>properties[required.hostname]=localhost</li>
+ * <li>properties[required.port]=80</li>
+ * <li>properties[optional.file.path]=/path/to/file</li>
+ * <li>properties[optional.hostname]=localhost</li>
+ * <li>properties[optional.port]=80</li>
+ * <li>properties[user.defined.pattern]=^.*?s.*$</li>
+ * </ul>
+ * @return A reportingTaskEntity.
+ */
+ @PUT
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}/{id}")
+ @PreAuthorize("hasRole('ROLE_DFM')")
+ @TypeHint(ReportingTaskEntity.class)
+ public Response updateReportingTask(
+ @Context HttpServletRequest httpServletRequest,
+ @FormParam(VERSION) LongParameter version,
+ @FormParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId,
+ @PathParam("availability") String availability, @PathParam("id") String id, @FormParam("name") String name,
+ @FormParam("annotationData") String annotationData, @FormParam("markedForDeletion[]") List<String> markedForDeletion,
+ @FormParam("state") String state, @FormParam("schedulingStrategy") String schedulingStrategy,
+ @FormParam("schedulingPeriod") String schedulingPeriod, @FormParam("comments") String comments,
+ MultivaluedMap<String, String> formParams) {
+
+ // create collections for holding the reporting task properties
+ final Map<String, String> updatedProperties = new LinkedHashMap<>();
+
+ // go through each parameter and look for processor properties
+ for (String parameterName : formParams.keySet()) {
+ if (StringUtils.isNotBlank(parameterName)) {
+ // see if the parameter name starts with an expected parameter type...
+ // if so, store the parameter name and value in the corresponding collection
+ if (parameterName.startsWith("properties")) {
+ final int startIndex = StringUtils.indexOf(parameterName, "[");
+ final int endIndex = StringUtils.lastIndexOf(parameterName, "]");
+ if (startIndex != -1 && endIndex != -1) {
+ final String propertyName = StringUtils.substring(parameterName, startIndex + 1, endIndex);
+ updatedProperties.put(propertyName, formParams.getFirst(parameterName));
+ }
+ }
+ }
+ }
+
+ // set the properties to remove
+ for (String propertyToDelete : markedForDeletion) {
+ updatedProperties.put(propertyToDelete, null);
+ }
+
+ // create the reporting task DTO
+ final ReportingTaskDTO reportingTaskDTO = new ReportingTaskDTO();
+ reportingTaskDTO.setId(id);
+ reportingTaskDTO.setName(name);
+ reportingTaskDTO.setState(state);
+ reportingTaskDTO.setSchedulingStrategy(schedulingStrategy);
+ reportingTaskDTO.setSchedulingPeriod(schedulingPeriod);
+ reportingTaskDTO.setAnnotationData(annotationData);
+ reportingTaskDTO.setComments(comments);
+
+ // only set the properties when appropriate
+ if (!updatedProperties.isEmpty()) {
+ reportingTaskDTO.setProperties(updatedProperties);
+ }
+
+ // create the revision
+ final RevisionDTO revision = new RevisionDTO();
+ revision.setClientId(clientId.getClientId());
+ if (version != null) {
+ revision.setVersion(version.getLong());
+ }
+
+ // create the reporting task entity
+ final ReportingTaskEntity reportingTaskEntity = new ReportingTaskEntity();
+ reportingTaskEntity.setRevision(revision);
+ reportingTaskEntity.setReportingTask(reportingTaskDTO);
+
+ // update the reporting task
+ return updateReportingTask(httpServletRequest, availability, id, reportingTaskEntity);
+ }
+
+ /**
+ * Updates the specified a Reporting Task.
+ *
+ * @param httpServletRequest
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @param id The id of the reporting task to update.
+ * @param reportingTaskEntity A reportingTaskEntity.
+ * @return A reportingTaskEntity.
+ */
+ @PUT
+ @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}/{id}")
+ @PreAuthorize("hasRole('ROLE_DFM')")
+ @TypeHint(ReportingTaskEntity.class)
+ public Response updateReportingTask(
+ @Context HttpServletRequest httpServletRequest,
+ @PathParam("availability") String availability,
+ @PathParam("id") String id,
+ ReportingTaskEntity reportingTaskEntity) {
+
+ final Availability avail = parseAvailability(availability);
+
+ if (reportingTaskEntity == null || reportingTaskEntity.getReportingTask() == null) {
+ throw new IllegalArgumentException("Reporting task details must be specified.");
+ }
+
+ if (reportingTaskEntity.getRevision() == null) {
+ throw new IllegalArgumentException("Revision must be specified.");
+ }
+
+ // ensure the ids are the same
+ final ReportingTaskDTO requestReportingTaskDTO = reportingTaskEntity.getReportingTask();
+ if (!id.equals(requestReportingTaskDTO.getId())) {
+ throw new IllegalArgumentException(String.format("The reporting task id (%s) in the request body does not equal the "
+ + "reporting task id of the requested resource (%s).", requestReportingTaskDTO.getId(), id));
+ }
+
+ // replicate if cluster manager
+ if (properties.isClusterManager() && Availability.NODE.equals(avail)) {
+ // change content type to JSON for serializing entity
+ final Map<String, String> headersToOverride = new HashMap<>();
+ headersToOverride.put("content-type", MediaType.APPLICATION_JSON);
+
+ // replicate the request
+ return clusterManager.applyRequest(HttpMethod.PUT, getAbsolutePath(), updateClientId(reportingTaskEntity), getHeaders(headersToOverride)).getResponse();
+ }
+
+ // handle expects request (usually from the cluster manager)
+ final String expects = httpServletRequest.getHeader(WebClusterManager.NCM_EXPECTS_HTTP_HEADER);
+ if (expects != null) {
+ serviceFacade.verifyUpdateReportingTask(requestReportingTaskDTO);
+ return generateContinueResponse().build();
+ }
+
+ // update the reporting task
+ final RevisionDTO revision = reportingTaskEntity.getRevision();
+ final ConfigurationSnapshot<ReportingTaskDTO> controllerResponse = serviceFacade.updateReportingTask(
+ new Revision(revision.getVersion(), revision.getClientId()), requestReportingTaskDTO);
+
+ // get the results
+ final ReportingTaskDTO responseReportingTaskDTO = controllerResponse.getConfiguration();
+
+ // get the updated revision
+ final RevisionDTO updatedRevision = new RevisionDTO();
+ updatedRevision.setClientId(revision.getClientId());
+ updatedRevision.setVersion(controllerResponse.getVersion());
+
+ // build the response entity
+ final ReportingTaskEntity entity = new ReportingTaskEntity();
+ entity.setRevision(updatedRevision);
+ entity.setReportingTask(populateRemainingReportingTaskContent(availability, responseReportingTaskDTO));
+
+ return clusterContext(generateOkResponse(entity)).build();
+ }
+
+ /**
+ * Removes the specified reporting task.
+ *
+ * @param httpServletRequest
+ * @param version The revision is used to verify the client is working with
+ * the latest version of the flow.
+ * @param clientId Optional client id. If the client id is not specified, a
+ * new one will be generated. This value (whether specified or generated) is
+ * included in the response.
+ * @param availability Whether the reporting task is available on the NCM only (ncm) or on the
+ * nodes only (node). If this instance is not clustered all tasks should use the node availability.
+ * @param id The id of the reporting task to remove.
+ * @return A entity containing the client id and an updated revision.
+ */
+ @DELETE
+ @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+ @Path("/{availability}/{id}")
+ @PreAuthorize("hasRole('ROLE_DFM')")
+ @TypeHint(ReportingTaskEntity.class)
+ public Response removeReportingTask(
+ @Context HttpServletRequest httpServletRequest,
+ @QueryParam(VERSION) LongParameter version,
+ @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) ClientIdParameter clientId,
+ @PathParam("availability") String availability, @PathParam("id") String id) {
+
+ final Availability avail = parseAvailability(availability);
+
+ // replicate if cluster manager
+ if (properties.isClusterManager() && Availability.NODE.equals(avail)) {
+ return clusterManager.applyRequest(HttpMethod.DELETE, getAbsolutePath(), getRequestParameters(true), getHeaders()).getResponse();
+ }
+
+ // handle expects request (usually from the cluster manager)
+ final String expects = httpServletRequest.getHeader(WebClusterManager.NCM_EXPECTS_HTTP_HEADER);
+ if (expects != null) {
+ serviceFacade.verifyDeleteReportingTask(id);
+ return generateContinueResponse().build();
+ }
+
+ // determine the specified version
+ Long clientVersion = null;
+ if (version != null) {
+ clientVersion = version.getLong();
+ }
+
+ // delete the specified reporting task
+ final ConfigurationSnapshot<Void> controllerResponse = serviceFacade.deleteReportingTask(new Revision(clientVersion, clientId.getClientId()), id);
+
+ // get the updated revision
+ final RevisionDTO revision = new RevisionDTO();
+ revision.setClientId(clientId.getClientId());
+ revision.setVersion(controllerResponse.getVersion());
+
+ // build the response entity
+ final ReportingTaskEntity entity = new ReportingTaskEntity();
+ entity.setRevision(revision);
+
+ return clusterContext(generateOkResponse(entity)).build();
+ }
+
+ // setters
+
+ public void setServiceFacade(NiFiServiceFacade serviceFacade) {
+ this.serviceFacade = serviceFacade;
+ }
+
+ public void setClusterManager(WebClusterManager clusterManager) {
+ this.clusterManager = clusterManager;
+ }
+
+ public void setProperties(NiFiProperties properties) {
+ this.properties = properties;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
index e0b7788..275b133 100644
--- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/SnippetResource.java
@@ -340,7 +340,7 @@ public class SnippetResource extends ApplicationResource {
// get the updated revision
final RevisionDTO updatedRevision = new RevisionDTO();
updatedRevision.setClientId(revision.getClientId());
- updatedRevision.setVersion(response.getRevision());
+ updatedRevision.setVersion(response.getVersion());
// build the response entity
SnippetEntity entity = new SnippetEntity();
@@ -520,7 +520,7 @@ public class SnippetResource extends ApplicationResource {
// get the updated revision
final RevisionDTO updatedRevision = new RevisionDTO();
updatedRevision.setClientId(revision.getClientId());
- updatedRevision.setVersion(controllerResponse.getRevision());
+ updatedRevision.setVersion(controllerResponse.getVersion());
// build the response entity
SnippetEntity entity = new SnippetEntity();
@@ -577,7 +577,7 @@ public class SnippetResource extends ApplicationResource {
// get the updated revision
final RevisionDTO revision = new RevisionDTO();
revision.setClientId(clientId.getClientId());
- revision.setVersion(controllerResponse.getRevision());
+ revision.setVersion(controllerResponse.getVersion());
// build the response entity
SnippetEntity entity = new SnippetEntity();
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/ThrowableMapper.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/ThrowableMapper.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/ThrowableMapper.java
index 091653a..0ef6edb 100644
--- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/ThrowableMapper.java
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/config/ThrowableMapper.java
@@ -34,11 +34,8 @@ public class ThrowableMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable exception) {
// log the error
- logger.info(String.format("An unexpected error has occurred: %s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR));
-
- if (logger.isDebugEnabled()) {
- logger.debug(StringUtils.EMPTY, exception);
- }
+ logger.error(String.format("An unexpected error has occurred: %s. Returning %s response.", exception, Response.Status.INTERNAL_SERVER_ERROR));
+ logger.error(StringUtils.EMPTY, exception);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("An unexpected error has occurred. Please check the logs for additional details.").type("text/plain").build();
}
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index 92a5449..7fe76ad 100644
--- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -39,7 +39,7 @@ import javax.ws.rs.WebApplicationException;
import org.apache.nifi.action.Action;
import org.apache.nifi.action.component.details.ComponentDetails;
-import org.apache.nifi.action.component.details.ProcessorDetails;
+import org.apache.nifi.action.component.details.ExtensionDetails;
import org.apache.nifi.action.component.details.RemoteProcessGroupDetails;
import org.apache.nifi.action.details.ActionDetails;
import org.apache.nifi.action.details.ConfigureDetails;
@@ -97,14 +97,12 @@ import org.apache.nifi.scheduling.SchedulingStrategy;
import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.user.NiFiUserGroup;
import org.apache.nifi.util.FormatUtils;
-import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.Revision;
-import org.apache.nifi.web.api.dto.ProcessorConfigDTO.AllowableValueDTO;
-import org.apache.nifi.web.api.dto.ProcessorConfigDTO.PropertyDescriptorDTO;
+import org.apache.nifi.web.api.dto.PropertyDescriptorDTO.AllowableValueDTO;
import org.apache.nifi.web.api.dto.action.ActionDTO;
import org.apache.nifi.web.api.dto.action.HistoryDTO;
import org.apache.nifi.web.api.dto.action.component.details.ComponentDetailsDTO;
-import org.apache.nifi.web.api.dto.action.component.details.ProcessorDetailsDTO;
+import org.apache.nifi.web.api.dto.action.component.details.ExtensionDetailsDTO;
import org.apache.nifi.web.api.dto.action.component.details.RemoteProcessGroupDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.ActionDetailsDTO;
import org.apache.nifi.web.api.dto.action.details.ConfigureDetailsDTO;
@@ -124,6 +122,12 @@ import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO;
import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO;
import org.apache.nifi.web.api.dto.status.StatusDTO;
import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.controller.ConfiguredComponent;
+import org.apache.nifi.controller.ReportingTaskNode;
+import org.apache.nifi.controller.service.ControllerServiceNode;
+import org.apache.nifi.controller.service.ControllerServiceReference;
+import org.apache.nifi.reporting.ReportingTask;
+import org.apache.nifi.web.FlowModification;
/**
*
@@ -218,9 +222,9 @@ public final class DtoFactory {
return null;
}
- if (componentDetails instanceof ProcessorDetails) {
- final ProcessorDetailsDTO processorDetails = new ProcessorDetailsDTO();
- processorDetails.setType(((ProcessorDetails) componentDetails).getType());
+ if (componentDetails instanceof ExtensionDetails) {
+ final ExtensionDetailsDTO processorDetails = new ExtensionDetailsDTO();
+ processorDetails.setType(((ExtensionDetails) componentDetails).getType());
return processorDetails;
} else if (componentDetails instanceof RemoteProcessGroupDetails) {
final RemoteProcessGroupDetailsDTO remoteProcessGroupDetails = new RemoteProcessGroupDetailsDTO();
@@ -834,6 +838,241 @@ public final class DtoFactory {
return dto;
}
+ public ReportingTaskDTO createReportingTaskDto(final ReportingTaskNode reportingTaskNode) {
+ final ReportingTaskDTO dto = new ReportingTaskDTO();
+ dto.setId(reportingTaskNode.getIdentifier());
+ dto.setName(reportingTaskNode.getName());
+ dto.setType(reportingTaskNode.getReportingTask().getClass().getName());
+ dto.setSchedulingStrategy(reportingTaskNode.getSchedulingStrategy().name());
+ dto.setSchedulingPeriod(reportingTaskNode.getSchedulingPeriod());
+ dto.setState(reportingTaskNode.getScheduledState().name());
+ dto.setActiveThreadCount(reportingTaskNode.getActiveThreadCount());
+ dto.setAnnotationData(reportingTaskNode.getAnnotationData());
+ dto.setComments(reportingTaskNode.getComments());
+
+ final Map<String, String> defaultSchedulingPeriod = new HashMap<>();
+ defaultSchedulingPeriod.put(SchedulingStrategy.TIMER_DRIVEN.name(), SchedulingStrategy.TIMER_DRIVEN.getDefaultSchedulingPeriod());
+ defaultSchedulingPeriod.put(SchedulingStrategy.CRON_DRIVEN.name(), SchedulingStrategy.CRON_DRIVEN.getDefaultSchedulingPeriod());
+ dto.setDefaultSchedulingPeriod(defaultSchedulingPeriod);
+
+ // sort a copy of the properties
+ final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
+ @Override
+ public int compare(PropertyDescriptor o1, PropertyDescriptor o2) {
+ return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
+ }
+ });
+ sortedProperties.putAll(reportingTaskNode.getProperties());
+
+ // get the property order from the reporting task
+ final ReportingTask reportingTask = reportingTaskNode.getReportingTask();
+ final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
+ final List<PropertyDescriptor> descriptors = reportingTask.getPropertyDescriptors();
+ if (descriptors != null && !descriptors.isEmpty()) {
+ for (PropertyDescriptor descriptor : descriptors) {
+ orderedProperties.put(descriptor, null);
+ }
+ }
+ orderedProperties.putAll(sortedProperties);
+
+ // build the descriptor and property dtos
+ dto.setDescriptors(new LinkedHashMap<String, PropertyDescriptorDTO>());
+ dto.setProperties(new LinkedHashMap<String, String>());
+ for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
+ final PropertyDescriptor descriptor = entry.getKey();
+
+ // store the property descriptor
+ dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor));
+
+ // determine the property value - don't include sensitive properties
+ String propertyValue = entry.getValue();
+ if (propertyValue != null && descriptor.isSensitive()) {
+ propertyValue = "********";
+ }
+
+ // set the property value
+ dto.getProperties().put(descriptor.getName(), propertyValue);
+ }
+
+ // add the validation errors
+ final Collection<ValidationResult> validationErrors = reportingTaskNode.getValidationErrors();
+ if (validationErrors != null && !validationErrors.isEmpty()) {
+ final List<String> errors = new ArrayList<>();
+ for (final ValidationResult validationResult : validationErrors) {
+ errors.add(validationResult.toString());
+ }
+
+ dto.setValidationErrors(errors);
+ }
+
+ return dto;
+ }
+
+ public ControllerServiceDTO createControllerServiceDto(final ControllerServiceNode controllerServiceNode) {
+ final ControllerServiceDTO dto = new ControllerServiceDTO();
+ dto.setId(controllerServiceNode.getIdentifier());
+ dto.setName(controllerServiceNode.getName());
+ dto.setType(controllerServiceNode.getControllerServiceImplementation().getClass().getName());
+ dto.setState(controllerServiceNode.getState().name());
+ dto.setAnnotationData(controllerServiceNode.getAnnotationData());
+ dto.setComments(controllerServiceNode.getComments());
+
+ // sort a copy of the properties
+ final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
+ @Override
+ public int compare(PropertyDescriptor o1, PropertyDescriptor o2) {
+ return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
+ }
+ });
+ sortedProperties.putAll(controllerServiceNode.getProperties());
+
+ // get the property order from the controller service
+ final ControllerService controllerService = controllerServiceNode.getControllerServiceImplementation();
+ final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
+ final List<PropertyDescriptor> descriptors = controllerService.getPropertyDescriptors();
+ if (descriptors != null && !descriptors.isEmpty()) {
+ for (PropertyDescriptor descriptor : descriptors) {
+ orderedProperties.put(descriptor, null);
+ }
+ }
+ orderedProperties.putAll(sortedProperties);
+
+ // build the descriptor and property dtos
+ dto.setDescriptors(new LinkedHashMap<String, PropertyDescriptorDTO>());
+ dto.setProperties(new LinkedHashMap<String, String>());
+ for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
+ final PropertyDescriptor descriptor = entry.getKey();
+
+ // store the property descriptor
+ dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor));
+
+ // determine the property value - don't include sensitive properties
+ String propertyValue = entry.getValue();
+ if (propertyValue != null && descriptor.isSensitive()) {
+ propertyValue = "********";
+ }
+
+ // set the property value
+ dto.getProperties().put(descriptor.getName(), propertyValue);
+ }
+
+ // create the reference dto's
+ dto.setReferencingComponents(createControllerServiceReferencingComponentsDto(controllerServiceNode.getReferences()));
+
+ // add the validation errors
+ final Collection<ValidationResult> validationErrors = controllerServiceNode.getValidationErrors();
+ if (validationErrors != null && !validationErrors.isEmpty()) {
+ final List<String> errors = new ArrayList<>();
+ for (final ValidationResult validationResult : validationErrors) {
+ errors.add(validationResult.toString());
+ }
+
+ dto.setValidationErrors(errors);
+ }
+
+ return dto;
+ }
+
+ public Set<ControllerServiceReferencingComponentDTO> createControllerServiceReferencingComponentsDto(final ControllerServiceReference reference) {
+ return createControllerServiceReferencingComponentsDto(reference, new HashSet<ControllerServiceNode>());
+ }
+
+ private Set<ControllerServiceReferencingComponentDTO> createControllerServiceReferencingComponentsDto(final ControllerServiceReference reference, final Set<ControllerServiceNode> visited) {
+ final Set<ControllerServiceReferencingComponentDTO> referencingComponents = new LinkedHashSet<>();
+
+ // get all references
+ for (final ConfiguredComponent component : reference.getReferencingComponents()) {
+ final ControllerServiceReferencingComponentDTO dto = new ControllerServiceReferencingComponentDTO();
+ dto.setId(component.getIdentifier());
+ dto.setName(component.getName());
+
+ List<PropertyDescriptor> propertyDescriptors = null;
+ Collection<ValidationResult> validationErrors = null;
+ if (component instanceof ProcessorNode) {
+ final ProcessorNode node = ((ProcessorNode) component);
+ dto.setGroupId(node.getProcessGroup().getIdentifier());
+ dto.setState(node.getScheduledState().name());
+ dto.setActiveThreadCount(node.getActiveThreadCount());
+ dto.setType(node.getProcessor().getClass().getName());
+ dto.setReferenceType(Processor.class.getSimpleName());
+
+ propertyDescriptors = node.getProcessor().getPropertyDescriptors();
+ validationErrors = node.getValidationErrors();
+ } else if (component instanceof ControllerServiceNode) {
+ final ControllerServiceNode node = ((ControllerServiceNode) component);
+ dto.setState(node.getState().name());
+ dto.setType(node.getControllerServiceImplementation().getClass().getName());
+ dto.setReferenceType(ControllerService.class.getSimpleName());
+ dto.setReferenceCycle(visited.contains(node));
+
+ // if we haven't encountered this service before include it's referencing components
+ if (!dto.getReferenceCycle()) {
+ dto.setReferencingComponents(createControllerServiceReferencingComponentsDto(node.getReferences(), visited));
+ }
+
+ propertyDescriptors = node.getControllerServiceImplementation().getPropertyDescriptors();
+ validationErrors = node.getValidationErrors();
+ } else if (component instanceof ReportingTaskNode) {
+ final ReportingTaskNode node = ((ReportingTaskNode) component);
+ dto.setState(node.getScheduledState().name());
+ dto.setActiveThreadCount(node.getActiveThreadCount());
+ dto.setType(node.getReportingTask().getClass().getName());
+ dto.setReferenceType(ReportingTask.class.getSimpleName());
+
+ propertyDescriptors = node.getReportingTask().getPropertyDescriptors();
+ validationErrors = node.getValidationErrors();
+ }
+
+ if (propertyDescriptors != null && !propertyDescriptors.isEmpty()) {
+ final Map<PropertyDescriptor, String> sortedProperties = new TreeMap<>(new Comparator<PropertyDescriptor>() {
+ @Override
+ public int compare(PropertyDescriptor o1, PropertyDescriptor o2) {
+ return Collator.getInstance(Locale.US).compare(o1.getName(), o2.getName());
+ }
+ });
+ sortedProperties.putAll(component.getProperties());
+
+ final Map<PropertyDescriptor, String> orderedProperties = new LinkedHashMap<>();
+ for (PropertyDescriptor descriptor : propertyDescriptors) {
+ orderedProperties.put(descriptor, null);
+ }
+ orderedProperties.putAll(sortedProperties);
+
+ // build the descriptor and property dtos
+ dto.setDescriptors(new LinkedHashMap<String, PropertyDescriptorDTO>());
+ dto.setProperties(new LinkedHashMap<String, String>());
+ for (final Map.Entry<PropertyDescriptor, String> entry : orderedProperties.entrySet()) {
+ final PropertyDescriptor descriptor = entry.getKey();
+
+ // store the property descriptor
+ dto.getDescriptors().put(descriptor.getName(), createPropertyDescriptorDto(descriptor));
+
+ // determine the property value - don't include sensitive properties
+ String propertyValue = entry.getValue();
+ if (propertyValue != null && descriptor.isSensitive()) {
+ propertyValue = "********";
+ }
+
+ // set the property value
+ dto.getProperties().put(descriptor.getName(), propertyValue);
+ }
+ }
+
+ if (validationErrors != null && !validationErrors.isEmpty()) {
+ final List<String> errors = new ArrayList<>();
+ for (final ValidationResult validationResult : validationErrors) {
+ errors.add(validationResult.toString());
+ }
+
+ dto.setValidationErrors(errors);
+ }
+
+ referencingComponents.add(dto);
+ }
+
+ return referencingComponents;
+ }
+
public RemoteProcessGroupPortDTO createRemoteProcessGroupPortDto(final RemoteGroupPort port) {
if (port == null) {
return null;
@@ -1143,6 +1382,135 @@ public final class DtoFactory {
return types;
}
+
+ /**
+ * Identifies all baseTypes for the specified type that are assignable to the specified baseType.
+ *
+ * @param baseType
+ * @param type
+ * @param baseTypes
+ */
+ private void identifyBaseTypes(final Class baseType, final Class type, final Set<Class> baseTypes, final boolean recurse) {
+ final Class[] interfaces = type.getInterfaces();
+ for (final Class i : interfaces) {
+ if (baseType.isAssignableFrom(i) && !baseType.equals(i)) {
+ baseTypes.add(i);
+ }
+ }
+
+ if (recurse) {
+ if (type.getSuperclass() != null) {
+ identifyBaseTypes(baseType, type.getSuperclass(), baseTypes, recurse);
+ }
+ }
+ }
+
+ /**
+ * Gets the DocumentedTypeDTOs from the specified classes for the specified baseClass.
+ *
+ * @param baseClass
+ * @param classes
+ * @return
+ */
+ public Set<DocumentedTypeDTO> fromDocumentedTypes(final Class baseClass, final Set<Class> classes) {
+ final Set<DocumentedTypeDTO> types = new LinkedHashSet<>();
+ final Set<Class> sortedClasses = new TreeSet<>(CLASS_NAME_COMPARATOR);
+ sortedClasses.addAll(classes);
+
+ // identify all interfaces that extend baseClass for all classes
+ final Set<Class> interfaces = new HashSet<>();
+ for (final Class<?> cls : sortedClasses) {
+ identifyBaseTypes(baseClass, cls, interfaces, true);
+ }
+
+ // build a lookup of all interfaces
+ final Map<Class, DocumentedTypeDTO> lookup = new HashMap<>();
+
+ // convert the interfaces to DTO form
+ for (final Class<?> i : interfaces) {
+ final DocumentedTypeDTO type = new DocumentedTypeDTO();
+ type.setType(i.getName());
+ type.setDescription(getCapabilityDescription(i));
+ type.setTags(getTags(i));
+ type.setChildTypes(new LinkedHashSet<DocumentedTypeDTO>());
+ lookup.put(i, type);
+ }
+
+ // move the interfaces into the appropriate hierarchy
+ final Collection<Class> rootTypes = new ArrayList<>();
+ for (final Class<?> i : interfaces) {
+ rootTypes.add(i);
+
+ // identify the base types
+ final Set<Class> baseTypes = new LinkedHashSet<>();
+ identifyBaseTypes(baseClass, i, baseTypes, false);
+
+ // move this interfaces into the hierarchy where appropriate
+ if (!baseTypes.isEmpty()) {
+ // get the DTO for each base type
+ for (final Class baseType : baseTypes) {
+ final DocumentedTypeDTO parentInteface = lookup.get(baseType);
+ final DocumentedTypeDTO childInterface = lookup.get(i);
+
+ // include all parent tags in the respective children
+ childInterface.getTags().addAll(parentInteface.getTags());
+
+ // update the hierarchy
+ parentInteface.getChildTypes().add(childInterface);
+ }
+
+ // remove this interface from the lookup (this will only
+ // leave the interfaces that are ancestor roots)
+ rootTypes.remove(i);
+ }
+ }
+
+ // include the interfaces
+ sortedClasses.addAll(rootTypes);
+
+ // get the DTO form for all interfaces and classes
+ for (final Class<?> cls : sortedClasses) {
+ boolean add = false;
+
+ final DocumentedTypeDTO type;
+ if (rootTypes.contains(cls)) {
+ type = lookup.get(cls);
+ add = true;
+ } else {
+ type = new DocumentedTypeDTO();
+ type.setType(cls.getName());
+ type.setDescription(getCapabilityDescription(cls));
+ type.setTags(getTags(cls));
+ }
+
+ // identify the base types
+ final Set<Class> baseTypes = new LinkedHashSet<>();
+ identifyBaseTypes(baseClass, cls, baseTypes, false);
+
+ // include this type if it doesn't belong to another hierarchy
+ if (baseTypes.isEmpty()) {
+ add = true;
+ } else {
+ // get the DTO for each base type
+ for (final Class baseType : baseTypes) {
+ final DocumentedTypeDTO parentInterface = lookup.get(baseType);
+
+ // include all parent tags in the respective children
+ type.getTags().addAll(parentInterface.getTags());
+
+ // update the hierarchy
+ parentInterface.getChildTypes().add(type);
+ }
+ }
+
+ // add if appropriate
+ if (add) {
+ types.add(type);
+ }
+ }
+
+ return types;
+ }
/**
* Creates a ProcessorDTO from the specified ProcessorNode.
@@ -1575,12 +1943,12 @@ public final class DtoFactory {
* @param propertyDescriptor
* @return
*/
- private ProcessorConfigDTO.PropertyDescriptorDTO createPropertyDescriptorDto(final PropertyDescriptor propertyDescriptor) {
+ public PropertyDescriptorDTO createPropertyDescriptorDto(final PropertyDescriptor propertyDescriptor) {
if (propertyDescriptor == null) {
return null;
}
- final ProcessorConfigDTO.PropertyDescriptorDTO dto = new ProcessorConfigDTO.PropertyDescriptorDTO();
+ final PropertyDescriptorDTO dto = new PropertyDescriptorDTO();
dto.setName(propertyDescriptor.getName());
dto.setDisplayName(propertyDescriptor.getDisplayName());
@@ -1590,18 +1958,16 @@ public final class DtoFactory {
dto.setDescription(propertyDescriptor.getDescription());
dto.setDefaultValue(propertyDescriptor.getDefaultValue());
dto.setSupportsEl(propertyDescriptor.isExpressionLanguageSupported());
+ dto.setIdentifiesControllerService(propertyDescriptor.getControllerServiceDefinition() != null);
final Class<? extends ControllerService> serviceDefinition = propertyDescriptor.getControllerServiceDefinition();
if (propertyDescriptor.getAllowableValues() == null) {
if (serviceDefinition == null) {
dto.setAllowableValues(null);
} else {
- final Set<AllowableValueDTO> allowableValues = new LinkedHashSet<>();
+ final List<AllowableValueDTO> allowableValues = new ArrayList<>();
for (final String serviceIdentifier : controllerServiceLookup.getControllerServiceIdentifiers(serviceDefinition)) {
- String displayName = serviceIdentifier;
-
- // TODO: attempt to get the controller service name
- final ControllerService controllerService = controllerServiceLookup.getControllerService(serviceIdentifier);
+ final String displayName = controllerServiceLookup.getControllerServiceName(serviceIdentifier);
final AllowableValueDTO allowableValue = new AllowableValueDTO();
allowableValue.setDisplayName(displayName);
@@ -1611,7 +1977,7 @@ public final class DtoFactory {
dto.setAllowableValues(allowableValues);
}
} else {
- final Set<AllowableValueDTO> allowableValues = new LinkedHashSet<>();
+ final List<AllowableValueDTO> allowableValues = new ArrayList<>();
for (final AllowableValue allowableValue : propertyDescriptor.getAllowableValues()) {
final AllowableValueDTO allowableValueDto = new AllowableValueDTO();
allowableValueDto.setDisplayName(allowableValue.getDisplayName());
@@ -1642,6 +2008,25 @@ public final class DtoFactory {
return copy;
}
+
+ public ControllerServiceDTO copy(final ControllerServiceDTO original) {
+ final ControllerServiceDTO copy = new ControllerServiceDTO();
+ copy.setAnnotationData(original.getAnnotationData());
+ copy.setAvailability(original.getAvailability());
+ copy.setComments(original.getComments());
+ copy.setCustomUiUrl(original.getCustomUiUrl());
+ copy.setDescriptors(copy(original.getDescriptors()));
+ copy.setId(original.getId());
+ copy.setName(original.getName());
+ copy.setProperties(copy(original.getProperties()));
+ copy.setReferencingComponents(copy(original.getReferencingComponents()));
+ copy.setState(original.getState());
+ copy.setType(original.getType());
+ copy.setUri(original.getUri());
+ copy.setValidationErrors(copy(original.getValidationErrors()));
+ return copy;
+ }
+
public FunnelDTO copy(final FunnelDTO original) {
final FunnelDTO copy = new FunnelDTO();
copy.setId(original.getId());
@@ -2029,14 +2414,17 @@ public final class DtoFactory {
/**
* Factory method for creating a new RevisionDTO based on this controller.
*
- * @param revision
+ * @param lastMod
* @return
*/
- public RevisionDTO createRevisionDTO(Revision revision) {
+ public RevisionDTO createRevisionDTO(FlowModification lastMod) {
+ final Revision revision = lastMod.getRevision();
+
// create the dto
final RevisionDTO revisionDTO = new RevisionDTO();
revisionDTO.setVersion(revision.getVersion());
revisionDTO.setClientId(revision.getClientId());
+ revisionDTO.setLastModifier(lastMod.getLastModifier());
return revisionDTO;
}
@@ -2146,8 +2534,6 @@ public final class DtoFactory {
}
/* setters */
- public void setProperties(NiFiProperties properties) {
- }
public void setControllerServiceLookup(ControllerServiceLookup lookup) {
this.controllerServiceLookup = lookup;
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
index 117555a..a373f05 100644
--- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java
@@ -52,8 +52,6 @@ import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.repository.ContentNotFoundException;
import org.apache.nifi.controller.repository.claim.ContentDirection;
-import org.apache.nifi.controller.service.ControllerServiceNode;
-import org.apache.nifi.controller.service.ControllerServiceProvider;
import org.apache.nifi.controller.status.ProcessGroupStatus;
import org.apache.nifi.diagnostics.SystemDiagnostics;
import org.apache.nifi.flowfile.FlowFilePrioritizer;
@@ -79,11 +77,11 @@ import org.apache.nifi.provenance.search.SearchableField;
import org.apache.nifi.remote.RootGroupPort;
import org.apache.nifi.reporting.Bulletin;
import org.apache.nifi.reporting.BulletinRepository;
+import org.apache.nifi.reporting.ReportingTask;
import org.apache.nifi.scheduling.SchedulingStrategy;
import org.apache.nifi.search.SearchContext;
import org.apache.nifi.search.SearchResult;
import org.apache.nifi.search.Searchable;
-import org.apache.nifi.web.security.user.NiFiUserUtils;
import org.apache.nifi.services.FlowService;
import org.apache.nifi.user.NiFiUser;
import org.apache.nifi.util.FormatUtils;
@@ -114,6 +112,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.admin.service.UserService;
import org.apache.nifi.authorization.DownloadAuthorization;
import org.apache.nifi.processor.DataUnit;
+import org.apache.nifi.web.security.user.NiFiUserUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
@@ -121,7 +120,7 @@ import org.springframework.security.access.AccessDeniedException;
/**
*
*/
-public class ControllerFacade implements ControllerServiceProvider {
+public class ControllerFacade {
private static final Logger logger = LoggerFactory.getLogger(ControllerFacade.class);
@@ -347,6 +346,24 @@ public class ControllerFacade implements ControllerServiceProvider {
public Set<DocumentedTypeDTO> getFlowFileComparatorTypes() {
return dtoFactory.fromDocumentedTypes(ExtensionManager.getExtensions(FlowFilePrioritizer.class));
}
+
+ /**
+ * Gets the ControllerService types that this controller supports.
+ *
+ * @return
+ */
+ public Set<DocumentedTypeDTO> getControllerServiceTypes() {
+ return dtoFactory.fromDocumentedTypes(ControllerService.class, ExtensionManager.getExtensions(ControllerService.class));
+ }
+
+ /**
+ * Gets the ReportingTask types that this controller supports.
+ *
+ * @return
+ */
+ public Set<DocumentedTypeDTO> getReportingTaskTypes() {
+ return dtoFactory.fromDocumentedTypes(ReportingTask.class, ExtensionManager.getExtensions(ReportingTask.class));
+ }
/**
* Gets the counters for this controller.
@@ -371,56 +388,6 @@ public class ControllerFacade implements ControllerServiceProvider {
return counter;
}
-
- /**
- * Return the controller service for the specified identifier.
- *
- * @param serviceIdentifier
- * @return
- */
- @Override
- public ControllerService getControllerService(String serviceIdentifier) {
- return flowController.getControllerService(serviceIdentifier);
- }
-
- @Override
- public ControllerServiceNode createControllerService(String type, String id, boolean firstTimeAdded) {
- return flowController.createControllerService(type, id, firstTimeAdded);
- }
-
- public void removeControllerService(ControllerServiceNode serviceNode) {
- flowController.removeControllerService(serviceNode);
- }
-
- @Override
- public Set<String> getControllerServiceIdentifiers(Class<? extends ControllerService> serviceType) {
- return flowController.getControllerServiceIdentifiers(serviceType);
- }
-
- @Override
- public ControllerServiceNode getControllerServiceNode(final String id) {
- return flowController.getControllerServiceNode(id);
- }
-
- @Override
- public boolean isControllerServiceEnabled(final ControllerService service) {
- return flowController.isControllerServiceEnabled(service);
- }
-
- @Override
- public boolean isControllerServiceEnabled(final String serviceIdentifier) {
- return flowController.isControllerServiceEnabled(serviceIdentifier);
- }
-
- @Override
- public void enableControllerService(final ControllerServiceNode serviceNode) {
- flowController.enableControllerService(serviceNode);
- }
-
- @Override
- public void disableControllerService(ControllerServiceNode serviceNode) {
- flowController.disableControllerService(serviceNode);
- }
/**
* Gets the status of this controller.
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
new file mode 100644
index 0000000..c1fba0c
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ControllerServiceDAO.java
@@ -0,0 +1,110 @@
+/*
+ * 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;
+
+import java.util.Set;
+import org.apache.nifi.controller.ScheduledState;
+
+import org.apache.nifi.controller.service.ControllerServiceNode;
+import org.apache.nifi.controller.service.ControllerServiceReference;
+import org.apache.nifi.controller.service.ControllerServiceState;
+import org.apache.nifi.web.api.dto.ControllerServiceDTO;
+
+/**
+ *
+ */
+public interface ControllerServiceDAO {
+
+ /**
+ * Determines if the specified controller service exists.
+ *
+ * @param controllerServiceId
+ * @return
+ */
+ boolean hasControllerService(String controllerServiceId);
+
+ /**
+ * Creates a controller service.
+ *
+ * @param controllerServiceDTO The controller service DTO
+ * @return The controller service
+ */
+ ControllerServiceNode createControllerService(ControllerServiceDTO controllerServiceDTO);
+
+ /**
+ * Gets the specified controller service.
+ *
+ * @param controllerServiceId The controller service id
+ * @return The controller service
+ */
+ ControllerServiceNode getControllerService(String controllerServiceId);
+
+ /**
+ * Gets all of the controller services.
+ *
+ * @return The controller services
+ */
+ Set<ControllerServiceNode> getControllerServices();
+
+ /**
+ * Updates the specified controller service.
+ *
+ * @param controllerServiceDTO The controller service DTO
+ * @return The controller service
+ */
+ ControllerServiceNode updateControllerService(ControllerServiceDTO controllerServiceDTO);
+
+ /**
+ * Updates the referencing components for the specified controller service.
+ *
+ * @param controllerServiceId
+ * @param scheduledState
+ * @param controllerServiceState the value of state
+ * @return the org.apache.nifi.controller.service.ControllerServiceReference
+ */
+ ControllerServiceReference updateControllerServiceReferencingComponents(String controllerServiceId, ScheduledState scheduledState, ControllerServiceState controllerServiceState);
+
+ /**
+ * Determines whether this controller service can be updated.
+ *
+ * @param controllerServiceDTO
+ */
+ void verifyUpdate(ControllerServiceDTO controllerServiceDTO);
+
+ /**
+ * Determines whether the referencing component of the specified controller service can be updated.
+ *
+ * @param controllerServiceId
+ * @param scheduledState
+ * @param controllerServiceState
+ */
+ void verifyUpdateReferencingComponents(String controllerServiceId, ScheduledState scheduledState, ControllerServiceState controllerServiceState);
+
+ /**
+ * Determines whether this controller service can be removed.
+ *
+ * @param controllerServiceId
+ */
+ void verifyDelete(String controllerServiceId);
+
+ /**
+ * Deletes the specified controller service.
+ *
+ * @param controllerServiceId The controller service id
+ */
+ void deleteControllerService(String controllerServiceId);
+}
http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/e9647717/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ReportingTaskDAO.java
----------------------------------------------------------------------
diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ReportingTaskDAO.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ReportingTaskDAO.java
new file mode 100644
index 0000000..49446d3
--- /dev/null
+++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ReportingTaskDAO.java
@@ -0,0 +1,88 @@
+/*
+ * 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;
+
+import java.util.Set;
+import org.apache.nifi.controller.ReportingTaskNode;
+
+import org.apache.nifi.web.api.dto.ReportingTaskDTO;
+
+/**
+ *
+ */
+public interface ReportingTaskDAO {
+
+ /**
+ * Determines if the specified reporting task exists.
+ *
+ * @param reportingTaskId
+ * @return
+ */
+ boolean hasReportingTask(String reportingTaskId);
+
+ /**
+ * Creates a reporting task.
+ *
+ * @param reportingTaskDTO The reporting task DTO
+ * @return The reporting task
+ */
+ ReportingTaskNode createReportingTask(ReportingTaskDTO reportingTaskDTO);
+
+ /**
+ * Gets the specified reporting task.
+ *
+ * @param reportingTaskId The reporting task id
+ * @return The reporting task
+ */
+ ReportingTaskNode getReportingTask(String reportingTaskId);
+
+ /**
+ * Gets all of the reporting tasks.
+ *
+ * @return The reporting tasks
+ */
+ Set<ReportingTaskNode> getReportingTasks();
+
+ /**
+ * Updates the specified reporting task.
+ *
+ * @param reportingTaskDTO The reporting task DTO
+ * @return The reporting task
+ */
+ ReportingTaskNode updateReportingTask(ReportingTaskDTO reportingTaskDTO);
+
+ /**
+ * Determines whether this reporting task can be updated.
+ *
+ * @param reportingTaskDTO
+ */
+ void verifyUpdate(ReportingTaskDTO reportingTaskDTO);
+
+ /**
+ * Determines whether this reporting task can be removed.
+ *
+ * @param reportingTaskId
+ */
+ void verifyDelete(String reportingTaskId);
+
+ /**
+ * Deletes the specified reporting task.
+ *
+ * @param reportingTaskId The reporting task id
+ */
+ void deleteReportingTask(String reportingTaskId);
+}