1 /*
  2  * Copyright © [2008-2009] Novell, Inc. All Rights Reserved.
  3  * 
  4  * Novell grants permission, free of charge, to any person obtaining copies of this 
  5  * software and its associated documentation files (the "Software"), to deal in the 
  6  * Software without restriction, including to use, copy, adapt, publish, distribute, 
  7  * display, perform, sublicense, and sell copies of the Software, subject to the following 
  8  * condition: You must include the above copyright notice and this permission notice in 
  9  * all full or partial copies of the Software.
 10  * 
 11  * NOVELL PROVIDES THE SOFTWARE "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 
 12  * INCLUDING WITHOUT THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 13  * PURPOSE, AND NON-INFRINGMENT.  NOVELL, THE AUTHORS OF THE SOFTWARE, AND THE OWNERS OF 
 14  * COPYRIGHT IN THE SOFTWARE ARE NOT LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, 
 15  * WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN 
 16  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 17  */
 18 
 19 /**
 20  * @fileoverview
 21  * This file contains the non-template routines that must be completed to create a new
 22  * Collector. The methods defined in this file extend a number of other classes.
 23  */
 24 
 25 /**
 26  * The initialize method is used to perform any event source-specific initialization
 27  * routines required to support processing of data from this event source.  
 28  * <p>Common things done in this section are:
 29  * <ul>
 30  * <li>Load any custom parameters
 31  * <li>Pre-set static event fields in the instance.protoEvt object
 32  * <li>Send any initialization strings to the Connector
 33  * </ul>
 34  * @return {Boolean}  Whether the initialization was successful
 35  */
 36 Collector.prototype.initialize = function(){
 37 
 38 	// Example code to define a parser that can determine the latest offset from new records
 39 	// Use this for DATABASE sources (see SQLQuery class)
 40 	this.PARSER.getOffsetData = function(input){
 41 		// parser code, like "return input.RXMap.col_AutoID"
 42 	}
 43 	conn.addParser(this.PARSER.getOffsetData);
 44 	
 45 	// Example code to load standard syslog maps - use this for SYSLOG sources
 46 	this.MAPS.syslogSev = new KeyMap(this.CONFIG.collDir + "syslog_severity.map");
 47 	this.MAPS.syslogFac = new KeyMap(this.CONFIG.collDir + "syslog_facility.map");
 48 	
 49 	return true;
 50 }
 51 /**
 52  * Cleans up the environment when the Collector is stopped.
 53  * Use this method to shut down or close any external connections necessary when the Collector is
 54  * stopped. This is rarely necessary as most ESM components already shut down on their own.
 55  * @return void
 56  */
 57 Collector.prototype.cleanup = function(){
 58     return true;
 59 }
 60 
 61 /**
 62  * The sendQuery() method will transmit a string to the Connector for processing;
 63  * for example with the DB Connector this would be the database query, and for the
 64  * Process Connector this would be passed to STDIN of the process. See each Connector's
 65  * documentation for details.
 66  * Please note that for many Connectors this step is not necessary, and can be skipped.
 67  * For the Database Connector in particular, the template will help handle offsets and suboffsets
 68  * automatically if you define parsers for them (see SQLQuery class), and will handle the complexities
 69  * of re-querying the DB (hence, you'd only use this in special circumstances).
 70  * <p>Example:
 71  * <code>
 72  * // Note: not an example of usage, but of implementation:
 73  * Record.prototype.sendQuery = function() {
 74  *   conn.send("exec fetch");
 75  *   return true;
 76  * }
 77  * </code>
 78  * @return {Boolean}  Whether the query was sent correctly
 79  * @see SQLQuery
 80  */
 81 Connector.prototype.sendQuery = function(){
 82     return true;
 83 }
 84 
 85 /**
 86  * The preParse() method should be used to perform preliminary data
 87  * cleaning prior to the main parsing step.
 88  * For example, you might need to strip end-of-record characters, replace unsafe 
 89  * characters, check to make sure you have a full record, filter out certain events, etc.
 90  * You should also check for error conditions coming back from the Connector, which are
 91  * typically recorded in rec.connErr.
 92  * <p>Example:
 93  * <code>
 94  * // Note: not an example of usage, but of implementation:
 95  * Record.prototype.preParse = function(e) {
 96  *  if( rec.connErr != "" )  { return false; }
 97  *  this.replace(/\n/, ""));
 98  *  return true;
 99  * }
100  * </code>
101  * @param {Event} e  The current instance of the output event, this is in
102  * general not used directly but is provided for reference or for presetting fields.
103  * @return {Boolean}  Whether the preParse() method completed without errors.
104  */ 
105 Record.prototype.preParse = function(e){
106     if (this.CONNECTION_ERROR != null || typeof this.RXMap == "undefined") { return false; }
107     
108     // Example code on some standard syslog-style parsing
109     if (this.CONNECTION_METHOD == "SYSLOG" && this.CONNECTION_MODE == "map") {
110         // We can pre-set certain fields - we will do this directly against
111         // the Event object, even though this is in general bad practice
112         e.ReporterIP = this.s_SyslogRelayIp;
113         if (this.s_MessageOriginatorHost.search(/\d+\.\d+\.\d+\.\d+/) != -1) {
114             e.ObserverIP = this.s_MessageOriginatorHost;
115         }
116         else {
117             e.ObserverHostName = this.s_MessageOriginatorHost;
118         }
119         e.Severity = instance.MAPS.syslogSev.lookup(this.i_syslog_severity);
120         e.ObserverChannel = instance.MAPS.syslogFac.lookup(this.i_syslog_facility);
121 		// use the below logic for below 6r5 syslog connector
122         this.syslogMsg = this.s_RXBufferString.parseSyslog();
123         e.setDeviceEventTime(this.syslogMsg.date);
124         this.s_RXBufferString = this.syslogMsg.message;
125     }
126     return true;
127 }
128 
129 
130 /**
131  * The parse() method is used to perform the main parsing on the input
132  * record. The focus here should be to break the input up into small
133  * data units that can be easily mapped to the Sentinel event structure
134  * in the convert() method. 
135  * <p>Example:
136  * <code>
137  * // Note: not an example of usage, but of implementation:
138  * Record.prototype.parse = function(e) {
139  *   this.inpArray = [];
140  *   this.inpArray = this.safesplit(",");
141  *   return true;
142  * }
143  * </code>
144  * @param {Event} e  The current instance of the output event; this is in
145  * general not used directly but is provided for reference or for presetting fields.
146  * @return {Boolean}  Whether the parse() method completed without errors.
147  */
148 Record.prototype.parse = function(e){
149     // parsing logic goes here
150     if (false) { // set SEND_EVENT to true if your parsing logic worked correctly
151         instance.SEND_EVENT = true;
152     }
153     // If you can't parse...
154     rec.sendUnsupported();
155     return true;
156 }
157 
158 
159 /**
160  * The normalize() method is used to convert data elements from the input
161  * record into Sentinel-friendly data, typically by using external
162  * translation files to look up the data or by performing simple data manipulation.
163  * Most of your normalization can be done in the Record object, but the output
164  * event 'e' is provided for your convenience if you wish to place your
165  * translated data in it directly. In general, however, it is safer and more
166  * convenient to do your work in the Record object, then just let convert()
167  * do the conversion to the output event.
168  * <p>Example:
169  * <code>
170  * // Note: not an example of usage, but of implementation:
171  * Record.prototype.normalize = function(e) {
172  *   this.inpArray = [];
173  *   this.inpArray = this.safesplit(",");
174  *   return true;
175  * }
176  * </code>
177  * @param {Event} e  The current instance of the output event; this is in
178  * general not used directly but is provided for reference or for presetting fields.
179  * @return {Boolean}  Whether the parse() method completed without errors.
180  */
181 Record.prototype.normalize = function(e){
182     return true;
183 }
184 
185 /**
186  * The postParse() method performs any necessary post-processing steps after the
187  * input record is converted into the output event, but before the event is actually
188  * sent. In general this function will not be necessary, but is provided for
189  * special cases.
190  * <p>Example:
191  * <code>
192  * // Note: not an example of usage, but of implementation:
193  * Record.prototype.postParse = function(e) {
194  *   var d = new Date();
195  *   e.EndTime = Date.getTime();
196  *   return true;
197  * }
198  * </code>
199  * @param {Event} e  The current instance of the output event, which should have
200  * a complete set of data in it already.
201  * @return {Boolean}  Whether the postParse() method completed without errors.
202 
203  */ 
204 Record.prototype.postParse = function(e){
205     return true;
206 }
207 
208 /**
209  * The reply method should be used to perform any final acknowledgement to the
210  * Connector that might be necessary. In general this method is not used, but is
211  * provided for special cases.
212  * <p>Example:
213  * <code>
214  * // Note: not an example of usage, but of implementation:
215  * Record.prototype.reply = function(e) {
216  *   conn.send("Event sent successfully\n");
217  *   return true;
218  * }
219  * </code>
220  * @param {Event} e  The current instance of the output event that was just sent.
221  * @return {Boolean}  Whether the reply method completed without errors.
222  */ 
223 Record.prototype.reply = function(e){
224     return true;
225 }