KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > agent > CommandProcessor


1 /*_############################################################################
2   _##
3   _## SNMP4J-Agent - CommandProcessor.java
4   _##
5   _## Copyright (C) 2005-2007 Frank Fock (SNMP4J.org)
6   _##
7   _## Licensed under the Apache License, Version 2.0 (the "License");
8   _## you may not use this file except in compliance with the License.
9   _## You may obtain a copy of the License at
10   _##
11   _## http://www.apache.org/licenses/LICENSE-2.0
12   _##
13   _## Unless required by applicable law or agreed to in writing, software
14   _## distributed under the License is distributed on an "AS IS" BASIS,
15   _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   _## See the License for the specific language governing permissions and
17   _## limitations under the License.
18   _##
19   _##########################################################################*/

20
21 package org.snmp4j.agent;
22
23 import java.util.*;
24
25 import org.snmp4j.*;
26 import org.snmp4j.agent.request.*;
27 import org.snmp4j.agent.security.*;
28 import org.snmp4j.event.*;
29 import org.snmp4j.mp.*;
30 import org.snmp4j.smi.*;
31 import org.snmp4j.util.*;
32 import org.snmp4j.agent.util.TemporaryList;
33 import org.snmp4j.agent.mo.snmp.CoexistenceInfo;
34 import org.snmp4j.agent.mo.snmp.CoexistenceInfoProvider;
35 import org.snmp4j.log.LogAdapter;
36 import org.snmp4j.log.LogFactory;
37 import org.snmp4j.agent.mo.MOChangeEvent;
38 import org.snmp4j.agent.mo.MOChangeListener;
39
40 /**
41  * The <code>CommandProcessor</code> is the central glue code that puts together
42  * the various sub-systems of a SNMP agent.
43  *
44  * @author Frank Fock
45  * @version 1.0
46  */

