simonbence commented on a change in pull request #5088:
URL: https://github.com/apache/nifi/pull/5088#discussion_r662050885



##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapConfiguration.java
##########
@@ -0,0 +1,38 @@
+/*
+ * 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.snmp.configuration;
+
+public interface TrapConfiguration {

Review comment:
       Please provide JavaDOC

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapV2cV3Configuration.java
##########
@@ -0,0 +1,63 @@
+/*
+ * 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.snmp.configuration;
+
+public class TrapV2cV3Configuration implements TrapConfiguration {
+
+    private final String trapOidValue;
+    private final int sysUpTime;
+
+    public TrapV2cV3Configuration(final String trapOidValue, final int 
sysUpTime) {
+        this.trapOidValue = trapOidValue;
+        this.sysUpTime = sysUpTime;
+    }
+
+    @Override
+    public String getTrapOidValue() {
+        return trapOidValue;
+    }
+
+    @Override
+    public int getSysUpTime() {
+        return sysUpTime;
+    }
+
+    @Override
+    public String getEnterpriseOid() {
+        throw new UnsupportedOperationException("Enterprise OID is SNMPv1 
specific property.");

Review comment:
       This looks a pretty unlucky way to approach. If there are such a 
differences between the different versions, it would be better to avoid shared 
interface (or at least not using a facade interface tries to cover all)

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/SNMPConfiguration.java
##########
@@ -104,4 +111,95 @@ public String getSecurityLevel() {
     public String getCommunityString() {
         return communityString;
     }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private String managerPort = "0";
+        private String targetHost;
+        private String targetPort;
+        private int retries;
+        private int timeout = 500;
+        private int version;
+        private String authProtocol;
+        private String authPassphrase;
+        private String privacyProtocol;
+        private String privacyPassphrase;
+        private String securityName;
+        private String securityLevel;
+        private String communityString;
+
+        public Builder setManagerPort(final String managerPort) {
+            this.managerPort = managerPort;
+            return this;
+        }
+
+        public Builder setTargetHost(final String targetHost) {
+            this.targetHost = targetHost;
+            return this;
+        }
+
+        public Builder setTargetPort(final String targetPort) {
+            this.targetPort = targetPort;
+            return this;
+        }
+
+        public Builder setRetries(final int retries) {
+            this.retries = retries;
+            return this;
+        }
+
+        public Builder setTimeout(final int timeout) {
+            this.timeout = timeout;
+            return this;
+        }
+
+        public Builder setVersion(final int version) {
+            this.version = version;
+            return this;
+        }
+
+        public Builder setAuthProtocol(final String authProtocol) {
+            this.authProtocol = authProtocol;
+            return this;
+        }
+
+        public Builder setAuthPassphrase(final String authPassphrase) {
+            this.authPassphrase = authPassphrase;
+            return this;
+        }
+
+        public Builder setPrivacyProtocol(final String privacyProtocol) {
+            this.privacyProtocol = privacyProtocol;
+            return this;
+        }
+
+        public Builder setPrivacyPassphrase(final String privacyPassphrase) {
+            this.privacyPassphrase = privacyPassphrase;
+            return this;
+        }
+
+        public Builder setSecurityName(final String securityName) {
+            this.securityName = securityName;
+            return this;
+        }
+
+        public Builder setSecurityLevel(final String securityLevel) {
+            this.securityLevel = securityLevel;
+            return this;
+        }
+
+        public Builder setCommunityString(String communityString) {
+            this.communityString = communityString;
+            return this;
+        }
+
+        public SNMPConfiguration build() {

Review comment:
       Is not any validation necessary? For example: is there any mandatory 
value must be set before building?

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapV1Configuration.java
##########
@@ -0,0 +1,111 @@
+/*
+ * 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.snmp.configuration;
+
+import com.google.common.base.Preconditions;
+
+public final class TrapV1Configuration implements TrapConfiguration {
+
+    private final String enterpriseOid;
+    private final String agentAddress;
+    private final int genericTrapType;
+    private final Integer specificTrapType;
+    private final int timeStamp;
+
+    public TrapV1Configuration(final Builder builder) {

Review comment:
       As this is highly coupled with the builder, it would be better to make 
this private

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/factory/CompositeSNMPFactory.java
##########
@@ -20,51 +20,40 @@
 import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
 import org.snmp4j.Snmp;
 import org.snmp4j.Target;
+import org.snmp4j.mp.SnmpConstants;
 
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Optional;
 
 public class CompositeSNMPFactory implements SNMPFactory {
 
     private static final String INVALID_SNMP_VERSION = "SNMP version is not 
supported.";
-    private static final List<SNMPFactory> FACTORIES;
+    private static final Map<Integer, SNMPFactory> FACTORIES;
 
     static {
-        final List<SNMPFactory> factories = Arrays.asList(new V1SNMPFactory(), 
new V2cSNMPFactory(), new V3SNMPFactory());
-        FACTORIES = Collections.unmodifiableList(factories);
-    }
-
-    @Override
-    public boolean supports(final int version) {
-        return !getMatchingFactory(version).isPresent();
+        final Map<Integer, SNMPFactory> factories = new HashMap<>();
+        factories.put(SnmpConstants.version1, new V1SNMPFactory());
+        factories.put(SnmpConstants.version2c, new V2cSNMPFactory());
+        factories.put(SnmpConstants.version3, new V3SNMPFactory());
+        FACTORIES = Collections.unmodifiableMap(factories);
     }
 
     @Override
     public Snmp createSnmpManagerInstance(final SNMPConfiguration 
configuration) {
-        final Optional<SNMPFactory> factory = 
getMatchingFactory(configuration.getVersion());
-        if (!factory.isPresent()) {
-            throw new InvalidSnmpVersionException(INVALID_SNMP_VERSION);
-        }
-        return factory.get().createSnmpManagerInstance(configuration);
+        final SNMPFactory factory = 
getMatchingFactory(configuration.getVersion());
+        return factory.createSnmpManagerInstance(configuration);
     }
 
     @Override
-    public Target createTargetInstance(final SNMPConfiguration configuration) {
-        final Optional<SNMPFactory> factory = 
getMatchingFactory(configuration.getVersion());
-        if (!factory.isPresent()) {
-            throw new InvalidSnmpVersionException(INVALID_SNMP_VERSION);
-        }
-        return factory.get().createTargetInstance(configuration);
+    public Target createTargetInstance(SNMPConfiguration configuration) {

Review comment:
       Please be consistent with the usage of "final" on the method arguments. 
Other methods have them, so please follow the local pattern

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/factory/ListenTrapSNMPFactory.java
##########
@@ -0,0 +1,35 @@
+/*
+ * 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.snmp.factory;
+
+import org.apache.nifi.snmp.configuration.SNMPConfiguration;
+import org.snmp4j.Snmp;
+import org.snmp4j.Target;
+
+public class ListenTrapSNMPFactory extends AbstractSNMPFactory implements 
SNMPFactory {

Review comment:
       As the `SNMPFactory` implementations are distinguished by version, this 
is kind of strange. Especially the this makes me wonder which version the 
`ListenTrap` is from?

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapV2cV3Configuration.java
##########
@@ -0,0 +1,63 @@
+/*
+ * 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.snmp.configuration;
+
+public class TrapV2cV3Configuration implements TrapConfiguration {
+
+    private final String trapOidValue;
+    private final int sysUpTime;
+
+    public TrapV2cV3Configuration(final String trapOidValue, final int 
sysUpTime) {

Review comment:
       It's minor, but I see some asymmetry with this: TrapV1 uses a builder 
and this is being called directly. I would propose an approach like: use a 
builder without version and when you create the actual config, version specific 
builder methods might work well 

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/StandardSNMPRequestHandler.java
##########
@@ -44,9 +46,19 @@
 
 final class StandardSNMPRequestHandler implements SNMPRequestHandler {
 
+    private static final String INVALID_FLOWFILE_EXCEPTION_MESSAGE = "Could 
not read the variable bindings from the " +
+            "flowfile. Please, add the OIDs to set in separate properties. 
E.g. Property name: snmp$1.3.6.1.2.1.1.1.0 " +
+            "Value: Example value. ";
+
+    private static final String REQUEST_TIMEOUT_EXCEPTION_TEMPLATE = "Request 
timed out. Please check if (1). the " +

Review comment:
       "Please check" might not be the luckiest phrasing. Maybe "Usually the 
following things might cause this"

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/SNMPConfiguration.java
##########
@@ -104,4 +111,95 @@ public String getSecurityLevel() {
     public String getCommunityString() {
         return communityString;
     }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private String managerPort = "0";
+        private String targetHost;
+        private String targetPort;
+        private int retries;
+        private int timeout = 500;

Review comment:
       Please incorporate the unit, for example "timeoutInMs"

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapConfiguration.java
##########
@@ -0,0 +1,38 @@
+/*
+ * 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.snmp.configuration;
+
+public interface TrapConfiguration {
+
+    // SNMPv1 specific
+    String getEnterpriseOid();

Review comment:
       If it is specific to SNMPv1, would it be possible to separate it from 
the generic methods? (child interface or such a thing) - Especially that 
implementations are version specific

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/SNMPConfiguration.java
##########
@@ -104,4 +111,95 @@ public String getSecurityLevel() {
     public String getCommunityString() {
         return communityString;
     }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private String managerPort = "0";

Review comment:
       I might move the value to a constant with a name like "WILDCARD_PORT" or 
something communicates the intention

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapV1Configuration.java
##########
@@ -0,0 +1,111 @@
+/*
+ * 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.snmp.configuration;
+
+import com.google.common.base.Preconditions;
+
+public final class TrapV1Configuration implements TrapConfiguration {
+
+    private final String enterpriseOid;
+    private final String agentAddress;
+    private final int genericTrapType;
+    private final Integer specificTrapType;
+    private final int timeStamp;
+
+    public TrapV1Configuration(final Builder builder) {
+        Preconditions.checkNotNull(builder.enterpiseOid);

Review comment:
       I think, these checks might be better in the `build()` method (as this 
is the only constructor).

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/factory/AbstractSNMPFactory.java
##########
@@ -35,22 +35,24 @@
 public abstract class AbstractSNMPFactory {
 
     private static final Logger logger = 
LoggerFactory.getLogger(AbstractSNMPFactory.class);
+    private static final String LOCALHOST = "127.0.0.1";
 
     protected AbstractSNMPFactory() {
         // hide implicit constructor
     }
 
-    protected static Snmp createSnmpClient() {
-        final Snmp snmp;
+    protected static Snmp createSimpleSnmpManager(SNMPConfiguration 
configuration) {
+        final String managerAddress = LOCALHOST + "/" + 
configuration.getManagerPort();
+        final Snmp snmpManager;
         try {
-            snmp = new Snmp(new DefaultUdpTransportMapping());
-            snmp.listen();
-            return snmp;
+            snmpManager = new Snmp(new DefaultUdpTransportMapping(new 
UdpAddress(managerAddress)));
+            snmpManager.listen();
         } catch (IOException e) {
-            final String errorMessage = "Creating SNMP client failed.";
+            final String errorMessage = "Creating SNMP manager failed.";
             logger.error(errorMessage, e);
             throw new CreateSNMPClientException(errorMessage);

Review comment:
       You swallow the original exception by doing this. Please pass `e` as an 
argument of the thrown exception. I would think, the best would be passing `e` 
_instead_ of the message because the message itself does not provide additional 
information over the type of the exception. (And by doing that you can spare 
the error message local variable as well)

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SNMPRequestHandlerFactory.java
##########
@@ -26,9 +26,9 @@
 
     public static SNMPRequestHandler createStandardRequestHandler(final 
SNMPConfiguration configuration) {
         final SNMPFactory snmpFactory = new CompositeSNMPFactory();
-        final Snmp snmpClient = 
snmpFactory.createSnmpManagerInstance(configuration);
+        final Snmp snmpManager = 
snmpFactory.createSnmpManagerInstance(configuration);

Review comment:
       As this used exclusively in `AbstractSNMPProcessor`, would not it make 
sense to reorganise and move this code into a method within it?

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/factory/CompositeSNMPFactory.java
##########
@@ -20,51 +20,40 @@
 import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
 import org.snmp4j.Snmp;
 import org.snmp4j.Target;
+import org.snmp4j.mp.SnmpConstants;
 
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Optional;
 
 public class CompositeSNMPFactory implements SNMPFactory {
 
     private static final String INVALID_SNMP_VERSION = "SNMP version is not 
supported.";
-    private static final List<SNMPFactory> FACTORIES;
+    private static final Map<Integer, SNMPFactory> FACTORIES;
 
     static {
-        final List<SNMPFactory> factories = Arrays.asList(new V1SNMPFactory(), 
new V2cSNMPFactory(), new V3SNMPFactory());
-        FACTORIES = Collections.unmodifiableList(factories);
-    }
-
-    @Override
-    public boolean supports(final int version) {
-        return !getMatchingFactory(version).isPresent();
+        final Map<Integer, SNMPFactory> factories = new HashMap<>();
+        factories.put(SnmpConstants.version1, new V1SNMPFactory());
+        factories.put(SnmpConstants.version2c, new V2cSNMPFactory());
+        factories.put(SnmpConstants.version3, new V3SNMPFactory());
+        FACTORIES = Collections.unmodifiableMap(factories);
     }
 
     @Override
     public Snmp createSnmpManagerInstance(final SNMPConfiguration 
configuration) {
-        final Optional<SNMPFactory> factory = 
getMatchingFactory(configuration.getVersion());
-        if (!factory.isPresent()) {
-            throw new InvalidSnmpVersionException(INVALID_SNMP_VERSION);
-        }
-        return factory.get().createSnmpManagerInstance(configuration);
+        final SNMPFactory factory = 
getMatchingFactory(configuration.getVersion());
+        return factory.createSnmpManagerInstance(configuration);
     }
 
     @Override
-    public Target createTargetInstance(final SNMPConfiguration configuration) {
-        final Optional<SNMPFactory> factory = 
getMatchingFactory(configuration.getVersion());
-        if (!factory.isPresent()) {
-            throw new InvalidSnmpVersionException(INVALID_SNMP_VERSION);
-        }
-        return factory.get().createTargetInstance(configuration);
+    public Target createTargetInstance(SNMPConfiguration configuration) {
+        final SNMPFactory factory = 
getMatchingFactory(configuration.getVersion());
+        return factory.createTargetInstance(configuration);
     }
 
-    private Optional<SNMPFactory> getMatchingFactory(final int version) {
-        for (final SNMPFactory factory : FACTORIES) {
-            if (factory.supports(version)) {
-                return Optional.of(factory);
-            }
-        }
-        return Optional.empty();
+    private SNMPFactory getMatchingFactory(final int version) {
+        return Optional.ofNullable(FACTORIES.get(version))
+                .orElseThrow(() -> new 
InvalidSnmpVersionException(INVALID_SNMP_VERSION));

Review comment:
       It would be good to include the actual version argument into the 
exception's message

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/SendTrapSNMP.java
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.snmp.processors;
+
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.snmp.configuration.TrapConfiguration;
+import org.apache.nifi.snmp.configuration.TrapV1Configuration;
+import org.apache.nifi.snmp.configuration.TrapV2cV3Configuration;
+import org.apache.nifi.snmp.utils.SNMPUtils;
+import org.snmp4j.mp.SnmpConstants;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Receiving data from configured SNMP agent which, upon each invocation of
+ * {@link #onTrigger(ProcessContext, ProcessSession)} method, will construct a
+ * {@link FlowFile} containing in its properties the information retrieved.
+ * The output {@link FlowFile} won't have any content.
+ */
+@Tags({"snmp", "send", "trap"})
+@InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
+@CapabilityDescription("Sends information to SNMP Manager.")
+public class SendTrapSNMP extends AbstractSNMPProcessor {
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_0 = new 
AllowableValue("0", "Cold Start",

Review comment:
       As nothing else uses these please make them `private`. Also, some more 
descriptive name would make readability better. Something like 
`GENERAIC_TRAP_WARM_START`.

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SNMPTrapReceiverHandler.java
##########
@@ -0,0 +1,106 @@
+/*
+ * 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.snmp.operations;
+
+import com.alibaba.fastjson.JSON;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSessionFactory;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.snmp.configuration.SNMPConfiguration;
+import org.apache.nifi.snmp.dto.UserDetails;
+import org.apache.nifi.snmp.exception.CloseSNMPManagerException;
+import org.apache.nifi.snmp.factory.ListenTrapSNMPFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.snmp4j.Snmp;
+import org.snmp4j.mp.MPv3;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.security.SecurityModels;
+import org.snmp4j.security.SecurityProtocols;
+import org.snmp4j.security.USM;
+import org.snmp4j.security.UsmUser;
+import org.snmp4j.smi.Integer32;
+import org.snmp4j.smi.OctetString;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Scanner;
+
+public class SNMPTrapReceiverHandler {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(StandardSNMPRequestHandler.class);

Review comment:
       Log should be for `SNMPTrapReceiverHandler`

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/SendTrapSNMP.java
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.snmp.processors;
+
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.snmp.configuration.TrapConfiguration;
+import org.apache.nifi.snmp.configuration.TrapV1Configuration;
+import org.apache.nifi.snmp.configuration.TrapV2cV3Configuration;
+import org.apache.nifi.snmp.utils.SNMPUtils;
+import org.snmp4j.mp.SnmpConstants;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Receiving data from configured SNMP agent which, upon each invocation of
+ * {@link #onTrigger(ProcessContext, ProcessSession)} method, will construct a
+ * {@link FlowFile} containing in its properties the information retrieved.
+ * The output {@link FlowFile} won't have any content.
+ */
+@Tags({"snmp", "send", "trap"})
+@InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
+@CapabilityDescription("Sends information to SNMP Manager.")
+public class SendTrapSNMP extends AbstractSNMPProcessor {
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_0 = new 
AllowableValue("0", "Cold Start",
+            "A coldStart trap signifies that the sending protocol entity is 
reinitializing itself such that" +
+                    " the agent's configuration or the protocol entity 
implementation may be altered.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_1 = new 
AllowableValue("1", "Warm Start",
+            "A warmStart trap signifies that the sending protocol entity is 
reinitializing itself such that" +
+                    " neither the agent configuration nor the protocol entity 
implementation is altered.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_2 = new 
AllowableValue("2", "Link Down",
+            "A linkDown trap signifies that the sending protocol entity 
recognizes a failure in one of " +
+                    "the communication links represented in the agent's 
configuration.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_3 = new 
AllowableValue("3", "Link Up",
+            "A linkUp trap signifies that the sending protocol entity 
recognizes that one of the communication " +
+                    "links represented in the agent's configuration has come 
up.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_4 = new 
AllowableValue("4", "Authentication Failure",
+            "An authenticationFailure trap signifies that the sending protocol 
entity is the addressee of a " +
+                    "protocol message that is not properly authenticated.  
While implementations of the SNMP must be " +
+                    "capable of generating this trap, they must also be 
capable of suppressing the emission of such traps " +
+                    "via an implementation- specific mechanism.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_5 = new 
AllowableValue("5", "EGP Neighbor Loss",
+            "An egpNeighborLoss trap signifies that an EGP neighbor for whom 
the sending protocol entity was " +
+                    "an EGP peer has been marked down and the peer 
relationship no longer obtains.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_6 = new 
AllowableValue("6", "Enterprise Specific",
+            "An enterpriseSpecific trap signifies that a particular 
enterprise-specific trap has occurred which " +
+                    "can be defined in the Specific Trap Type field.");
+
+    public static final PropertyDescriptor SNMP_MANAGER_HOST = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-manager-host")
+            .displayName("SNMP Manager Host")
+            .description("The host where the SNMP Manager sends the trap.")
+            .required(true)
+            .defaultValue("localhost")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor SNMP_MANAGER_PORT = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-manager-port")
+            .displayName("SNMP Manager Port")
+            .description("The port where the SNMP Manager listens to the 
incoming traps.")
+            .required(true)
+            .defaultValue("0")
+            .addValidator(StandardValidators.PORT_VALIDATOR)
+            .build();
+
+    // SNMPv1 TRAP PROPERTIES
+
+    public static final PropertyDescriptor ENTERPRISE_OID = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-enterprise-oid")
+            .displayName("Enterprise OID")
+            .description("Enterprise is the vendor identification (OID) for 
the network management sub-system that generated the trap")
+            .required(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+    public static final PropertyDescriptor AGENT_ADDRESS = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-agent-address")
+            .displayName("SNMP Trap Agent Address")
+            .description("The address where the SNMP Manager sends the trap.")
+            .required(true)
+            .defaultValue("0")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    public static final PropertyDescriptor GENERIC_TRAP_TYPE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-generic-type")
+            .displayName("Generic Trap Type")
+            .description("Generic trap type is an integer in the range of 0 to 
6. See Usage for details.")
+            .required(true)
+            .allowableValues(GENERIC_TRAP_TYPE_0, GENERIC_TRAP_TYPE_1, 
GENERIC_TRAP_TYPE_2, GENERIC_TRAP_TYPE_3,
+                    GENERIC_TRAP_TYPE_4, GENERIC_TRAP_TYPE_5, 
GENERIC_TRAP_TYPE_6)
+            .addValidator(StandardValidators.createLongValidator(0, 6, true))
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    public static final PropertyDescriptor SPECIFIC_TRAP_TYPE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-specific-type")
+            .displayName("Specific Trap Type")
+            .description("Specific trap type is a number that further 
specifies the nature of the event that generated " +
+                    "the trap in the case of traps of generic type 6 
(enterpriseSpecific). The interpretation of this " +
+                    "code is vendor-specific")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .dependsOn(GENERIC_TRAP_TYPE, GENERIC_TRAP_TYPE_6)
+            .build();
+
+    public static final PropertyDescriptor TIME_STAMP = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-timestamp")
+            .displayName("Timestamp")
+            .description("Timestamp of the trap (unit: 0.01 second).")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    // SNMPv2c/v3 TRAP PROPERTIES
+
+    public static final PropertyDescriptor TRAP_OID_VALUE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-oid-value")
+            .displayName("Trap OID Value")
+            .description("The value of the trap OID")
+            .required(false)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V2C, SNMP_V3)
+            .build();
+
+    public static final PropertyDescriptor SYSTEM_UPTIME = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-sysuptime")
+            .displayName("System Uptime")
+            .description("System uptime of the trap (unit: 0.01 second)")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V2C, SNMP_V3)
+            .build();
+
+    public static final Relationship REL_SUCCESS = new Relationship.Builder()
+            .name("success")
+            .description("All FlowFiles that are received from the SNMP agent 
are routed to this relationship")
+            .build();
+
+    public static final Relationship REL_FAILURE = new Relationship.Builder()
+            .name("failure")
+            .description("All FlowFiles that cannot received from the SNMP 
agent are routed to this relationship")
+            .build();
+
+    protected static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = 
Collections.unmodifiableList(Arrays.asList(
+            SNMP_MANAGER_HOST,
+            SNMP_MANAGER_PORT,
+            SNMP_VERSION,
+            SNMP_COMMUNITY,
+            SNMP_SECURITY_LEVEL,
+            SNMP_SECURITY_NAME,
+            SNMP_AUTH_PROTOCOL,
+            SNMP_AUTH_PASSWORD,
+            SNMP_PRIVACY_PROTOCOL,
+            SNMP_PRIVACY_PASSWORD,
+            SNMP_RETRIES,
+            SNMP_TIMEOUT,
+            ENTERPRISE_OID,
+            AGENT_ADDRESS,
+            GENERIC_TRAP_TYPE,
+            SPECIFIC_TRAP_TYPE,
+            TIME_STAMP,
+            TRAP_OID_VALUE,
+            SYSTEM_UPTIME
+    ));
+
+    private static final Set<Relationship> RELATIONSHIPS = 
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+            REL_SUCCESS,
+            REL_FAILURE
+    )));
+
+    private volatile TrapConfiguration trapConfiguration;
+
+    @OnScheduled
+    public void init(ProcessContext context) throws InitializationException {
+        initSnmpManager(context);
+        final int snmpVersion = 
SNMPUtils.getVersion(context.getProperty(SNMP_VERSION).getValue());
+        if (SnmpConstants.version1 == snmpVersion) {
+            trapConfiguration = TrapV1Configuration.builder()
+                    
.enterpriseOid(context.getProperty(ENTERPRISE_OID).getValue())
+                    
.agentAddress(context.getProperty(AGENT_ADDRESS).getValue())
+                    
.genericTrapType(context.getProperty(GENERIC_TRAP_TYPE).asInteger())
+                    
.specificTrapType(context.getProperty(SPECIFIC_TRAP_TYPE).asInteger())
+                    .timeStamp(context.getProperty(TIME_STAMP).asInteger())
+                    .build();
+        } else {
+            trapConfiguration = new TrapV2cV3Configuration(
+                    context.getProperty(TRAP_OID_VALUE).getValue(),
+                    context.getProperty(SYSTEM_UPTIME).asInteger()
+            );
+        }
+    }
+
+    @Override
+    public void onTrigger(final ProcessContext context, final ProcessSession 
processSession) {
+        final FlowFile flowFile = processSession.get();
+        try {
+            snmpRequestHandler.sendTrap(trapConfiguration, flowFile);
+            if (flowFile != null) {
+                processSession.remove(flowFile);

Review comment:
       Are you sure about that the file needs to be removed? Why not depend on 
"Automatically Terminate Relationships"?

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/testrunners/SNMPTestRunners.java
##########
@@ -0,0 +1,44 @@
+/*
+ * 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.snmp.helper.testrunners;

Review comment:
       I think the same applies here as above: the downside of adding a lot of 
util classes into the tests (like a lot of boilerplate, extra abstractions and 
fragmented tests) overweights the benefits.

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/SendTrapSNMP.java
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.snmp.processors;
+
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.snmp.configuration.TrapConfiguration;
+import org.apache.nifi.snmp.configuration.TrapV1Configuration;
+import org.apache.nifi.snmp.configuration.TrapV2cV3Configuration;
+import org.apache.nifi.snmp.utils.SNMPUtils;
+import org.snmp4j.mp.SnmpConstants;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Receiving data from configured SNMP agent which, upon each invocation of
+ * {@link #onTrigger(ProcessContext, ProcessSession)} method, will construct a
+ * {@link FlowFile} containing in its properties the information retrieved.
+ * The output {@link FlowFile} won't have any content.
+ */
+@Tags({"snmp", "send", "trap"})
+@InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
+@CapabilityDescription("Sends information to SNMP Manager.")
+public class SendTrapSNMP extends AbstractSNMPProcessor {
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_0 = new 
AllowableValue("0", "Cold Start",
+            "A coldStart trap signifies that the sending protocol entity is 
reinitializing itself such that" +
+                    " the agent's configuration or the protocol entity 
implementation may be altered.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_1 = new 
AllowableValue("1", "Warm Start",
+            "A warmStart trap signifies that the sending protocol entity is 
reinitializing itself such that" +
+                    " neither the agent configuration nor the protocol entity 
implementation is altered.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_2 = new 
AllowableValue("2", "Link Down",
+            "A linkDown trap signifies that the sending protocol entity 
recognizes a failure in one of " +
+                    "the communication links represented in the agent's 
configuration.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_3 = new 
AllowableValue("3", "Link Up",
+            "A linkUp trap signifies that the sending protocol entity 
recognizes that one of the communication " +
+                    "links represented in the agent's configuration has come 
up.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_4 = new 
AllowableValue("4", "Authentication Failure",
+            "An authenticationFailure trap signifies that the sending protocol 
entity is the addressee of a " +
+                    "protocol message that is not properly authenticated.  
While implementations of the SNMP must be " +
+                    "capable of generating this trap, they must also be 
capable of suppressing the emission of such traps " +
+                    "via an implementation- specific mechanism.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_5 = new 
AllowableValue("5", "EGP Neighbor Loss",
+            "An egpNeighborLoss trap signifies that an EGP neighbor for whom 
the sending protocol entity was " +
+                    "an EGP peer has been marked down and the peer 
relationship no longer obtains.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_6 = new 
AllowableValue("6", "Enterprise Specific",
+            "An enterpriseSpecific trap signifies that a particular 
enterprise-specific trap has occurred which " +
+                    "can be defined in the Specific Trap Type field.");
+
+    public static final PropertyDescriptor SNMP_MANAGER_HOST = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-manager-host")
+            .displayName("SNMP Manager Host")
+            .description("The host where the SNMP Manager sends the trap.")
+            .required(true)
+            .defaultValue("localhost")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor SNMP_MANAGER_PORT = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-manager-port")
+            .displayName("SNMP Manager Port")
+            .description("The port where the SNMP Manager listens to the 
incoming traps.")
+            .required(true)
+            .defaultValue("0")
+            .addValidator(StandardValidators.PORT_VALIDATOR)
+            .build();
+
+    // SNMPv1 TRAP PROPERTIES
+
+    public static final PropertyDescriptor ENTERPRISE_OID = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-enterprise-oid")
+            .displayName("Enterprise OID")
+            .description("Enterprise is the vendor identification (OID) for 
the network management sub-system that generated the trap")
+            .required(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+    public static final PropertyDescriptor AGENT_ADDRESS = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-agent-address")
+            .displayName("SNMP Trap Agent Address")
+            .description("The address where the SNMP Manager sends the trap.")
+            .required(true)
+            .defaultValue("0")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    public static final PropertyDescriptor GENERIC_TRAP_TYPE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-generic-type")
+            .displayName("Generic Trap Type")
+            .description("Generic trap type is an integer in the range of 0 to 
6. See Usage for details.")
+            .required(true)
+            .allowableValues(GENERIC_TRAP_TYPE_0, GENERIC_TRAP_TYPE_1, 
GENERIC_TRAP_TYPE_2, GENERIC_TRAP_TYPE_3,
+                    GENERIC_TRAP_TYPE_4, GENERIC_TRAP_TYPE_5, 
GENERIC_TRAP_TYPE_6)
+            .addValidator(StandardValidators.createLongValidator(0, 6, true))
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    public static final PropertyDescriptor SPECIFIC_TRAP_TYPE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-specific-type")
+            .displayName("Specific Trap Type")
+            .description("Specific trap type is a number that further 
specifies the nature of the event that generated " +
+                    "the trap in the case of traps of generic type 6 
(enterpriseSpecific). The interpretation of this " +
+                    "code is vendor-specific")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .dependsOn(GENERIC_TRAP_TYPE, GENERIC_TRAP_TYPE_6)
+            .build();
+
+    public static final PropertyDescriptor TIME_STAMP = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-timestamp")
+            .displayName("Timestamp")
+            .description("Timestamp of the trap (unit: 0.01 second).")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    // SNMPv2c/v3 TRAP PROPERTIES
+
+    public static final PropertyDescriptor TRAP_OID_VALUE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-oid-value")
+            .displayName("Trap OID Value")
+            .description("The value of the trap OID")
+            .required(false)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V2C, SNMP_V3)
+            .build();
+
+    public static final PropertyDescriptor SYSTEM_UPTIME = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-sysuptime")
+            .displayName("System Uptime")
+            .description("System uptime of the trap (unit: 0.01 second)")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V2C, SNMP_V3)
+            .build();
+
+    public static final Relationship REL_SUCCESS = new Relationship.Builder()
+            .name("success")
+            .description("All FlowFiles that are received from the SNMP agent 
are routed to this relationship")
+            .build();
+
+    public static final Relationship REL_FAILURE = new Relationship.Builder()
+            .name("failure")
+            .description("All FlowFiles that cannot received from the SNMP 
agent are routed to this relationship")
+            .build();
+
+    protected static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = 
Collections.unmodifiableList(Arrays.asList(
+            SNMP_MANAGER_HOST,
+            SNMP_MANAGER_PORT,
+            SNMP_VERSION,
+            SNMP_COMMUNITY,
+            SNMP_SECURITY_LEVEL,
+            SNMP_SECURITY_NAME,
+            SNMP_AUTH_PROTOCOL,
+            SNMP_AUTH_PASSWORD,
+            SNMP_PRIVACY_PROTOCOL,
+            SNMP_PRIVACY_PASSWORD,
+            SNMP_RETRIES,
+            SNMP_TIMEOUT,
+            ENTERPRISE_OID,
+            AGENT_ADDRESS,
+            GENERIC_TRAP_TYPE,
+            SPECIFIC_TRAP_TYPE,
+            TIME_STAMP,
+            TRAP_OID_VALUE,
+            SYSTEM_UPTIME
+    ));
+
+    private static final Set<Relationship> RELATIONSHIPS = 
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+            REL_SUCCESS,

Review comment:
       I did not find any usage for `REL_SUCCESS`

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/configurations/SNMPV1Configurations.java
##########
@@ -0,0 +1,58 @@
+/*
+ * 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.snmp.helper.configurations;
+
+import org.apache.nifi.snmp.configuration.SNMPConfiguration;
+import org.snmp4j.mp.SnmpConstants;
+
+public class SNMPV1Configurations implements SNMPConfigurations {

Review comment:
       I think, there is too much util class for testing. Would not it be 
possible to move the code into the relevant tests? My reasoning:
   - The tests become too fragmented and because of this: hard to read
   - As I see, most of the calls are used at one place, which does not reason 
extracting in a test
   - The SNMPConfigurations abstraction is implemented in such a ways that 
V1... etc are used in the respected test file (V1... etc) only, thus the 
abstraction is not really provides benefit

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/configuration/TrapV2cV3Configuration.java
##########
@@ -0,0 +1,63 @@
+/*
+ * 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.snmp.configuration;
+
+public class TrapV2cV3Configuration implements TrapConfiguration {
+
+    private final String trapOidValue;
+    private final int sysUpTime;
+
+    public TrapV2cV3Configuration(final String trapOidValue, final int 
sysUpTime) {

Review comment:
       I would propose to separate V2 and V3. With the current usage, they 
should work identical, but this might not be the case in longer term. And 
separating them later will come with more headache. This level of code 
duplication, when the equality might be momentarily is not necessary a bad 
thing.

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/processors/SendTrapSNMP.java
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.snmp.processors;
+
+import org.apache.nifi.annotation.behavior.InputRequirement;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.AllowableValue;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.snmp.configuration.TrapConfiguration;
+import org.apache.nifi.snmp.configuration.TrapV1Configuration;
+import org.apache.nifi.snmp.configuration.TrapV2cV3Configuration;
+import org.apache.nifi.snmp.utils.SNMPUtils;
+import org.snmp4j.mp.SnmpConstants;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Receiving data from configured SNMP agent which, upon each invocation of
+ * {@link #onTrigger(ProcessContext, ProcessSession)} method, will construct a
+ * {@link FlowFile} containing in its properties the information retrieved.
+ * The output {@link FlowFile} won't have any content.
+ */
+@Tags({"snmp", "send", "trap"})
+@InputRequirement(InputRequirement.Requirement.INPUT_FORBIDDEN)
+@CapabilityDescription("Sends information to SNMP Manager.")
+public class SendTrapSNMP extends AbstractSNMPProcessor {
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_0 = new 
AllowableValue("0", "Cold Start",
+            "A coldStart trap signifies that the sending protocol entity is 
reinitializing itself such that" +
+                    " the agent's configuration or the protocol entity 
implementation may be altered.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_1 = new 
AllowableValue("1", "Warm Start",
+            "A warmStart trap signifies that the sending protocol entity is 
reinitializing itself such that" +
+                    " neither the agent configuration nor the protocol entity 
implementation is altered.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_2 = new 
AllowableValue("2", "Link Down",
+            "A linkDown trap signifies that the sending protocol entity 
recognizes a failure in one of " +
+                    "the communication links represented in the agent's 
configuration.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_3 = new 
AllowableValue("3", "Link Up",
+            "A linkUp trap signifies that the sending protocol entity 
recognizes that one of the communication " +
+                    "links represented in the agent's configuration has come 
up.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_4 = new 
AllowableValue("4", "Authentication Failure",
+            "An authenticationFailure trap signifies that the sending protocol 
entity is the addressee of a " +
+                    "protocol message that is not properly authenticated.  
While implementations of the SNMP must be " +
+                    "capable of generating this trap, they must also be 
capable of suppressing the emission of such traps " +
+                    "via an implementation- specific mechanism.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_5 = new 
AllowableValue("5", "EGP Neighbor Loss",
+            "An egpNeighborLoss trap signifies that an EGP neighbor for whom 
the sending protocol entity was " +
+                    "an EGP peer has been marked down and the peer 
relationship no longer obtains.");
+
+    public static final AllowableValue GENERIC_TRAP_TYPE_6 = new 
AllowableValue("6", "Enterprise Specific",
+            "An enterpriseSpecific trap signifies that a particular 
enterprise-specific trap has occurred which " +
+                    "can be defined in the Specific Trap Type field.");
+
+    public static final PropertyDescriptor SNMP_MANAGER_HOST = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-manager-host")
+            .displayName("SNMP Manager Host")
+            .description("The host where the SNMP Manager sends the trap.")
+            .required(true)
+            .defaultValue("localhost")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor SNMP_MANAGER_PORT = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-manager-port")
+            .displayName("SNMP Manager Port")
+            .description("The port where the SNMP Manager listens to the 
incoming traps.")
+            .required(true)
+            .defaultValue("0")
+            .addValidator(StandardValidators.PORT_VALIDATOR)
+            .build();
+
+    // SNMPv1 TRAP PROPERTIES
+
+    public static final PropertyDescriptor ENTERPRISE_OID = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-enterprise-oid")
+            .displayName("Enterprise OID")
+            .description("Enterprise is the vendor identification (OID) for 
the network management sub-system that generated the trap")
+            .required(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+    public static final PropertyDescriptor AGENT_ADDRESS = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-agent-address")
+            .displayName("SNMP Trap Agent Address")
+            .description("The address where the SNMP Manager sends the trap.")
+            .required(true)
+            .defaultValue("0")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    public static final PropertyDescriptor GENERIC_TRAP_TYPE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-generic-type")
+            .displayName("Generic Trap Type")
+            .description("Generic trap type is an integer in the range of 0 to 
6. See Usage for details.")
+            .required(true)
+            .allowableValues(GENERIC_TRAP_TYPE_0, GENERIC_TRAP_TYPE_1, 
GENERIC_TRAP_TYPE_2, GENERIC_TRAP_TYPE_3,
+                    GENERIC_TRAP_TYPE_4, GENERIC_TRAP_TYPE_5, 
GENERIC_TRAP_TYPE_6)
+            .addValidator(StandardValidators.createLongValidator(0, 6, true))
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    public static final PropertyDescriptor SPECIFIC_TRAP_TYPE = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-specific-type")
+            .displayName("Specific Trap Type")
+            .description("Specific trap type is a number that further 
specifies the nature of the event that generated " +
+                    "the trap in the case of traps of generic type 6 
(enterpriseSpecific). The interpretation of this " +
+                    "code is vendor-specific")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .dependsOn(GENERIC_TRAP_TYPE, GENERIC_TRAP_TYPE_6)
+            .build();
+
+    public static final PropertyDescriptor TIME_STAMP = new 
PropertyDescriptor.Builder()
+            .name("snmp-trap-timestamp")
+            .displayName("Timestamp")
+            .description("Timestamp of the trap (unit: 0.01 second).")
+            .required(true)
+            .addValidator(StandardValidators.POSITIVE_INTEGER_VALIDATOR)
+            .dependsOn(SNMP_VERSION, SNMP_V1)
+            .build();
+
+    // SNMPv2c/v3 TRAP PROPERTIES

Review comment:
       It might be a solution to avoid the comment by grouping the properties 
into collections like `PROPERTIES_V1` and  like and use these when building 
`PROPERTY_DESCRIPTORS`. I am not sure however if this grouping will effect the 
property ordering negatively.

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/helper/SNMPTestUtils.java
##########
@@ -16,53 +16,33 @@
  */
 package org.apache.nifi.snmp.helper;
 
-import org.snmp4j.CommunityTarget;
-import org.snmp4j.Snmp;
-import org.snmp4j.UserTarget;
-import org.snmp4j.security.UsmUser;
-import org.snmp4j.smi.OID;
-import org.snmp4j.smi.OctetString;
-import org.snmp4j.smi.UdpAddress;
-import org.snmp4j.transport.DefaultUdpTransportMapping;
+import org.apache.nifi.snmp.exception.InvalidSnmpVersionException;
+import org.apache.nifi.util.MockFlowFile;
+import org.snmp4j.mp.SnmpConstants;
 
-import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
-public class SNMPTestUtils {
-
-    public static Snmp createSnmpClient() throws IOException {
-        final DefaultUdpTransportMapping transportMapping = new 
DefaultUdpTransportMapping();
-        transportMapping.listen();
-        return new Snmp(transportMapping);
-    }
+import static org.apache.nifi.snmp.utils.SNMPUtils.SNMP_PROP_PREFIX;
 
-    public static CommunityTarget createCommTarget(final String community, 
final String address, final int version) {
-        final CommunityTarget target = new CommunityTarget();
-        target.setVersion(version);
-        target.setCommunity(new OctetString(community));
-        target.setAddress(new UdpAddress(address));
-        target.setRetries(0);
-        target.setTimeout(500);
-        return target;
-    }
+public class SNMPTestUtils {
 
-    public static UserTarget createUserTarget(final String address, final int 
securityLevel, final String securityName, final int version) {
-        final UserTarget target = new UserTarget();
-        target.setVersion(version);
-        target.setSecurityLevel(securityLevel);
-        target.setSecurityName(new OctetString(securityName));
-        target.setAddress(new UdpAddress(address));
-        target.setRetries(0);
-        target.setTimeout(500);
-        return target;
+    public static String getVersionByInt(int version) {
+        if (SnmpConstants.version1 == version) {

Review comment:
       Is not there a build-in SNMP support for such a conversion?

##########
File path: 
nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/factory/SNMPFactoryTest.java
##########
@@ -0,0 +1,68 @@
+/*
+ * 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.snmp.factory;
+
+import org.apache.nifi.snmp.configuration.SNMPConfiguration;
+import org.junit.Test;
+import org.snmp4j.Snmp;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.security.UsmUser;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class SNMPFactoryTest {
+
+    private final SNMPConfiguration.Builder configurationBuilder = 
SNMPConfiguration.builder()
+            .setManagerPort("0")
+            .setTargetHost("1.2.3.4")

Review comment:
       Minor: a realistic value would be better (this is true for port as well)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@nifi.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to