001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.snmp;
018
019 import javax.jbi.management.DeploymentException;
020 import javax.jbi.messaging.InOnly;
021 import javax.jbi.messaging.MessageExchange;
022 import javax.jbi.messaging.MessagingException;
023 import javax.jbi.messaging.NormalizedMessage;
024
025 import org.apache.servicemix.common.endpoints.ConsumerEndpoint;
026 import org.apache.servicemix.snmp.marshaler.DefaultSnmpMarshaler;
027 import org.apache.servicemix.snmp.marshaler.SnmpMarshalerSupport;
028 import org.snmp4j.CommandResponder;
029 import org.snmp4j.CommandResponderEvent;
030 import org.snmp4j.PDU;
031 import org.snmp4j.Snmp;
032 import org.snmp4j.TransportMapping;
033 import org.snmp4j.smi.Address;
034 import org.snmp4j.smi.GenericAddress;
035 import org.snmp4j.smi.UdpAddress;
036 import org.snmp4j.transport.DefaultUdpTransportMapping;
037
038 /**
039 * This is the trap endpoint for the snmp component.
040 *
041 * This endpoint receives and process trap PDUs from
042 * a device. Then it sends an exchange to the target service
043 * containing the processed content.
044 *
045 * @org.apache.xbean.XBean element="trap-consumer"
046 * @author gperdiguero
047 * @author jbonofre
048 */
049 public class SnmpTrapConsumerEndpoint extends ConsumerEndpoint implements SnmpEndpointType, CommandResponder {
050
051 public static final boolean DEFAULT_ENABLED_VALUE = true;
052
053 private Address listenGenericAddress;
054 private Snmp snmp;
055 private TransportMapping transport;
056
057 private String address;
058 private boolean enabled = DEFAULT_ENABLED_VALUE;
059
060 private SnmpMarshalerSupport marshaler = new DefaultSnmpMarshaler();
061
062 /*
063 * (non-Javadoc)
064 * @see org.apache.servicemix.common.endpoints.ConsumerEndpoint#activate()
065 */
066 @Override
067 public synchronized void activate() throws Exception {
068 super.activate();
069 // load connection data only if the endpoint is enabled
070 if (isEnabled()) {
071 logger.debug("Activating endpoint");
072 this.listenGenericAddress = GenericAddress.parse(this.address);
073 this.transport = new DefaultUdpTransportMapping((UdpAddress) this.listenGenericAddress);
074 this.snmp = new Snmp(transport);
075 snmp.addCommandResponder(this);
076 }
077 }
078
079 /*
080 * (non-Javadoc)
081 * @see org.apache.servicemix.common.endpoints.PollingEndpoint#start()
082 */
083 @Override
084 public synchronized void start() throws Exception {
085 super.start();
086
087 // listening is only allowed if the endpoint was initialized
088 if (isEnabled()) {
089 // listen to the transport
090 this.transport.listen();
091 }
092 }
093
094 /*
095 * (non-Javadoc)
096 * @see org.apache.servicemix.common.endpoints.PollingEndpoint#stop()
097 */
098 @Override
099 public synchronized void stop() throws Exception {
100 // stop listening only if the endpoint was initialized
101 if (isEnabled()) {
102 // stop listening to the transport
103 if (this.transport.isListening()) {
104 this.transport.close();
105 }
106 }
107
108 super.stop();
109 }
110
111 /*
112 * (non-Javadoc)
113 * @see org.apache.servicemix.common.endpoints.ConsumerEndpoint#validate()
114 */
115 @Override
116 public void validate() throws DeploymentException {
117 super.validate();
118
119 // check listen address not null
120 if (this.address == null) {
121 throw new DeploymentException("The listen address attribute has to be specified!");
122 }
123
124 // check if address is valid
125 try {
126 if (GenericAddress.parse(this.address) == null) {
127 throw new DeploymentException("The specified address " + address + " is not valid!");
128 }
129 } catch (IllegalArgumentException ex) {
130 throw new DeploymentException("The specified address " + address + " is not valid!");
131 }
132 }
133
134 /*
135 * (non-Javadoc)
136 * @see
137 * org.apache.servicemix.common.endpoints.AbstractEndpoint#process(javax
138 * .jbi.messaging.MessageExchange)
139 */
140 @Override
141 public void process(MessageExchange exchange) throws Exception {
142 // only DONE and ERROR states will be received here and this
143 // endpoint is not interested in such messages at all
144 }
145
146 /*
147 * (non-Javadoc)
148 * @see
149 * org.snmp4j.CommandResponder#processPdu(org.snmp4j.CommandResponderEvent)
150 */
151 public void processPdu(CommandResponderEvent event) {
152 PDU pdu = event.getPDU();
153 // check PDU not null
154 if (pdu != null) {
155 sendSnmpTrapMessage(pdu);
156 } else {
157 logger.debug("Received invalid trap PDU: " + pdu);
158 }
159 }
160
161 /**
162 * Sends the message to the bus
163 * @param pdu the trap received
164 */
165 private void sendSnmpTrapMessage(PDU pdu) {
166 try {
167 // create an inOnly exchange
168 InOnly io = getExchangeFactory().createInOnlyExchange();
169
170 // configure the exchange target
171 configureExchangeTarget(io);
172
173 // create the in message
174 NormalizedMessage inMsg = io.createMessage();
175
176 // now let the marshaler convert the snmp data into
177 // a normalized message to send to jbi bus
178 this.marshaler.convertToJBI(io, inMsg, null, pdu);
179
180 // put the in message into the inOnly exchange
181 io.setInMessage(inMsg);
182
183 // send the exchange
184 getChannel().send(io);
185 } catch (MessagingException ex) {
186 logger.error("Error while trying to send the snmp trap PDU to the jbi bus", ex);
187 }
188 }
189
190 public Snmp getSnmp() {
191 return this.snmp;
192 }
193
194 public String getAddress() {
195 return this.address;
196 }
197
198 /**
199 * <p>Specifies the connection URI used to connect to a snmp capable device.
200 * <br /><br />
201 * <b><u>Template:</u></b> <br />
202 * <i><protocol>:<host>/<port></i>
203 * <br /><br />
204 * <b><u>Details:</u></b><br /><br/>
205 * <table border="0" cellpadding="0" cellspacing="0">
206 * <tr>
207 * <td width="40%" align="left"><b><u>Name</u></b></td>
208 * <td width="60%" align="left"><b><u>Description</u></b></td>
209 * </tr>
210 * <tr>
211 * <td>protocol</td>
212 * <td>the protocol to use (udp or tcp)</td>
213 * </tr>
214 * <tr>
215 * <td>host</td>
216 * <td>the name or ip address of the snmp capable device</td>
217 * </tr>
218 * <tr>
219 * <td>port</td>
220 * <td>the port number to use</td>
221 * </tr>
222 * </table>
223 * <br/>
224 * <b><u>Example:</u></b><br />
225 * <i>udp:192.168.2.122/162</i></p>
226 * <i> The default value is <b>null</b></i><br/><br/>
227 *
228 * @param listenAddress
229 * a <code>String</code> value containing the connection details
230 */
231 public void setAddress(String address) {
232 this.address = address;
233 }
234
235 public SnmpMarshalerSupport getMarshaler() {
236 return this.marshaler;
237 }
238
239 /**
240 * <p>Specifies a marshaler class which provides the logic for converting
241 * a snmp trap into a normalized message. This class has to implement
242 * the <code>SnmpMarshalerSupport</code> interface. If you don't specify a
243 * marshaler, the <code>DefaultSnmpMarshaler</code> will be used.</p>
244 *
245 * @param marshaler
246 * a class which implements <code>SnmpMarshalerSupport</code>
247 */
248 public void setMarshaler(SnmpMarshalerSupport marshaler) {
249 this.marshaler = marshaler;
250 }
251
252 public boolean isEnabled() {
253 return enabled;
254 }
255
256 /**
257 * <p>Specifies wether the endpoint is enabled or not.
258 * If its value is set to true, the connection data will be
259 * setted and trap PDUs will be processed. Otherwise,
260 * the endpoint won't do anything.</p>
261 * @param enabled the enabled to set
262 */
263 public void setEnabled(boolean enabled) {
264 this.enabled = enabled;
265 }
266 }