47 public class CommandProcessor
48     implements CommandResponder, NotificationOriginator {
49
50   private static final LogAdapter logger =
51       LogFactory.getLogger(CommandProcessor.class);
52
53   /**
54    * The maximum request timeout supported by this command processor
55    * (by default 60.000 ms = 1 min).
56    */

57   private static final int MAX_INTERNAL_REQUEST_TIMEOUT = 60000;
58
59   protected ThreadPool threadPool = null;
60   protected VACM vacm = null;
61   protected Vector moServers;
62   protected OctetString ownContextEngineID;
63   protected Vector pduHandler;
64   protected TemporaryList requestList;
65   protected RequestFactory requestFactory;
66   protected NotificationOriginator notificationOriginator;
67   protected ProxyMap proxyForwarder;
68   protected CoexistenceInfoProvider coexistenceProvider;
69
70   private transient Vector counterListeners;
71
72   public CommandProcessor(OctetString contextEngineID) {
73     this.ownContextEngineID = contextEngineID;
74     moServers = new Vector();
75     requestList = new TemporaryList(MAX_INTERNAL_REQUEST_TIMEOUT);
76     pduHandler = new Vector();
77     pduHandler.add(new GetHandler());
78     pduHandler.add(new GetNextHandler());
79     pduHandler.add(new SetHandler());
80     pduHandler.add(new GetBulkHandler());
81     requestFactory = new DefaultRequestFactory();
82   }
83
84   public void processPdu(CommandResponderEvent event) {
85     if (event.getPDU() != null) {
86       CoexistenceInfo cinfo = null;
87       OctetString sname = new OctetString(event.getSecurityName());
88       if (event.getPDU() instanceof ScopedPDU) {
89         ScopedPDU spdu = (ScopedPDU)event.getPDU();
90         cinfo = new CoexistenceInfo(sname,
91                                     spdu.getContextEngineID(),
92                                     spdu.getContextName());
93       }
94       else if (coexistenceProvider != null) {
95         cinfo = coexistenceProvider.getCoexistenceInfo(sname);
96         if (cinfo != null) {
97           if (!coexistenceProvider.passesFilter(event.getPeerAddress(),
98                                                 cinfo)) {
99             logger.warn("Access attempt from "+event.getPeerAddress()+
100                         " denied because of source address filtering");
101
102             fireIncrementCounter(
103                 new CounterEvent(this,
104                                  SnmpConstants.snmpInBadCommunityNames));
105             return;
106           }
107           event.setMaxSizeResponsePDU(cinfo.getMaxMessageSize());
108         }
109         else {
110           if (logger.isInfoEnabled()) {
111             logger.info("Community name '"+sname+
112                         "' not found in SNMP-COMMUNITY-MIB");
113           }
114           fireIncrementCounter(
115               new CounterEvent(this,
116                                SnmpConstants.snmpInBadCommunityNames));
117           return;
118         }
119       }
120       if ((cinfo == null) ||
121           (ownContextEngineID.equals(cinfo.getContextEngineID()))) {
122         event.setProcessed(true);
123         Command command = new Command(event, cinfo);
124         if (threadPool != null) {
125           threadPool.execute(command);
126         }
127         else {
128           command.run();
129         }
130       }
131       else if (proxyForwarder != null) {
132         ProxyForwardRequest request =
133             new ProxyForwardRequest(event, cinfo);
134         ProxyForwarder proxy =
135             proxyForwarder.get(cinfo.getContextEngineID(),
136                                request.getProxyType());
137         ProxyCommand command = new ProxyCommand(proxy, request);
138         if (proxy != null) {
139           if (logger.isDebugEnabled()) {
140             logger.debug("Processsing proxy request with proxy forwarder "+
141                          proxy);
142           }
143           if (threadPool != null) {
144             threadPool.execute(command);
145           }
146           else {
147             command.run();
148           }
149         }
150         else {
151           fireIncrementCounter(new CounterEvent(this,
152                                                 SnmpConstants.snmpProxyDrops));
153         }
154       }
155       else {
156         fireIncrementCounter(new CounterEvent(this,
157                                               SnmpConstants.snmpSilentDrops));
158       }
159     }
160   }
161
162   public void setThreadPool(ThreadPool threadPool) {
163     this.threadPool = threadPool;
164   }
165
166   public VACM getVacm() {
167     return vacm;
168   }
169
170   public void setVacm(VACM vacm) {
171     this.vacm = vacm;
172   }
173   public OctetString getContextEngineID() {
174     return ownContextEngineID;
175   }
176   public void setContextEngineID(OctetString contextEngineID) {
177     this.ownContextEngineID = contextEngineID;
178   }
179
180   /**
181    * Sends notification/inform messages to all registered targets. This method
182    * uses the internal {@link ThreadPool} to send the message(s) via the
183    * <code>NotificationOriginator</code>
184    * (see {@link #getNotificationOriginator}) to the targets specified by the
185    * SnmpTargetMIB and SnmpNotificationMIB instances supplied to the
186    * notification originator.
187    *
188    * @param context
189    * the context name of the context on whose behalf this notification has
190    * been generated.
191    * @param notificationID
192    * the object ID that uniquely identifies this notification. For SNMPv1
193    * traps, the notification ID has to be build using the rules provided
194    * by RFC 2576.
195    * @param vbs
196    * an array of <code>VariableBinding</code> instances representing the
197    * payload of the notification.
198    * @return
199    * an array of ResponseEvent instances or NotificationTask instance if
200    * the notification has been send asynchronously. Since the
201    * <code>NotificationOriginator</code> determines on behalf of the
202    * SNMP-NOTIFICTON-MIB contents whether a notification is sent as
203    * trap/notification or as inform request, the returned array will contain
204    * an element for each addressed target, but only a response PDU for
205    * inform targets.
206    * <p>
207    * <code>null</code> will be returned when sending the notification failed
208    * because there is no {@link NotificationOriginator} set.
209    * <p>
210    * NOTE: If this command processor is using a ThreadPool then the returned
211    * object will be {@link NotificationTask} instance. If all response have
212    * been received {@link Object#notify()} will be called on the returned
213    * <code>NotificationTask</code> object by the sending thread.
214    */

215   public Object JavaDoc notify(final OctetString context,
216                        final OID notificationID,
217                        final VariableBinding[] vbs) {
218     return notify(context, notificationID, null, vbs);
219   }
220
221   public Object JavaDoc notify(OctetString context, OID notificationID,
222                        TimeTicks sysUpTime, VariableBinding[] vbs) {
223     if (notificationOriginator != null) {
224       NotificationTask notifyTask =
225           new NotificationTask(notificationOriginator,
226                                context, notificationID,
227                                sysUpTime, vbs);
228       if (threadPool != null) {
229         threadPool.execute(notifyTask);
230         return notifyTask;
231       }
232       else {
233         notifyTask.run();
234         return notifyTask.getResponses();
235       }
236     }
237     else {
238       logger.warn("Could not sent notification '"+notificationID+"'="+
239                   Arrays.asList(vbs)+" because NotificationOriginator not set");
240     }
241     return null;
242   }
243
244
245   public void setNotificationOriginator(NotificationOriginator
246                                         notificationOriginator) {
247     this.notificationOriginator = notificationOriginator;
248   }
249
250   public void setCoexistenceProvider(CoexistenceInfoProvider
251                                      coexistenceProvider) {
252     this.coexistenceProvider = coexistenceProvider;
253   }
254
255   public ProxyForwarder addProxyForwarder(ProxyForwarder proxyForwarder,
256                                           OctetString contextEngineID,
257                                           int proxyType) {
258     if (this.proxyForwarder == null) {
259       this.proxyForwarder = new ProxyMap();
260     }
261     return this.proxyForwarder.add(proxyForwarder, contextEngineID, proxyType);
262   }
263
264   public ProxyForwarder removeProxyForwarder(OctetString contextEngineID,
265                                           int proxyType) {
266     if (proxyForwarder != null) {
267       return proxyForwarder.remove(contextEngineID, proxyType);
268     }
269     return null;
270   }
271
272   protected RequestHandler getHandler(int pduType) {
273     synchronized (pduHandler) {
274       for (int i = 0; i < pduHandler.size(); i++) {
275         RequestHandler handler = (RequestHandler) pduHandler.get(i);
276         if (handler.isSupported(pduType)) {
277           return handler;
278         }
279       }
280     }
281     return null;
282   }
283
284   protected void dispatchCommand(CommandResponderEvent command,
285                                  CoexistenceInfo cinfo) {
286     RequestHandler handler = getHandler(command.getPDU().getType());
287     if (handler != null) {
288       processRequest(command, cinfo, handler);
289     }
290     else {
291       sendUnknownPDUHandlersReport(command);
292     }
293   }
294
295   private void sendUnknownPDUHandlersReport(CommandResponderEvent command) {
296     logger.info("No PDU handler found for request "+command);
297     CounterEvent counter =
298         new CounterEvent(this, SnmpConstants.snmpUnknownPDUHandlers);
299     fireIncrementCounter(counter);
300     if ((command.getMessageProcessingModel() == MessageProcessingModel.MPv3) &&
301         (command.getPDU() instanceof ScopedPDU)) {
302       ScopedPDU request = (ScopedPDU) command.getPDU();
303       ScopedPDU report = new ScopedPDU();
304       report.setContextEngineID(request.getContextEngineID());
305       report.setContextName(request.getContextName());
306       report.setType(PDU.REPORT);
307       report.add(new VariableBinding(counter.getOid(),
308                                      counter.getCurrentValue()));
309       sendResponse(command, report);
310     }
311     else {
312       PDU resp = (PDU) command.getPDU().clone();
313       resp.setErrorStatus(PDU.genErr);
314       sendResponse(command, resp);
315     }
316   }
317
318   protected void processRequest(CommandResponderEvent command,
319                                 CoexistenceInfo cinfo, RequestHandler handler) {
320     Request req = requestFactory.createRequest(command, cinfo);
321     requestList.add(req);
322
323     MOServer server = null;
324     OctetString context = req.getContext();
325     OctetString viewName = getViewName(command, cinfo, req.getViewType());
326     if (viewName == null) {
327       setAuthorizationError(req, VACM.VACM_NO_SUCH_VIEW);
328     }
329     else {
330       req.setViewName(viewName);
331       server = getServer(context);
332       processRequest(server, handler, req);
333     }
334     finalizeRequest(command, req, server);
335   }
336
337   protected void reprocessRequest(MOServer server, SnmpRequest req) {
338     RequestHandler handler =
339         getHandler(req.getInitiatingEvent().getPDU().getType());
340     if (handler != null) {
341       req.resetProcessedStatus();
342       req.incReprocessCounter();
343       processRequest(server, handler, req);
344     }
345     else {
346       sendUnknownPDUHandlersReport(req.getInitiatingEvent());
347     }
348   }
349
350   /**
351    * Processs (or re-process) a request and try to complete the request (thus
352    * to complete any incomplete subrequests).
353    *
354    * @param server
355    * the <code>MOServer</code> instance to use for accessing instrumentation.
356    * @param handler
357    * the <code>RequestHandler</code> to use to process the request.
358    * @param req
359    * the <code>Request</code>.
360    */

361   protected void processRequest(MOServer server,
362                                 RequestHandler handler,
363                                 Request req) {
364
365     if (server == null) {
366       logger.error("No server for "+req.getContext()+
367                    " found -> request cannot be processed");
368       req.setErrorStatus(SnmpConstants.SNMP_ERROR_GENERAL_ERROR);
369     }
370     else {
371       handler.processPdu(req, server);
372     }
373   }
374
375   protected void finalizeRequest(CommandResponderEvent command, Request req,
376                                  MOServer server) {
377     if (req.isComplete()) {
378       requestList.remove(req);
379       // send response
380
sendResponse(command, (PDU)req.getResponse());
381       if (server != null) {
382         release(server, req);
383       }
384     }
385   }
386
387   protected void release(MOServer server, Request req) {
388     for (Iterator it = req.iterator(); it.hasNext();) {
389       SubRequest sreq = (SubRequest)it.next();
390       if (sreq.getTargetMO() != null) {
391         server.unlock(req, sreq.getTargetMO());
392       }
393     }
394   }
395
396   protected void sendResponse(CommandResponderEvent requestEvent,
397                               PDU response) {
398     MessageDispatcher disp = requestEvent.getMessageDispatcher();
399     try {
400       if (response.getBERLength() > requestEvent.getMaxSizeResponsePDU()) {
401         // response is tooBig
402
if (response.getType() != PDU.REPORT) {
403           if (requestEvent.getPDU().getType() == PDU.GETBULK) {
404             while ((response.size() > 0) &&
405                    (response.getBERLength() >
406                     requestEvent.getMaxSizeResponsePDU())) {
407               response.trim();
408             }
409           }
410           else {
411             response.clear();
412             response.setRequestID(requestEvent.getPDU().getRequestID());
413             response.setErrorStatus(PDU.tooBig);
414           }
415         }
416         if (response.getBERLength() > requestEvent.getMaxSizeResponsePDU()) {
417           fireIncrementCounter(new CounterEvent(this,
418                                                 SnmpConstants.snmpSilentDrops));
419           return;
420         }
421       }
422       StatusInformation status = new StatusInformation();
423       requestEvent.getStateReference().
424           setTransportMapping(requestEvent.getTransportMapping());
425       disp.returnResponsePdu(requestEvent.getMessageProcessingModel(),
426                              requestEvent.getSecurityModel(),
427                              requestEvent.getSecurityName(),
428                              requestEvent.getSecurityLevel(),
429                              response,
430                              requestEvent.getMaxSizeResponsePDU(),
431                              requestEvent.getStateReference(),
432                              status);
433     }
434     catch (MessageException ex) {
435       logger.error("Failed to send response to request "+requestEvent, ex);
436     }
437   }
438
439   protected void setAuthorizationError(Request req, int vacmStatus) {
440     if (req.size() > 0) {
441       SubRequest sreq = (SubRequest) req.iterator().next();
442       sreq.getStatus().setErrorStatus(PDU.authorizationError);
443     }
444     else {
445       req.setErrorStatus(PDU.authorizationError);
446     }
447   }
448
449   public void addPduHandler(RequestHandler handler) {
450     pduHandler.add(handler);
451   }
452
453   public void removePduHandler(RequestHandler handler) {
454     pduHandler.remove(handler);
455   }
456
457   public void addMOServer(MOServer server) {
458     moServers.add(server);
459   }
460
461   public void removeMOServer(MOServer server) {
462     moServers.remove(server);
463   }
464
465   public MOServer getServer(OctetString context) {
466     for (int i=0; i<moServers.size(); i++) {
467       MOServer s = (MOServer)moServers.get(i);
468       if (s.isContextSupported(context)) {
469         return s;
470       }
471     }
472     return null;
473   }
474
475   public TemporaryList getRequestList() {
476     return requestList;
477   }
478
479   public NotificationOriginator getNotificationOriginator() {
480     return notificationOriginator;
481   }
482
483   public ProxyMap getProxyForwarder() {
484     return proxyForwarder;
485   }
486
487   public CoexistenceInfoProvider getCoexistenceProvider() {
488     return coexistenceProvider;
489   }
490
491
492   class Command implements Runnable JavaDoc {
493
494     private CommandResponderEvent request;
495     private CoexistenceInfo cinfo;
496
497     public Command(CommandResponderEvent event, CoexistenceInfo cinfo) {
498       this.request = event;
499       this.cinfo = cinfo;
500     }
501
502     public void run() {
503       dispatchCommand(request, cinfo);
504     }
505   }
506
507   class ProxyCommand implements Runnable JavaDoc {
508
509     private ProxyForwardRequest request;
510     private ProxyForwarder forwarder;
511
512     public ProxyCommand(ProxyForwarder forwarder, ProxyForwardRequest event) {
513       this.forwarder = forwarder;
514       this.request = event;
515     }
516
517     public void run() {
518       if (forwarder.forward(request)) {
519         PDU response = request.getResponsePDU();
520         if (response != null) {
521           sendResponse(request.getCommandEvent(), response);
522         }
523       }
524       else if (request.getProxyType() != ProxyForwarder.PROXY_TYPE_NOTIFY) {
525         // proxy drop
526
CounterEvent cevent = new CounterEvent(this,
527                                                SnmpConstants.snmpProxyDrops);
528         fireIncrementCounter(cevent);
529         if (request.getCommandEvent().getMessageProcessingModel() == MPv3.ID) {
530           ScopedPDU reportPDU = new ScopedPDU();
531           reportPDU.setType(PDU.REPORT);
532           reportPDU.setContextEngineID(request.getContextEngineID());
533           reportPDU.setContextName(request.getContext());
534           reportPDU.add(new VariableBinding(SnmpConstants.snmpProxyDrops,
535                                             cevent.getCurrentValue()));
536           sendResponse(request.getCommandEvent(), reportPDU);
537         }
538       }
539     }
540   }
541
542   protected OctetString getViewName(CommandResponderEvent req,
543                                     CoexistenceInfo cinfo,
544                                     int viewType) {
545     OctetString viewName =
546         vacm.getViewName(cinfo.getContextName(),
547                          cinfo.getSecurityName(),
548                          req.getSecurityModel(),
549                          req.getSecurityLevel(),
550                          viewType);
551     return viewName;
552   }
553
554   protected void processNextSubRequest(Request request, MOServer server,
555                                        OctetString context,
556                                        SubRequest sreq)
557       throws NoSuchElementException
558   {
559     // We can be sure to have a default context scope here because
560
// the inner class SnmpSubRequest creates it!
561
DefaultMOContextScope scope = (DefaultMOContextScope) sreq.getScope();
562     MOQuery query = sreq.getQuery();
563     if (query == null) {
564       query = new VACMQuery(context,
565                             scope.getLowerBound(),
566                             scope.isLowerIncluded(),
567                             scope.getUpperBound(),
568                             scope.isUpperIncluded(),
569                             request.getViewName());
570       sreq.setQuery(query);
571     }
572     while (!sreq.getStatus().isProcessed()) {
573       ManagedObject mo = server.lookup(query);
574       if (mo == null) {
575         if (logger.isDebugEnabled()) {
576           logger.debug("EndOfMibView at scope="+scope+" and query "+query);
577         }
578         sreq.getVariableBinding().setVariable(Null.endOfMibView);
579         sreq.getStatus().setPhaseComplete(true);
580         continue;
581       }
582       try {
583         if (logger.isDebugEnabled()) {
584           logger.debug("Processing NEXT query "+query+" with "+mo+
585                        " sub-request with index "+sreq.getIndex());
586         }
587         if ((!mo.next(sreq)) ||
588              ((request.getMessageProcessingModel() == MPv1.ID) &&
589               (sreq.getVariableBinding().getSyntax() ==
590                SMIConstants.SYNTAX_COUNTER64))) {
591           sreq.getVariableBinding().setVariable(Null.instance);
592           scope.substractScope(mo.getScope());
593           // don't forget to update VACM query:
594
query.substractScope(mo.getScope());
595         }
596       }
597       catch (Exception JavaDoc moex) {
598         if (logger.isDebugEnabled()) {
599           moex.printStackTrace();
600         }
601         logger.error("Exception occurred while executing NEXT query: "+
602                      moex.getMessage(), moex);
603         if (sreq.getStatus().getErrorStatus() == PDU.noError) {
604           sreq.getStatus().setErrorStatus(PDU.genErr);
605         }
606         if (SNMP4JSettings.isFowardRuntimeExceptions()) {
607           throw new RuntimeException JavaDoc(moex);
608         }
609       }
610     }
611   }
612
613   public synchronized void addCounterListener(CounterListener l) {
614     if (counterListeners == null) {
615       counterListeners = new Vector(2);
616     }
617     counterListeners.add(l);
618   }
619
620   public synchronized void removeCounterListener(CounterListener l) {
621     if (counterListeners != null) {
622       counterListeners.remove(l);
623     }
624   }
625
626   protected void fireIncrementCounter(CounterEvent event) {
627     if (counterListeners != null) {
628       Vector listeners = counterListeners;
629       int count = listeners.size();
630       for (int i = 0; i < count; i++) {
631         ((CounterListener) listeners.elementAt(i)).incrementCounter(event);
632       }
633     }
634   }
635
636   private static void initRequestPhase(Request request) {
637     if (request.getPhase() == Request.PHASE_INIT) {
638       request.nextPhase();
639     }
640   }
641
642   class GetNextHandler implements RequestHandler {
643
644     public void processPdu(Request request, MOServer server) {
645       initRequestPhase(request);
646       OctetString context = request.getContext();
647       try {
648         SubRequestIterator it = (SubRequestIterator) request.iterator();
649         while (it.hasNext()) {
650           SubRequest sreq = it.nextSubRequest();
651           processNextSubRequest(request, server, context, sreq);
652         }
653       }
654       catch (NoSuchElementException nsex) {
655         if (logger.isDebugEnabled()) {
656           nsex.printStackTrace();
657         }
658         logger.error("SubRequest not found");
659         request.setErrorStatus(PDU.genErr);
660       }
661     }
662
663
664     public boolean isSupported(int pduType) {
665       return (pduType == PDU.GETNEXT);
666     }
667
668   }
669
670   class SetHandler implements RequestHandler {
671
672     public void prepare(OctetString context,
673                         Request request, MOServer server) {
674       try {
675         SubRequestIterator it = (SubRequestIterator) request.iterator();
676         while ((!request.isPhaseComplete()) && (it.hasNext())) {
677           SubRequest sreq = it.nextSubRequest();
678           if (sreq.isComplete()) {
679             continue;
680           }
681           MOScope scope = sreq.getScope();
682           MOQuery query = sreq.getQuery();
683           if (query == null) {
684             // create a query for write access
685
query = new VACMQuery(context,
686                                   scope.getLowerBound(),
687                                   scope.isLowerIncluded(),
688                                   scope.getUpperBound(),
689                                   scope.isUpperIncluded(),
690                                   request.getViewName());
691             sreq.setQuery(query);
692           }
693           if (!query.getScope().isCovered(
694               new DefaultMOContextScope(context, scope))) {
695             sreq.getStatus().setErrorStatus(PDU.noAccess);
696           }
697           else {
698             ManagedObject mo = server.lookup(query);
699             if (mo == null) {
700               if ((query instanceof VACMQuery) &&
701                   (!((VACMQuery)query).isAccessAllowed(scope.getLowerBound()))){
702                 sreq.getStatus().setErrorStatus(PDU.noAccess);
703               }
704               else {
705                 sreq.getStatus().setErrorStatus(PDU.notWritable);
706               }
707               break;
708             }
709             sreq.setTargetMO(mo);
710             server.lock(sreq.getRequest(), mo);
711             try {
712               mo.prepare(sreq);
713             }
714             catch (Exception JavaDoc moex) {
715               logger.error("Set request "+request+" failed with exception",
716                            moex);
717               if (sreq.getStatus().getErrorStatus() == PDU.noError) {
718                 sreq.getStatus().setErrorStatus(PDU.genErr);
719               }
720               if (SNMP4JSettings.isFowardRuntimeExceptions()) {
721                 throw new RuntimeException JavaDoc(moex);
722               }
723             }
724           }
725         }
726       }
727       catch (NoSuchElementException nsex) {
728         if (logger.isDebugEnabled()) {
729           nsex.printStackTrace();
730         }
731         logger.error("Cannot find sub-request: ", nsex);
732         request.setErrorStatus(PDU.genErr);
733       }
734     }
735
736     public void processPdu(Request request, MOServer server) {
737       OctetString context = request.getContext();
738       try {
739         while (request.getPhase() < Request.PHASE_2PC_CLEANUP) {
740           int phase = request.nextPhase();
741           switch (phase) {
742             case Request.PHASE_2PC_PREPARE: {
743               prepare(context, request, server);
744               break;
745             }
746             case Request.PHASE_2PC_COMMIT: {
747               commit(context, request, server);
748               break;
749             }
750             case Request.PHASE_2PC_UNDO: {
751               undo(context, request, server);
752               break;
753             }
754             case Request.PHASE_2PC_CLEANUP: {
755               cleanup(context, request, server);
756               return;
757             }
758           }
759           if (!request.isPhaseComplete()) {
760             // request needs to be reprocessed later!
761
return;
762           }
763         }
764       }
765       catch (Exception JavaDoc ex) {
766         if (logger.isDebugEnabled()) {
767           ex.printStackTrace();
768         }
769         logger.error("Failed to process SET request, trying to clean it up...",
770                      ex);
771         if (SNMP4JSettings.isFowardRuntimeExceptions()) {
772           throw new RuntimeException JavaDoc(ex);
773         }
774       }
775       cleanup(context, request, server);
776     }
777
778     protected void undo(OctetString context, Request request,
779                         MOServer server) {
780       try {
781         SubRequestIterator it = (SubRequestIterator) request.iterator();
782         while (it.hasNext()) {
783           SubRequest sreq = it.nextSubRequest();
784           if (sreq.isComplete()) {
785             continue;
786           }
787           OID oid = sreq.getVariableBinding().getOid();
788           ManagedObject mo = sreq.getTargetMO();
789           if (mo == null) {
790             DefaultMOContextScope scope =
791                 new DefaultMOContextScope(context, oid, true, oid, true);
792             mo = server.lookup(new DefaultMOQuery(scope, true, request));
793           }
794           if (mo == null) {
795             sreq.getStatus().setErrorStatus(PDU.undoFailed);
796             continue;
797           }
798           try {
799             mo.undo(sreq);
800           }
801           catch (Exception JavaDoc moex) {
802             if (logger.isDebugEnabled()) {
803               moex.printStackTrace();
804             }
805             logger.error(moex);
806             if (sreq.getStatus().getErrorStatus() == PDU.noError) {
807               sreq.getStatus().setErrorStatus(PDU.undoFailed);
808             }
809             if (SNMP4JSettings.isFowardRuntimeExceptions()) {
810               throw new RuntimeException JavaDoc(moex);
811             }
812           }
813         }
814       }
815       catch (NoSuchElementException nsex) {
816         if (logger.isDebugEnabled()) {
817           nsex.printStackTrace();
818         }
819         logger.error("Cannot find sub-request: ", nsex);
820         request.setErrorStatus(PDU.genErr);
821       }
822     }
823
824     protected void commit(OctetString context, Request request,
825                           MOServer server) {
826       try {
827         SubRequestIterator it = (SubRequestIterator) request.iterator();
828         while ((request.getErrorStatus() == PDU.noError) && (it.hasNext())) {
829           SubRequest sreq = it.nextSubRequest();
830           if (sreq.isComplete()) {
831             continue;
832           }
833           OID oid = sreq.getVariableBinding().getOid();
834           ManagedObject mo = sreq.getTargetMO();
835           if (mo == null) {
836             DefaultMOContextScope scope =
837                 new DefaultMOContextScope(context, oid, true, oid, true);
838             mo = server.lookup(new DefaultMOQuery(scope, true, request));
839           }
840           if (mo == null) {
841             sreq.getStatus().setErrorStatus(PDU.commitFailed);
842             continue;
843           }
844           try {
845             mo.commit(sreq);
846           }
847           catch (Exception JavaDoc moex) {
848             if (logger.isDebugEnabled()) {
849               moex.printStackTrace();
850             }
851             logger.error(moex);
852             if (sreq.getStatus().getErrorStatus() == PDU.noError) {
853               sreq.getStatus().setErrorStatus(PDU.commitFailed);
854             }
855             if (SNMP4JSettings.isFowardRuntimeExceptions()) {
856               throw new RuntimeException JavaDoc(moex);
857             }
858           }
859         }
860       }
861       catch (NoSuchElementException nsex) {
862         if (logger.isDebugEnabled()) {
863           nsex.printStackTrace();
864         }
865         logger.error("Cannot find sub-request: ", nsex);
866         request.setErrorStatus(PDU.genErr);
867       }
868     }
869
870     protected void cleanup(OctetString context, Request request,
871                            MOServer server) {
872       try {
873         SubRequestIterator it = (SubRequestIterator) request.iterator();
874         while (it.hasNext()) {
875           SubRequest sreq = it.nextSubRequest();
876           if (sreq.isComplete()) {
877             continue;
878           }
879           OID oid = sreq.getVariableBinding().getOid();
880           ManagedObject mo = sreq.getTargetMO();
881           if (mo == null) {
882             DefaultMOContextScope scope =
883                 new DefaultMOContextScope(context, oid, true, oid, true);
884             mo = server.lookup(new DefaultMOQuery(scope));
885           }
886           if (mo == null) {
887             sreq.completed();
888             continue;
889           }
890           server.unlock(sreq.getRequest(), mo);
891           try {
892             mo.cleanup(sreq);
893             sreq.getStatus().setPhaseComplete(true);
894           }
895           catch (Exception JavaDoc moex) {
896             if (logger.isDebugEnabled()) {
897               moex.printStackTrace();
898             }
899             logger.error(moex);
900             if (SNMP4JSettings.isFowardRuntimeExceptions()) {
901               throw new RuntimeException JavaDoc(moex);
902             }
903           }
904         }
905       }
906       catch (NoSuchElementException nsex) {
907         logger.error("Cannot find sub-request: ", nsex);
908         if (logger.isDebugEnabled()) {
909           nsex.printStackTrace();
910         }
911       }
912     }
913
914     public boolean isSupported(int pduType) {
915       return (pduType == PDU.SET);
916     }
917
918   }
919
920   class GetHandler implements RequestHandler {
921
922     public boolean isSupported(int pduType) {
923       return (pduType == PDU.GET);
924     }
925
926     public void processPdu(Request request, MOServer server) {
927       initRequestPhase(request);
928       OctetString context = request.getContext();
929       try {
930         SubRequestIterator it = (SubRequestIterator) request.iterator();
931         while (it.hasNext()) {
932           SubRequest sreq = it.nextSubRequest();
933           MOScope scope = sreq.getScope();
934           MOQuery query = sreq.getQuery();
935           if (query == null) {
936             query = new VACMQuery(context,
937                                   scope.getLowerBound(),
938                                   scope.isLowerIncluded(),
939                                   scope.getUpperBound(),
940                                   scope.isUpperIncluded(),
941                                   request.getViewName());
942             sreq.setQuery(query);
943           }
944           ManagedObject mo = server.lookup(query);
945           if (mo == null) {
946             sreq.getVariableBinding().setVariable(Null.noSuchObject);
947             sreq.getStatus().setPhaseComplete(true);
948             continue;
949           }
950           try {
951             mo.get(sreq);
952             if ((request.getMessageProcessingModel() == MPv1.ID) &&
953                 (sreq.getVariableBinding().getSyntax() ==
954                  SMIConstants.SYNTAX_COUNTER64)) {
955               sreq.getVariableBinding().setVariable(Null.noSuchInstance);
956             }
957           }
958           catch (Exception JavaDoc moex) {
959             if (logger.isDebugEnabled()) {
960               moex.printStackTrace();
961             }
962             logger.warn(moex);
963             if (sreq.getStatus().getErrorStatus() == PDU.noError) {
964               sreq.getStatus().setErrorStatus(PDU.genErr);
965             }
966             if (SNMP4JSettings.isFowardRuntimeExceptions()) {
967               throw new RuntimeException JavaDoc(moex);
968             }
969           }
970         }
971       }
972       catch (NoSuchElementException nsex) {
973         if (logger.isDebugEnabled()) {
974           nsex.printStackTrace();
975         }
976         logger.error("SubRequest not found");
977         request.setErrorStatus(PDU.genErr);
978       }
979     }
980
981   }
982
983   class GetBulkHandler implements RequestHandler {
984
985     public boolean isSupported(int pduType) {
986       return (pduType == PDU.GETBULK);
987     }
988
989     public void processPdu(Request request, MOServer server) {
990       initRequestPhase(request);
991       OctetString context = request.getContext();
992       SnmpRequest req = (SnmpRequest)request;
993       int nonRep = req.getNonRepeaters();
994       try {
995         SubRequestIterator it = (SubRequestIterator) request.iterator();
996         int i = 0;
997         // non repeaters
998
for (; ((i < nonRep) && it.hasNext()); i++) {
999           SubRequest sreq = it.nextSubRequest();
1000          if (!sreq.isComplete()) {
1001            processNextSubRequest(request, server, context, sreq);
1002          }
1003        }
1004        // repetitions
1005
for (; it.hasNext(); i++) {
1006          SubRequest sreq = it.nextSubRequest();
1007          if (!sreq.isComplete()) {
1008            processNextSubRequest(request, server, context, sreq);
1009            sreq.updateNextRepetition();
1010          }
1011        }
1012      }
1013      catch (NoSuchElementException nsex) {
1014        if (logger.isDebugEnabled()) {
1015          nsex.printStackTrace();
1016        }
1017        logger.error("SubRequest not found");
1018        request.setErrorStatus(PDU.genErr);
1019      }
1020    }
1021  }
1022
1023  class VACMQuery extends DefaultMOQuery {
1024
1025    private OctetString viewName;
1026
1027    /**
1028     * Creates a VACMQuery for read-only access.
1029     * @param context
1030     * the context for the query, an empty OctetString denotes the default
1031     * context.
1032     * @param lowerBound
1033     * the lower bound OID.
1034     * @param isLowerIncluded
1035     * indicates whether the lower bound should be included or not.
1036     * @param upperBound
1037     * the upper bound OID or <code>null</code> if no upper bound is
1038     * specified.
1039     * @param isUpperIncluded
1040     * indicates whether the upper bound should be included or not.
1041     * @param viewName
1042     * the view name to use for the query.
1043     * @deprecated
1044     * Use a constructor with <code>source</code> reference parameter instead.
1045     */

1046    public VACMQuery(OctetString context,
1047                     OID lowerBound, boolean isLowerIncluded,
1048                     OID upperBound, boolean isUpperIncluded,
1049                     OctetString viewName) {
1050      super(new DefaultMOContextScope(context,
1051                                      lowerBound, isLowerIncluded,
1052                                      upperBound, isUpperIncluded));
1053      this.viewName = viewName;
1054    }
1055
1056    /**
1057     * Creates a VACMQuery for read-only access.
1058     * @param context
1059     * the context for the query, an empty OctetString denotes the default
1060     * context.
1061     * @param lowerBound
1062     * the lower bound OID.
1063     * @param isLowerIncluded
1064     * indicates whether the lower bound should be included or not.
1065     * @param upperBound
1066     * the upper bound OID or <code>null</code> if no upper bound is
1067     * specified.
1068     * @param isUpperIncluded
1069     * indicates whether the upper bound should be included or not.
1070     * @param viewName
1071     * the view name to use for the query.
1072     * @param isWriteAccessIntended
1073     * indicates if this query is issued on behalf of a SNMP SET request
1074     * or not.
1075     * @param source
1076     * the source ({@link Request}) object on whose behalf this query is
1077     * executed.
1078     * @since 1.1
1079     */

1080    public VACMQuery(OctetString context,
1081                     OID lowerBound, boolean isLowerIncluded,
1082                     OID upperBound, boolean isUpperIncluded,
1083                     OctetString viewName,
1084                     boolean isWriteAccessIntended,
1085                     Object JavaDoc source) {
1086      super(new DefaultMOContextScope(context,
1087                                      lowerBound, isLowerIncluded,
1088                                      upperBound, isUpperIncluded),
1089            isWriteAccessIntended, source);
1090      this.viewName = viewName;
1091    }
1092
1093    public boolean isSearchQuery() {
1094      MOContextScope scope = getScope();
1095      return ((!scope.isLowerIncluded()) &&
1096              ((scope.getUpperBound() == null) ||
1097               (!scope.getUpperBound().equals(scope.getLowerBound()))));
1098    }
1099
1100    public boolean matchesQuery(ManagedObject managedObject) {
1101      OID oid;
1102      if (isSearchQuery()) {
1103         oid = managedObject.find(getScope());
1104         if (oid == null) {
1105           return false;
1106         }
1107      }
1108      else {
1109        oid = getScope().getLowerBound();
1110      }
1111      return (vacm.isAccessAllowed(viewName, oid) == VACM.VACM_OK);
1112    }
1113
1114    public boolean isAccessAllowed(OID oid) {
1115      return (vacm.isAccessAllowed(viewName, oid) == VACM.VACM_OK);
1116    }
1117
1118    public String JavaDoc toString() {
1119      return super.toString()+
1120          "[viewName="+viewName+"]";
1121    }
1122
1123  }
1124
1125  static class DefaultRequestFactory implements RequestFactory {
1126    public Request createRequest(EventObject initiatingEvent,
1127                                 CoexistenceInfo cinfo) {
1128      return new SnmpRequest((CommandResponderEvent)initiatingEvent, cinfo);
1129    }
1130
1131  }
1132
1133}
1134
Popular Tags