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 	// This Boolean tells the Collector whether the event source reports in UTC or not (if not, it will report in local time)
 39 	instance.CONFIG.params.reportsUTC = false;
 40 
 41 	// Example code to define a parser that can determine the latest offset from new records
 42 	// Use this for DATABASE sources (see SQLQuery class)
 43 	this.PARSER.getOffsetData = function(input){
 44 		// parser code, like "return input.RXMap.col_AutoID"
 45 	}
 46 	conn.addParser(this.PARSER.getOffsetData);
 47 	
 48 	// Example code to load standard syslog maps - use this for SYSLOG sources
 49 	this.MAPS.syslogSev = new KeyMap(this.CONFIG.collDir + "syslog_severity.map");
 50 	this.MAPS.syslogFac = new KeyMap(this.CONFIG.collDir + "syslog_facility.map");
 51 	
 52 	return true;
 53 };
 54 
 55 /**
 56  * Cleans up the environment when the Collector is stopped.
 57  * Use this method to shut down or close any external connections necessary when the Collector is
 58  * stopped. This is rarely necessary as most ESM components already shut down on their own.
 59  * @return void
 60  */
 61 Collector.prototype.cleanup = function(){
 62     return true;
 63 };
 64 
 65 /**
 66  * The sendQuery() method will transmit a string to the Connector for processing;
 67  * for example with the DB Connector this would be the database query, and for the
 68  * Process Connector this would be passed to STDIN of the process. See each Connector's
 69  * documentation for details.
 70  * Please note that for many Connectors this step is not necessary, and can be skipped.
 71  * For the Database Connector in particular, the template will help handle offsets and suboffsets
 72  * automatically if you define parsers for them (see SQLQuery class), and will handle the complexities
 73  * of re-querying the DB (hence, you'd only use this in special circumstances).
 74  * <p>Example:
 75  * <code>
 76  * // Note: not an example of usage, but of implementation:
 77  * Record.prototype.sendQuery = function() {
 78  *   conn.send("exec fetch");
 79  *   return true;
 80  * }
 81  * </code>
 82  * @return {Boolean}  Whether the query was sent correctly
 83  * @see SQLQuery
 84  */
 85 Connector.prototype.sendQuery = function(){
 86     return true;
 87 };
 88 
 89 /**
 90  * The preParse() method should be used to perform preliminary data
 91  * cleaning prior to the main parsing step.
 92  * For example, you might need to strip end-of-record characters, replace unsafe 
 93  * characters, check to make sure you have a full record, filter out certain events, etc.
 94  * You should also check for error conditions coming back from the Connector, which are
 95  * typically recorded in rec.connErr.
 96  * <p>Example:
 97  * <code>
 98  * // Note: not an example of usage, but of implementation:
 99  * Record.prototype.preParse = function(e) {
100  *  if( rec.connErr != "" )  { return false; }
101  *  this.replace(/\n/, ""));
102  *  return true;
103  * }
104  * </code>
105  * @param {Event} e  The current instance of the output event, this is in
106  * general not used directly but is provided for reference or for presetting fields.
107  * @return {Boolean}  Whether the preParse() method completed without errors.
108  */ 
109 Record.prototype.preParse = function(e){
110     if (this.CONNECTION_ERROR != null || typeof this.RXMap == "undefined") { return false; }
111     
112     // Example code on some standard syslog-style parsing
113     if (this.CONNECTION_METHOD == "SYSLOG" && this.CONNECTION_MODE == "map") {
114         // We can pre-set certain fields - we will do this directly against
115         // the Event object, even though this is in general bad practice
116         e.ReporterIP = this.s_SyslogRelayIp;
117         if (this.s_MessageOriginatorHost.search(/\d+\.\d+\.\d+\.\d+/) != -1) {
118             e.ObserverIP = this.s_MessageOriginatorHost;
119         }
120         else {
121             e.ObserverHostName = this.s_MessageOriginatorHost;
122         }
123         e.Severity = instance.MAPS.syslogSev.lookup(this.i_syslog_severity);
124         e.ObserverServiceComponent = instance.MAPS.syslogFac.lookup(this.i_syslog_facility);
125 		// use the below logic for below 6r5 syslog connector
126         this.syslogMsg = this.s_RXBufferString.parseSyslog();
127         e.setObserverEventTime(this.syslogMsg.date);
128         this.s_RXBufferString = this.syslogMsg.message;
129     }
130     return true;
131 };
132 
133 
134 /**
135  * The parse() method is used to perform the main parsing on the input
136  * record. The focus here should be to break the input up into small
137  * data units that can be easily mapped to the Sentinel event structure
138  * in the convert() method. 
139  * <p>Example:
140  * <code>
141  * // Note: not an example of usage, but of implementation:
142  * Record.prototype.parse = function(e) {
143  *   this.inpArray = [];
144  *   this.inpArray = this.safesplit(",");
145  *   return true;
146  * }
147  * </code>
148  * @param {Event} e  The current instance of the output event; this is in
149  * general not used directly but is provided for reference or for presetting fields.
150  * @return {Boolean}  Whether the parse() method completed without errors.
151  */
152 Record.prototype.parse = function(e){
153     // parsing logic goes here
154     if (false) { // set SEND_EVENT to true if your parsing logic worked correctly
155         instance.SEND_EVENT = true;
156     }
157     // If you can't parse...
158     rec.sendUnsupported();
159     return true;
160 };
161 
162 
163 /**
164  * The normalize() method is used to convert data elements from the input
165  * record into Sentinel-friendly data, typically by using external
166  * translation files to look up the data or by performing simple data manipulation.
167  * Most of your normalization can be done in the Record object, but the output
168  * event 'e' is provided for your convenience if you wish to place your
169  * translated data in it directly. In general, however, it is safer and more
170  * convenient to do your work in the Record object, then just let convert()
171  * do the conversion to the output event.
172  * <p>Example:
173  * <code>
174  * // Note: not an example of usage, but of implementation:
175  * Record.prototype.normalize = function(e) {
176  *   this.inpArray = [];
177  *   this.inpArray = this.safesplit(",");
178  *   return true;
179  * }
180  * </code>
181  * @param {Event} e  The current instance of the output event; this is in
182  * general not used directly but is provided for reference or for presetting fields.
183  * @return {Boolean}  Whether the parse() method completed without errors.
184  */
185 Record.prototype.normalize = function(e){
186     return true;
187 };
188 
189 /**
190  * The postParse() method performs any necessary post-processing steps after the
191  * input record is converted into the output event, but before the event is actually
192  * sent. In general this function will not be necessary, but is provided for
193  * special cases.
194  * <p>Example:
195  * <code>
196  * // Note: not an example of usage, but of implementation:
197  * Record.prototype.postParse = function(e) {
198  *   var d = new Date();
199  *   e.EndTime = Date.getTime();
200  *   return true;
201  * }
202  * </code>
203  * @param {Event} e  The current instance of the output event, which should have
204  * a complete set of data in it already.
205  * @return {Boolean}  Whether the postParse() method completed without errors.
206 
207  */ 
208 Record.prototype.postParse = function(e){
209     return true;
210 };
211 
212 /**
213  * The reply method should be used to perform any final acknowledgement to the
214  * Connector that might be necessary. In general this method is not used, but is
215  * provided for special cases.
216  * <p>Example:
217  * <code>
218  * // Note: not an example of usage, but of implementation:
219  * Record.prototype.reply = function(e) {
220  *   conn.send("Event sent successfully\n");
221  *   return true;
222  * }
223  * </code>
224  * @param {Event} e  The current instance of the output event that was just sent.
225  * @return {Boolean}  Whether the reply method completed without errors.
226  */ 
227 Record.prototype.reply = function(e){
228     return true;
229 };