Repository: nifi-minifi
Updated Branches:
  refs/heads/minifi-c2-server caae8d768 -> 631b59926


http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ExtensionComponent.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ExtensionComponent.java
 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ExtensionComponent.java
new file mode 100644
index 0000000..eb26ffd
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ExtensionComponent.java
@@ -0,0 +1,119 @@
+/*
+ * 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.minifi.c2.model.extension;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.nifi.minifi.c2.model.BuildInfo;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A component provided by an extension bundle
+ */
+@ApiModel
+public class ExtensionComponent extends DefinedType {
+
+    private BuildInfo buildInfo;
+
+    private List<DefinedType> providedApiImplementations;
+
+    private String description;
+    private Set<String> tags;
+
+    private Boolean deprecated;
+    private String deprecationReason;
+
+    @ApiModelProperty("The build metadata for this component")
+    public BuildInfo getBuildInfo() {
+        return buildInfo;
+    }
+
+    public void setBuildInfo(BuildInfo buildInfo) {
+        this.buildInfo = buildInfo;
+    }
+
+    @ApiModelProperty("If this type represents a provider for an interface, 
this lists the APIs it implements")
+    public List<DefinedType> getProvidedApiImplementations() {
+        return (providedApiImplementations != null ? 
Collections.unmodifiableList(providedApiImplementations) : null);
+
+    }
+
+    public void setProvidedApiImplementations(List<DefinedType> 
providedApiImplementations) {
+        this.providedApiImplementations = providedApiImplementations;
+    }
+
+    @ApiModelProperty("A description of the component")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @ApiModelProperty("The tags associated with this type")
+    public Set<String> getTags() {
+        return (tags != null ? Collections.unmodifiableSet(tags) : null);
+    }
+
+    public void setTags(Set<String> tags) {
+        this.tags = tags;
+    }
+
+    @ApiModelProperty("Whether or not the component has been deprecated")
+    public Boolean getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(Boolean deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    @ApiModelProperty("If this component has been deprecated, this optional 
field can be used to provide an explanation")
+    public String getDeprecationReason() {
+        return deprecationReason;
+    }
+
+    public void setDeprecationReason(String deprecationReason) {
+        this.deprecationReason = deprecationReason;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ExtensionComponent that = (ExtensionComponent) o;
+
+        return new EqualsBuilder()
+                .appendSuper(super.equals(o))
+                .append(buildInfo, that.buildInfo)
+                .isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder(17, 37)
+                .appendSuper(super.hashCode())
+                .append(buildInfo)
+                .toHashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/Processor.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/Processor.java
 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/Processor.java
new file mode 100644
index 0000000..3c2856f
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/Processor.java
@@ -0,0 +1,92 @@
+/*
+ * 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.minifi.c2.model.extension;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+@ApiModel  // TODO Swagger docs description
+public class Processor extends ExtensionComponent {
+
+    private Map<String, PropertyDescriptor> propertyDescriptors;
+    private Boolean supportsDynamicProperties;
+    private String inputRequirement;
+
+    // TODO figure out the best way to include metadata for scheduling variants
+    // private Boolean supportsEventDriven;
+    // private Boolean supportsBatching;
+    private List<String> supportedSchedulingStrategies;
+    private String defaultSchedulingStrategy;
+    private Map<String, Map<String, String>> defaultValuesBySchedulingStrategy;
+
+
+    @ApiModelProperty("Descriptions of configuration properties applicable to 
this reporting task")
+    public Map<String, PropertyDescriptor> getPropertyDescriptors() {
+        return (propertyDescriptors != null ? 
Collections.unmodifiableMap(propertyDescriptors) : null);
+    }
+
+    public void setPropertyDescriptors(Map<String, PropertyDescriptor> 
propertyDescriptors) {
+        this.propertyDescriptors = propertyDescriptors;
+    }
+
+    @ApiModelProperty("Whether or not this processor makes use of dynamic 
(user-set) properties")
+    public Boolean getSupportsDynamicProperties() {
+        return supportsDynamicProperties;
+    }
+
+    public void setSupportsDynamicProperties(Boolean 
supportsDynamicProperties) {
+        this.supportsDynamicProperties = supportsDynamicProperties;
+    }
+
+    @ApiModelProperty("Any input requirements this processor has") // TODO, 
what is the format of this string?
+    public String getInputRequirement() {
+        return inputRequirement;
+    }
+
+    public void setInputRequirement(String inputRequirement) {
+        this.inputRequirement = inputRequirement;
+    }
+
+    @ApiModelProperty("A list of scheduling strategies supported by this 
processor")
+    public List<String> getSupportedSchedulingStrategies() {
+        return (supportedSchedulingStrategies != null ? 
Collections.unmodifiableList(supportedSchedulingStrategies) : null);
+    }
+
+    public void setSupportedSchedulingStrategies(List<String> 
supportedSchedulingStrategies) {
+        this.supportedSchedulingStrategies = supportedSchedulingStrategies;
+    }
+
+    @ApiModelProperty
+    public String getDefaultSchedulingStrategy() {
+        return defaultSchedulingStrategy;
+    }
+
+    public void setDefaultSchedulingStrategy(String defaultSchedulingStrategy) 
{
+        this.defaultSchedulingStrategy = defaultSchedulingStrategy;
+    }
+
+    @ApiModelProperty
+    public Map<String, Map<String, String>> 
getDefaultValuesBySchedulingStrategy() {
+        return (defaultValuesBySchedulingStrategy != null ? 
Collections.unmodifiableMap(defaultValuesBySchedulingStrategy) : null);
+    }
+
+    public void setDefaultValuesBySchedulingStrategy(Map<String, Map<String, 
String>> defaultValuesBySchedulingStrategy) {
+        this.defaultValuesBySchedulingStrategy = 
defaultValuesBySchedulingStrategy;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyAllowableValue.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyAllowableValue.java
 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyAllowableValue.java
new file mode 100644
index 0000000..e91d97b
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyAllowableValue.java
@@ -0,0 +1,75 @@
+/*
+ * 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.minifi.c2.model.extension;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+
+@ApiModel
+public class PropertyAllowableValue {
+
+    private String value;
+    private String displayName;
+    private String description;
+
+    @ApiModelProperty(value = "The internal value", required = true)
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @ApiModelProperty("The display name of the value, if different from the 
internal value")
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    @ApiModelProperty("The description of the value, e.g., the behavior it 
produces.")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (o == null || getClass() != o.getClass()) return false;
+
+        PropertyAllowableValue that = (PropertyAllowableValue) o;
+
+        return new EqualsBuilder()
+                .append(value, that.value)
+                .isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder(17, 37)
+                .append(value)
+                .toHashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyDescriptor.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyDescriptor.java
 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyDescriptor.java
new file mode 100644
index 0000000..21d1437
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/PropertyDescriptor.java
@@ -0,0 +1,118 @@
+/*
+ * 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.minifi.c2.model.extension;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Collections;
+import java.util.List;
+
+@ApiModel
+public class PropertyDescriptor {
+
+    private String name;
+    private String displayName;
+    private String description;
+    private List<PropertyAllowableValue> allowableValues;
+    private String defaultValue;
+    private Boolean required;
+    private Boolean sensitive;
+    private Boolean supportsEl;
+    private DefinedType typeProvidedByValue;
+
+    @ApiModelProperty(value = "The name of the property key", required = true)
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @ApiModelProperty("The display name of the property key, if different from 
the name")
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = displayName;
+    }
+
+    @ApiModelProperty("The description of what the property does")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @ApiModelProperty("A list of the allowable values for the property")
+    public List<PropertyAllowableValue> getAllowableValues() {
+        return (allowableValues != null ? 
Collections.unmodifiableList(allowableValues) : null);
+    }
+
+    public void setAllowableValues(List<PropertyAllowableValue> 
allowableValues) {
+        this.allowableValues = allowableValues;
+    }
+
+    @ApiModelProperty("The default value if a user-set value is not specified")
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @ApiModelProperty("Whether or not  the property is required for the 
component")
+    public Boolean getRequired() {
+        return required;
+    }
+
+    public void setRequired(Boolean required) {
+        this.required = required;
+    }
+
+    @ApiModelProperty("Whether or not  the value of the property is considered 
sensitive (e.g., passwords and keys)")
+    public Boolean getSensitive() {
+        return sensitive;
+    }
+
+    public void setSensitive(Boolean sensitive) {
+        this.sensitive = sensitive;
+    }
+
+    @ApiModelProperty("Whether or not the property supports using NiFi 
Expression Language in the value")
+    public Boolean getSupportsEl() {
+        return supportsEl;
+    }
+
+    public void setSupportsEl(Boolean supportsEl) {
+        this.supportsEl = supportsEl;
+    }
+
+    @ApiModelProperty
+    public DefinedType getTypeProvidedByValue() {
+        return typeProvidedByValue;
+    }
+
+    public void setTypeProvidedByValue(DefinedType typeProvidedByValue) {
+        this.typeProvidedByValue = typeProvidedByValue;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ReportingTask.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ReportingTask.java
 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ReportingTask.java
new file mode 100644
index 0000000..677d6ce
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-commons/src/main/java/org/apache/nifi/minifi/c2/model/extension/ReportingTask.java
@@ -0,0 +1,67 @@
+/*
+ * 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.minifi.c2.model.extension;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+@ApiModel
+public class ReportingTask extends ExtensionComponent {
+
+    private Map<String, PropertyDescriptor> propertyDescriptors;
+    private List<String> supportedSchedulingStrategies;
+    private String defaultSchedulingStrategy;
+    private Map<String, Map<String, String>> defaultValuesBySchedulingStrategy;
+
+    @ApiModelProperty("Descriptions of configuration properties applicable to 
this reporting task")
+    public Map<String, PropertyDescriptor> getPropertyDescriptors() {
+        return (propertyDescriptors != null ? 
Collections.unmodifiableMap(propertyDescriptors) : null);
+    }
+
+    public void setPropertyDescriptors(Map<String, PropertyDescriptor> 
propertyDescriptors) {
+        this.propertyDescriptors = propertyDescriptors;
+    }
+
+    @ApiModelProperty
+    public List<String> getSupportedSchedulingStrategies() {
+        return (supportedSchedulingStrategies != null ? 
Collections.unmodifiableList(supportedSchedulingStrategies) : null);
+    }
+
+    public void setSupportedSchedulingStrategies(List<String> 
supportedSchedulingStrategies) {
+        this.supportedSchedulingStrategies = supportedSchedulingStrategies;
+    }
+
+    @ApiModelProperty
+    public String getDefaultSchedulingStrategy() {
+        return defaultSchedulingStrategy;
+    }
+
+    public void setDefaultSchedulingStrategy(String defaultSchedulingStrategy) 
{
+        this.defaultSchedulingStrategy = defaultSchedulingStrategy;
+    }
+
+    @ApiModelProperty
+    public Map<String, Map<String, String>> 
getDefaultValuesBySchedulingStrategy() {
+        return (defaultValuesBySchedulingStrategy != null ? 
Collections.unmodifiableMap(defaultValuesBySchedulingStrategy) : null);
+    }
+
+    public void setDefaultValuesBySchedulingStrategy(Map<String, Map<String, 
String>> defaultValuesBySchedulingStrategy) {
+        this.defaultValuesBySchedulingStrategy = 
defaultValuesBySchedulingStrategy;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-framework/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-framework/pom.xml 
b/minifi-c2/minifi-c2-framework/pom.xml
index 09fe37a..464dd0e 100644
--- a/minifi-c2/minifi-c2-framework/pom.xml
+++ b/minifi-c2/minifi-c2-framework/pom.xml
@@ -76,7 +76,7 @@ limitations under the License.
         <dependency>
             <groupId>org.springframework.security</groupId>
             <artifactId>spring-security-ldap</artifactId>
-            <version>${spring.security.version}</version>
+            <version>${spring.security.ldap.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.springframework.security</groupId>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/minifi-c2-web-api/pom.xml 
b/minifi-c2/minifi-c2-web-api/pom.xml
index 1b6b485..046984a 100644
--- a/minifi-c2/minifi-c2-web-api/pom.xml
+++ b/minifi-c2/minifi-c2-web-api/pom.xml
@@ -27,6 +27,10 @@ limitations under the License.
     <artifactId>minifi-c2-web-api</artifactId>
     <packaging>war</packaging>
 
+    <properties>
+        <swagger.ui.version>3.12.0</swagger.ui.version>
+    </properties>
+
     <build>
         <resources>
             <resource>
@@ -45,9 +49,157 @@ limitations under the License.
                     <failOnMissingWebXml>false</failOnMissingWebXml>
                 </configuration>
             </plugin>
+            <plugin>
+                <!-- This plugin is for generating the a swagger.json as part 
of the build.
+                     It does not generate the swagger.json that is hosted by 
the web application. -->
+                <groupId>com.github.kongchen</groupId>
+                <artifactId>swagger-maven-plugin</artifactId>
+                <version>3.1.5</version>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <configuration>
+                            <apiSources>
+                                <apiSource>
+                                    <locations>
+                                        
<location>org.apache.nifi.minifi.c2.web.api</location>
+                                    </locations>
+                                    <schemes>
+                                        <scheme>http</scheme>
+                                        <scheme>https</scheme>
+                                    </schemes>
+                                    <basePath>/c2-api</basePath>
+                                    <info>
+                                        <title>MiNiFi C2 Server REST 
API</title>
+                                        <version>${project.version}</version>
+                                        <description>
+                                            This REST API provides the ability 
to command and control MiNiFi Agents
+                                        </description>
+                                        <contact>
+                                            <name>Apache MiNiFi</name>
+                                            <email>[email protected]</email>
+                                            <url>https://nifi.apache.org</url>
+                                        </contact>
+                                        <license>
+                                            
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
+                                            <name>Apache 2.0 License</name>
+                                        </license>
+                                    </info>
+                                    
<swaggerDirectory>${project.build.directory}/swagger-ui</swaggerDirectory>
+                                </apiSource>
+                            </apiSources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <!-- TODO add license/notice info for bundling the swagger-ui 
static assets in the web-api.war -->
+            <plugin>
+                <groupId>com.googlecode.maven-download-plugin</groupId>
+                <artifactId>download-maven-plugin</artifactId>
+                <version>1.2.1</version>
+                <executions>
+                    <execution>
+                        <id>download-swagger-ui</id>
+                        <!-- This plugin downloads swagger UI static assets 
during the build, to be
+                             served by the web app to render the dynamically 
generated Swagger spec.
+                             For offline development, or to build without the 
swagger UI, activate
+                             the "no-swagger-ui" maven profile during the 
build with the "-P" flag -->
+                        <goals>
+                            <goal>wget</goal>
+                        </goals>
+                        <configuration>
+                            <url>
+                                
https://github.com/swagger-api/swagger-ui/archive/v${swagger.ui.version}.tar.gz
+                            </url>
+                            <unpack>true</unpack>
+                            <outputDirectory>${project.build.directory}
+                            </outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>1.8</version>
+                <executions>
+                    <execution>
+                        <id>bundle-swagger-ui</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <tasks>
+                                <sequential>
+                                    <echo>Copy static Swagger UI files to 
target</echo>
+                                    <copy 
todir="${project.build.directory}/classes/static/swagger">
+                                        <fileset 
dir="${project.build.directory}/swagger-ui-${swagger.ui.version}/dist">
+                                            <include name="**"/>
+                                        </fileset>
+                                    </copy>
+                                    <echo>Rename 'index.html' to 
'ui.html'</echo>
+                                    <move 
file="${project.build.directory}/classes/static/swagger/index.html"
+                                          
tofile="${project.build.directory}/classes/static/swagger/ui.html"/>
+                                    <echo>Replace default swagger.json 
location</echo>
+                                    <replace 
token="http://petstore.swagger.io/v2/swagger.json";
+                                             
value="/minifi-c2-api/swagger.json"
+                                             
dir="${project.build.directory}/classes/static/swagger">
+                                        <include name="ui.html"/>
+                                    </replace>
+                                    <echo>Disable schema validation by 
removing validatorUrl</echo>
+                                    <replace 
token="https://online.swagger.io/validator";
+                                             value=""
+                                             
dir="${project.build.directory}/classes/static/swagger">
+                                        <include name="swagger-ui-bundle.js"/>
+                                        <include 
name="swagger-ui-standalone-preset.js"/>
+                                    </replace>
+                                </sequential>
+                            </tasks>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
+    <profiles>
+        <profile>
+            <id>no-swagger-ui</id>
+            <!-- Activate this profile with "-P no-swagger-ui" to disable the 
Swagger UI
+                 static assets from being downloaded and bundled with the web 
api WAR. -->
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>com.googlecode.maven-download-plugin</groupId>
+                        <artifactId>download-maven-plugin</artifactId>
+                        <version>1.2.1</version>
+                        <executions>
+                            <execution>
+                                <id>download-swagger-ui</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <version>1.8</version>
+                        <executions>
+                            <execution>
+                                <id>bundle-swagger-ui</id>
+                                <phase>none</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
     <dependencies>
         <!-- Project dependencies -->
         <dependency>
@@ -72,12 +224,13 @@ limitations under the License.
             <artifactId>spring-boot-starter-jersey</artifactId>
             <version>${spring.boot.version}</version>
         </dependency>
-        <!-- Exclude micrometer-core because it creates a class cast issue 
with logback, revisit later -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
             <version>${spring.boot.version}</version>
             <exclusions>
+                <!-- Exclude micrometer-core because it creates a
+                     class cast issue with logback, revisit later -->
                 <exclusion>
                     <groupId>io.micrometer</groupId>
                     <artifactId>micrometer-core</artifactId>
@@ -107,6 +260,19 @@ limitations under the License.
             <scope>provided</scope>
         </dependency>
 
+        <!-- Other dependencies -->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-jersey2-jaxrs</artifactId>
+            <version>${io.swagger.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
     </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/MinifiC2ApiApplication.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/MinifiC2ApiApplication.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/MinifiC2ApiApplication.java
index 706f532..8fcdaff 100644
--- 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/MinifiC2ApiApplication.java
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/MinifiC2ApiApplication.java
@@ -18,24 +18,39 @@ package org.apache.nifi.minifi.c2;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import 
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
 import 
org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
 
+import java.util.Properties;
+
 /**
- * Main class for starting the NiFi Registry Web API as a Spring Boot 
application.
+ * Main class for starting the MiNiFi C2 Web API as a Spring Boot application.
  *
  * This class is purposely in org.apache.nifi.minifi.c2 as that is the common 
base
  * package across other modules. Spring Boot will use the package of this 
class to
  * automatically scan for beans/config/entities/etc. and would otherwise 
require
  * configuring custom packages to scan in several different places.
- *
- * WebMvcAutoConfiguration is excluded because our web app is using Jersey in 
place of SpringMVC
  */
-@SpringBootApplication(exclude = WebMvcAutoConfiguration.class)
+@SpringBootApplication
 public class MinifiC2ApiApplication extends SpringBootServletInitializer {
 
     public static void main(String[] args) {
         SpringApplication.run(MinifiC2ApiApplication.class, args);
     }
 
+    @Override
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder 
application) {
+        final Properties defaultProperties = new Properties();
+
+        // Enable Actuator Endpoints
+        
defaultProperties.setProperty("management.endpoints.web.exposure.include", "*");
+        
defaultProperties.setProperty("management.endpoint.health.show-details", 
"always");
+
+        // Run Jersey as a filter instead of a servlet so that requests can be 
forwarded to other handlers (e.g., actuator, swagger-ui)
+        defaultProperties.setProperty("spring.jersey.type", "filter");
+
+        return application
+                .sources(MinifiC2ApiApplication.class)
+                .properties(defaultProperties);
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/MinifiC2ResourceConfig.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/MinifiC2ResourceConfig.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/MinifiC2ResourceConfig.java
index 603dcfc..b13f3bf 100644
--- 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/MinifiC2ResourceConfig.java
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/MinifiC2ResourceConfig.java
@@ -16,12 +16,22 @@
  */
 package org.apache.nifi.minifi.c2.web;
 
+import io.swagger.jaxrs.config.BeanConfig;
+import io.swagger.jaxrs.listing.ApiListingResource;
+import io.swagger.jaxrs.listing.SwaggerSerializers;
+import org.apache.nifi.minifi.c2.properties.C2Properties;
+import org.apache.nifi.minifi.c2.web.api.AgentClassResource;
+import org.apache.nifi.minifi.c2.web.api.AgentManifestResource;
+import org.apache.nifi.minifi.c2.web.api.C2ProtocolResource;
 import org.apache.nifi.minifi.c2.web.api.TestResource;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.server.ServerProperties;
 import org.glassfish.jersey.server.filter.HttpMethodOverrideFilter;
+import org.glassfish.jersey.servlet.ServletProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 
 import javax.servlet.ServletContext;
@@ -35,7 +45,10 @@ public class MinifiC2ResourceConfig extends ResourceConfig {
 
     private static final Logger logger = 
LoggerFactory.getLogger(MinifiC2ResourceConfig.class);
 
-    public MinifiC2ResourceConfig(@Context ServletContext servletContext) {
+    @Value("application.version")
+    String restApiVersion;
+
+    public MinifiC2ResourceConfig(@Context ServletContext servletContext, 
@Autowired C2Properties properties) {
         // register filters
         register(HttpMethodOverrideFilter.class);
 
@@ -43,8 +56,16 @@ public class MinifiC2ResourceConfig extends ResourceConfig {
         packages("org.apache.nifi.minifi.c2.web.mapper");
 
         // register endpoints
-        logger.info("Registering {}", TestResource.class.getName());
-        register(TestResource.class);
+        Class[] resources = {
+                AgentClassResource.class,
+                AgentManifestResource.class,
+                C2ProtocolResource.class,
+                TestResource.class
+        };
+        for (Class resourceClass : resources) {
+            logger.info("Registering {}", resourceClass.getName());
+            register(resourceClass);
+        }
 
         // include bean validation errors in response
         property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
@@ -54,6 +75,39 @@ public class MinifiC2ResourceConfig extends ResourceConfig {
         // If this value needs to be changed, Kerberos authentication needs to 
move to filter chain
         // so it can directly set the HttpServletResponse instead of 
indirectly through a JAX-RS Response
         property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
+
+        // configure jersey to ignore resource paths for actuator and 
swagger-ui
+        property(ServletProperties.FILTER_STATIC_CONTENT_REGEX, 
"/(actuator|swagger/).*");
+
+        // configure swagger and register swagger endpoints
+        configureSwagger(properties);
+    }
+
+    private void configureSwagger(C2Properties properties) {
+        register(ApiListingResource.class);
+        register(SwaggerSerializers.class);
+
+        BeanConfig swaggerConfig = new BeanConfig();
+        swaggerConfig.setConfigId("minifi-c2-swagger-config");
+        swaggerConfig.setResourcePackage("org.apache.nifi.minifi.c2");  // the 
base pkgs to scan for swagger annotated resources. TODO add actuator to swagger 
docs?
+        swaggerConfig.setScan(true);
+        swaggerConfig.setTitle("MiNiFi C2 Server");
+        swaggerConfig.setDescription("A command and control server for MiNiFi 
agents");
+        swaggerConfig.setContact("[email protected]");
+        swaggerConfig.setLicense("Apache Software License 2.0");
+        
swaggerConfig.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0";);
+
+        String[] schemes = properties.isTlsEnabled() ? new String[]{"https"} : 
new String[]{"http"};
+        swaggerConfig.setSchemes(schemes);
+
+        String host = properties.getHost() != null ? properties.getHost() : 
"localhost";
+        if (properties.getPort() != null) {
+            host += String.format(":%d", properties.getPort());
+        }
+        swaggerConfig.setHost(host);
+        swaggerConfig.setBasePath("/minifi-c2-api");
+
+        // 
SwaggerConfigLocator.getInstance().putConfig(SwaggerContextService.CONFIG_ID_DEFAULT,
 swaggerConfig);
     }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentClassResource.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentClassResource.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentClassResource.java
new file mode 100644
index 0000000..740951c
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentClassResource.java
@@ -0,0 +1,132 @@
+/*
+ * 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.minifi.c2.web.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.apache.nifi.minifi.c2.model.AgentClass;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.NotSupportedException;
+import javax.ws.rs.PATCH;
+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.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Component
+@Path("/agent-classes")
+@Api(value = "Agent Classes", description = "Register and manage agent class 
definitions")
+public class AgentClassResource {
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Register a MiNiFi agent class with this C2 server",
+            notes = "This can also be done with a heartbeat, which will 
register a MiNiFi agent class the first time it is seen in a heartbeat.",
+            response = AgentClass.class
+    )
+    public Response createAgentClass(
+            @ApiParam(value = "The class to create", required = true)
+                AgentClass agentClass) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get all MiNiFi agent classes that are registered with 
this C2 server",
+            response = AgentClass.class,
+            responseContainer = "List"
+    )
+    public Response getAgentClasses() {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @GET
+    @Path("/{name}")
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get a MiNiFi agent class that is registered with this C2 
server",
+            response = AgentClass.class
+    )
+    public Response getAgentClass(
+            @PathParam("name")
+            @ApiParam("The name of the class to retrieve")
+                String name) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @PUT
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Create or update a MiNiFi agent class",
+            notes = "This can also be done with a heartbeat, which will 
register a MiNiFi agent the first time it heartbeats.",
+            response = AgentClass.class
+    )
+    @Path("/{name}")
+    public Response upsertAgentClass(
+            @PathParam("name")
+            @ApiParam(value = "The name of the class")
+                String name,
+            @ApiParam(value = "The metadata of the class to associate with the 
given name. If not specified, a class with a name and no other attributes will 
be set.")
+                AgentClass agentClass) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @PATCH
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Update the metadata of a MiNiFi agent class",
+            notes = "This can also be done with a heartbeat, which will 
register a MiNiFi agent the first time it heartbeats.",
+            response = AgentClass.class
+    )
+    @Path("/{name}")
+    public Response updateAgentClass(
+            @PathParam("name")
+            @ApiParam(value = "The name of the class to update")
+                String name,
+            @ApiParam(value = "A partial metadata object to update.", required 
= true)
+                AgentClass agentClass) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @DELETE
+    @Path("/{name}")
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Delete a MiNiFi agent class",
+            response = AgentClass.class
+    )
+    public Response deleteAgentClass(
+            @PathParam("name")
+            @ApiParam("The name of the class to delete")
+                String name) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentManifestResource.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentManifestResource.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentManifestResource.java
new file mode 100644
index 0000000..214952b
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/AgentManifestResource.java
@@ -0,0 +1,93 @@
+/*
+ * 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.minifi.c2.web.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.apache.nifi.minifi.c2.model.AgentManifest;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.NotSupportedException;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/agent-manifests")
+@Api(value = "Agent Manifests", description = "Register and manage agent 
manifest definitions")
+public class AgentManifestResource {
+
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Upload an agent manifest",
+            response = AgentManifest.class)
+    public Response createAgentManifest(
+            @QueryParam("class")
+            @ApiParam("Optionally, a class label to associate with the 
manifest being uploaded")
+                    String className,
+            @ApiParam
+                    AgentManifest agentManifest) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "Get all agent manifests",
+            response = AgentManifest.class,
+            responseContainer = "List")
+            // TODO, pagination
+    public Response getAgentManifests(
+            @QueryParam("class")
+            @ApiParam("Optionally, filter the results to match a class label")
+                    String className) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/{id}")
+    @ApiOperation(
+            value = "Get the agent manifest specified by the id",
+            response = AgentManifest.class)
+    public Response getAgentManifest(
+            @PathParam("id")
+            @ApiParam
+                    String id) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+    @DELETE
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/{id}")
+    @ApiOperation(
+            value = "Delete the agent manifest specified by id",
+            response = AgentManifest.class)
+    public Response deleteAgentManifest(
+            @PathParam("id")
+            @ApiParam
+                    String id) {
+        throw new NotSupportedException("This method is not yet implemented 
for this resource.");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/ApplicationResource.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/ApplicationResource.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/ApplicationResource.java
new file mode 100644
index 0000000..bdf50bf
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/ApplicationResource.java
@@ -0,0 +1,32 @@
+/*
+ * 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.minifi.c2.web.api;
+
+import org.apache.nifi.minifi.c2.core.service.C2Service;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * A base resource type for all resources of the MiNiFi C2 Web API
+ */
+public abstract class ApplicationResource {
+
+    protected C2Service c2Service;
+
+    @Autowired
+    public ApplicationResource(C2Service c2Service) {
+        this.c2Service = c2Service;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/C2ProtocolResource.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/C2ProtocolResource.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/C2ProtocolResource.java
new file mode 100644
index 0000000..5f9de0b
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/C2ProtocolResource.java
@@ -0,0 +1,119 @@
+/*
+ * 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.minifi.c2.web.api;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.nifi.minifi.c2.model.C2Heartbeat;
+import org.apache.nifi.minifi.c2.model.C2HeartbeatResponse;
+import org.apache.nifi.minifi.c2.model.C2OperationAck;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Component
+@Path("/c2-protocol")
+@Api(value = "C2 Protocol", description = "An HTTP RESTful implementation of 
the MiNiFi C2 protocol.")
+public class C2ProtocolResource {
+
+    @POST
+    @Path("/heartbeat")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "An endpoint for a MiNiFi Agent to send a heartbeat to the 
C2 server",
+            response = C2HeartbeatResponse.class
+    )
+    @ApiResponses({
+            @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400) 
})
+    public Response heartbeat(
+            @ApiParam(required = true)
+                    C2Heartbeat heartbeat) {
+
+        // TODO process heartbeat
+        // Processing a heartbeat will include things such as:
+        //  - Creating / updating AgentClassManifest definitions based on label
+        //  - Updating firstSeen/lastSeen timestamps, metrics, 
device/agent/flow info and status
+        //  - Resolving any pending/queued operations (e.g., flow updates) to 
send to the agent in the HeartbeatResponse
+        // These processing steps will be done in the service later, not this 
HTTP Rest endpoint, as we plan to support protocols in addition to HTTP one day.
+
+        C2HeartbeatResponse heartbeatResponse = new C2HeartbeatResponse();
+
+        return Response.ok(heartbeatResponse).build();
+    }
+
+    @POST
+    @Path("/heartbeat/test-request")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "A test endpoint for a MiNiFi Agent to send a heartbeat to 
the C2 server",
+            notes = "The body of the request will be deserialized and 
validated, then re-serialized and returned in the response body.",
+            // hidden = true,
+            response = C2HeartbeatResponse.class
+    )
+    @ApiResponses({
+            @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400) 
})
+    public Response heartbeatTest(
+            @ApiParam(required = true)
+                    C2Heartbeat heartbeat) {
+        return Response.ok(heartbeat).build();
+    }
+
+    @POST
+    @Path("/acknowledge")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "An endpoint for a MiNiFi Agent to send an operation 
acknowledgement to the C2 server"
+    )
+    @ApiResponses({
+            @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400) 
})
+    public Response acknowledge(
+            @ApiParam(required = true)
+                    C2OperationAck c2OperationAck) {
+
+        // TODO process ack
+
+        return Response.ok().build();
+    }
+
+    @POST
+    @Path("/acknowledge/test-request")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @ApiOperation(
+            value = "A test endpoint for a MiNiFi Agent to send an ack to the 
C2 server",
+            notes = "The body of the request will be deserialized and 
validated, then re-serialized and returned in the response body.",
+            // hidden = true,
+            response = C2OperationAck.class
+    )
+    @ApiResponses({
+            @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400) 
})
+    public Response acknowledgeTest(
+            @ApiParam(required = true)
+                C2OperationAck c2OperationAck) {
+        return Response.ok(c2OperationAck).build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/TestResource.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/TestResource.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/TestResource.java
index 85a0dbd..e8982c0 100644
--- 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/TestResource.java
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/api/TestResource.java
@@ -21,7 +21,6 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
-import io.swagger.annotations.Authorization;
 import org.apache.nifi.minifi.c2.core.service.C2Service;
 import org.apache.nifi.minifi.c2.model.TestObject;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -41,11 +40,10 @@ import javax.ws.rs.core.Response;
 import java.util.List;
 
 @Component
-@Path("/test")
+@Path("/tests")
 @Api(
-        value = "test",
-        description = "An example/test resource.",
-        authorizations = { @Authorization("Authorization") }
+        value = "Tests",
+        description = "An example/test resource."
 )
 public class TestResource {
 
@@ -74,7 +72,6 @@ public class TestResource {
     }
 
     @GET
-    @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
     @ApiOperation(
             value = "Gets all test objects",
@@ -88,7 +85,6 @@ public class TestResource {
 
     @GET
     @Path("{id}")
-    @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
     @ApiOperation(
             value = "Gets a test object",
@@ -132,7 +128,6 @@ public class TestResource {
 
     @DELETE
     @Path("{id}")
-    @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.APPLICATION_JSON)
     @ApiOperation(
             value = "Deletes a test object",

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/mapper/NotSupportedExceptionMapper.java
----------------------------------------------------------------------
diff --git 
a/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/mapper/NotSupportedExceptionMapper.java
 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/mapper/NotSupportedExceptionMapper.java
new file mode 100644
index 0000000..e9b5500
--- /dev/null
+++ 
b/minifi-c2/minifi-c2-web-api/src/main/java/org/apache/nifi/minifi/c2/web/mapper/NotSupportedExceptionMapper.java
@@ -0,0 +1,43 @@
+/*
+ * 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.minifi.c2.web.mapper;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.NotSupportedException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+@Component
+@Provider
+public class NotSupportedExceptionMapper implements 
ExceptionMapper<NotSupportedException> {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(NotSupportedExceptionMapper.class);
+
+    @Override
+    public Response toResponse(NotSupportedException exception) {
+        logger.info("{}. Returning {} response.", exception, 
Response.Status.NOT_IMPLEMENTED);
+        logger.debug("", exception);
+
+        return Response.status(Response.Status.NOT_IMPLEMENTED)
+                .entity(exception.getMessage())
+                .type("text/plain")
+                .build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-c2/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-c2/pom.xml b/minifi-c2/pom.xml
index 626fcb1..904a50d 100644
--- a/minifi-c2/pom.xml
+++ b/minifi-c2/pom.xml
@@ -40,6 +40,10 @@ limitations under the License.
         <module>minifi-c2-web-api</module>
     </modules>
 
+    <properties>
+        <io.swagger.version>1.5.18</io.swagger.version>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/minifi-nar-bundles/minifi-standard-nar/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-nar-bundles/minifi-standard-nar/pom.xml 
b/minifi-nar-bundles/minifi-standard-nar/pom.xml
index adf15e2..c0ac5b8 100644
--- a/minifi-nar-bundles/minifi-standard-nar/pom.xml
+++ b/minifi-nar-bundles/minifi-standard-nar/pom.xml
@@ -65,6 +65,7 @@ limitations under the License.
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
+            <version>${guava.version}</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/631b5992/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index a35e578..629ed11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -149,13 +149,16 @@ limitations under the License.
         <org.slf4j.version>1.7.25</org.slf4j.version>
         <org.apache.nifi.version>1.5.0</org.apache.nifi.version>
         <logback.version>1.1.3</logback.version>
+        <guava.version>18.0</guava.version>
         <flyway.version>4.2.0</flyway.version>
         <jax.rs.api.version>2.1</jax.rs.api.version>
         <jackson.version>2.9.2</jackson.version>
         <jetty.version>9.4.3.v20170317</jetty.version>
         <jersey.version>2.26</jersey.version>
-        <spring.boot.version>2.0.0.M7</spring.boot.version>
-        <spring.security.version>5.0.0.RELEASE</spring.security.version>
+        <spring.boot.version>2.0.0.RELEASE</spring.boot.version>
+        <spring.version>5.0.4.RELEASE</spring.version>
+        <spring.security.version>5.0.4.RELEASE</spring.security.version>
+        
<spring.security.ldap.version>5.0.3.RELEASE</spring.security.ldap.version>
     </properties>
 
     <dependencies>
@@ -831,33 +834,6 @@ limitations under the License.
             </dependency>
             <dependency>
                 <groupId>com.sun.jersey.contribs</groupId>
-                <artifactId>jersey-spring</artifactId>
-                <version>1.19.4</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.springframework</groupId>
-                        <artifactId>spring-web</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.springframework</groupId>
-                        <artifactId>spring-core</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.springframework</groupId>
-                        <artifactId>spring-aop</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.springframework</groupId>
-                        <artifactId>spring-context</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.springframework</groupId>
-                        <artifactId>spring-beans</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>com.sun.jersey.contribs</groupId>
                 <artifactId>jersey-multipart</artifactId>
                 <version>${jersey.version}</version>
             </dependency>
@@ -975,11 +951,6 @@ limitations under the License.
             </dependency>
 
             <dependency>
-                <groupId>com.google.guava</groupId>
-                <artifactId>guava</artifactId>
-                <version>18.0</version>
-            </dependency>
-            <dependency>
                 <groupId>com.h2database</groupId>
                 <artifactId>h2</artifactId>
                 <version>1.3.176</version>
@@ -1010,11 +981,6 @@ limitations under the License.
                 <version>${jackson.version}</version>
             </dependency>
             <dependency>
-                <groupId>io.swagger</groupId>
-                <artifactId>swagger-annotations</artifactId>
-                <version>1.5.16</version>
-            </dependency>
-            <dependency>
                 <groupId>org.apache.spark</groupId>
                 <artifactId>spark-streaming_2.10</artifactId>
                 <version>1.6.0</version>

Reply via email to