/**
* 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.camel.component.snmp;
import java.net.URI;
import org.apache.camel.Consumer;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.impl.DefaultPollingEndpoint;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityLevel;
/**
* The snmp component gives you the ability to poll SNMP capable devices or receiving traps.
*/
@UriEndpoint(firstVersion = "2.1.0", scheme = "snmp", title = "SNMP", syntax = "snmp:host:port", consumerOnly = true, label = "monitoring")
public class SnmpEndpoint extends DefaultPollingEndpoint {
public static final String DEFAULT_COMMUNITY = "public";
public static final int DEFAULT_SNMP_VERSION = SnmpConstants.version1;
public static final int DEFAULT_SNMP_RETRIES = 2;
public static final int DEFAULT_SNMP_TIMEOUT = 1500;
private static final Logger LOG = LoggerFactory.getLogger(SnmpEndpoint.class);
private transient String address;
@UriPath(description = "Hostname of the SNMP enabled device") @Metadata(required = "true")
private String host;
@UriPath(description = "Port number of the SNMP enabled device") @Metadata(required = "true")
private Integer port;
@UriParam(defaultValue = "udp", enums = "tcp,udp")
private String protocol = "udp";
@UriParam(defaultValue = "" + DEFAULT_SNMP_RETRIES)
private int retries = DEFAULT_SNMP_RETRIES;
@UriParam(defaultValue = "" + DEFAULT_SNMP_TIMEOUT)
private int timeout = DEFAULT_SNMP_TIMEOUT;
@UriParam(defaultValue = "" + DEFAULT_SNMP_VERSION, enums = "0,1,3")
private int snmpVersion = DEFAULT_SNMP_VERSION;
@UriParam(defaultValue = DEFAULT_COMMUNITY)
private String snmpCommunity = DEFAULT_COMMUNITY;
@UriParam
private SnmpActionType type;
@UriParam(label = "consumer", defaultValue = "60000")
private long delay = 60000;
@UriParam(defaultValue = "" + SecurityLevel.AUTH_PRIV, enums = "1,2,3", label = "security")
private int securityLevel = SecurityLevel.AUTH_PRIV;
@UriParam(label = "security", secret = true)
private String securityName;
@UriParam(enums = "MD5,SHA1", label = "security")
private String authenticationProtocol;
@UriParam(label = "security", secret = true)
private String authenticationPassphrase;
@UriParam(label = "security", secret = true)
private String privacyProtocol;
@UriParam(label = "security", secret = true)
private String privacyPassphrase;
@UriParam
private String snmpContextName;
@UriParam
private String snmpContextEngineId;
@UriParam(javaType = "java.lang.String")
private OIDList oids = new OIDList();
/**
* creates a snmp endpoint
*
* @param uri the endpoint uri
* @param component the component
*/
public SnmpEndpoint(String uri, SnmpComponent component) {
super(uri, component);
}
public Consumer createConsumer(Processor processor) throws Exception {
if (this.type == SnmpActionType.TRAP) {
SnmpTrapConsumer answer = new SnmpTrapConsumer(this, processor);
// As the SnmpTrapConsumer is not a polling consumer we don't need to call the configureConsumer here.
return answer;
} else if (this.type == SnmpActionType.POLL) {
SnmpOIDPoller answer = new SnmpOIDPoller(this, processor);
configureConsumer(answer);
return answer;
} else {
throw new IllegalArgumentException("The type '" + this.type + "' is not valid!");
}
}
public Producer createProducer() throws Exception {
if (this.type == SnmpActionType.TRAP) {
return new SnmpTrapProducer(this);
} else {
return new SnmpProducer(this);
}
}
public boolean isSingleton() {
return true;
}
/**
* creates an exchange for the given message
*
* @param pdu the pdu
* @return an exchange
*/
public Exchange createExchange(PDU pdu) {
Exchange exchange = super.createExchange();
exchange.setIn(new SnmpMessage(pdu));
return exchange;
}
/**
* creates an exchange for the given message
*
* @param pdu the pdu
* @param event a snmp4j CommandResponderEvent
* @return an exchange
*/
public Exchange createExchange(PDU pdu, CommandResponderEvent event) {
Exchange exchange = super.createExchange();
exchange.setIn(new SnmpMessage(pdu, event));
return exchange;
}
/**
* creates and configures the endpoint
*
* @throws Exception if unable to setup connection
* @deprecated use {@link #start()} instead
*/
@Deprecated
public void initiate() throws Exception {
// noop
}
public long getDelay() {
return delay;
}
/**
* Sets update rate in seconds
*
* @param updateEvery the update rate in seconds
*/
@Override
public void setDelay(long updateEvery) {
this.delay = updateEvery;
}
public SnmpActionType getType() {
return this.type;
}
/**
* Which operation to perform such as poll, trap, etc.
*/
public void setType(SnmpActionType type) {
this.type = type;
}
public OIDList getOids() {
return this.oids;
}
/**
* Defines which values you are interested in. Please have a look at the Wikipedia to get a better understanding.
* You may provide a single OID or a coma separated list of OIDs.
* Example: oids="1.3.6.1.2.1.1.3.0,1.3.6.1.2.1.25.3.2.1.5.1,1.3.6.1.2.1.25.3.5.1.1.1,1.3.6.1.2.1.43.5.1.1.11.1"
*/
public void setOids(OIDList oids) {
this.oids = oids;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public int getRetries() {
return this.retries;
}
/**
* Defines how often a retry is made before canceling the request.
*/
public void setRetries(int retries) {
this.retries = retries;
}
public int getTimeout() {
return this.timeout;
}
/**
* Sets the timeout value for the request in millis.
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getSnmpVersion() {
return this.snmpVersion;
}
/**
* Sets the snmp version for the request.
* <p/>
* The value 0 means SNMPv1, 1 means SNMPv2c, and the value 3 means SNMPv3
*/
public void setSnmpVersion(int snmpVersion) {
this.snmpVersion = snmpVersion;
}
public String getSnmpCommunity() {
return this.snmpCommunity;
}
/**
* Sets the community octet string for the snmp request.
*/
public void setSnmpCommunity(String snmpCommunity) {
this.snmpCommunity = snmpCommunity;
}
public String getProtocol() {
return this.protocol;
}
/**
* Here you can select which protocol to use. You can use either udp or tcp.
*/
public void setProtocol(String protocol) {
this.protocol = protocol;
}
@Override
protected void doStart() throws Exception {
super.doStart();
URI uri = URI.create(getEndpointUri());
String host = uri.getHost();
int port = uri.getPort();
if (host == null || host.trim().length() < 1) {
host = "127.0.0.1";
}
if (port == -1) {
if (getType() == SnmpActionType.POLL) {
port = 161; // default snmp poll port
} else {
port = 162; // default trap port
}
}
// set the address
String address = String.format("%s:%s/%d", getProtocol(), host, port);
LOG.debug("Using snmp address {}", address);
setAddress(address);
}
public int getSecurityLevel() {
return securityLevel;
}
/**
* Sets the security level for this target. The supplied security level must
* be supported by the security model dependent information associated with
* the security name set for this target.
* <p/>
* The value 1 means: No authentication and no encryption. Anyone can create and read messages with this security level
* The value 2 means: Authentication and no encryption. Only the one with the right authentication key can create
* messages with this security level, but anyone can read the contents of the message.
* The value 3 means: Authentication and encryption. Only the one with the right authentication key can create messages
* with this security level, and only the one with the right encryption/decryption key can read the contents of the message.
*/
public void setSecurityLevel(int securityLevel) {
this.securityLevel = securityLevel;
}
public String getSecurityName() {
return securityName;
}
/**
* Sets the security name to be used with this target.
*/
public void setSecurityName(String securityName) {
this.securityName = securityName;
}
public String getAuthenticationProtocol() {
return authenticationProtocol;
}
/**
* Authentication protocol to use if security level is set to enable authentication
* The possible values are: MD5, SHA1
*/
public void setAuthenticationProtocol(String authenticationProtocol) {
this.authenticationProtocol = authenticationProtocol;
}
public String getAuthenticationPassphrase() {
return authenticationPassphrase;
}
/**
* The authentication passphrase. If not <code>null</code>, <code>authenticationProtocol</code> must also be not
* <code>null</code>. RFC3414 11.2 requires passphrases to have a minimum length of 8 bytes.
* If the length of <code>authenticationPassphrase</code> is less than 8 bytes an <code>IllegalArgumentException</code> is thrown.
*/
public void setAuthenticationPassphrase(String authenticationPassphrase) {
this.authenticationPassphrase = authenticationPassphrase;
}
public String getPrivacyProtocol() {
return privacyProtocol;
}
/**
* The privacy protocol ID to be associated with this user. If set to <code>null</code>, this user only supports unencrypted messages.
*/
public void setPrivacyProtocol(String privacyProtocol) {
this.privacyProtocol = privacyProtocol;
}
public String getPrivacyPassphrase() {
return privacyPassphrase;
}
/**
* The privacy passphrase. If not <code>null</code>, <code>privacyProtocol</code> must also be not <code>null</code>.
* RFC3414 11.2 requires passphrases to have a minimum length of 8 bytes. If the length of
* <code>authenticationPassphrase</code> is less than 8 bytes an <code>IllegalArgumentException</code> is thrown.
*/
public void setPrivacyPassphrase(String privacyPassphrase) {
this.privacyPassphrase = privacyPassphrase;
}
public String getSnmpContextName() {
return snmpContextName;
}
/**
* Sets the context name field of this scoped PDU.
*/
public void setSnmpContextName(String snmpContextName) {
this.snmpContextName = snmpContextName;
}
public String getSnmpContextEngineId() {
return snmpContextEngineId;
}
/**
* Sets the context engine ID field of the scoped PDU.
*/
public void setSnmpContextEngineId(String snmpContextEngineId) {
this.snmpContextEngineId = snmpContextEngineId;
}
@Override
public String toString() {
// only show address to avoid user and password details to be shown
return "snmp://" + address;
}
}