001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.api;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.HashMap;
033    import java.util.List;
034    import java.util.Map;
035    import java.util.TreeMap;
036    
037    import com.sleepycat.je.Transaction;
038    import com.sleepycat.je.Database;
039    import com.sleepycat.je.DatabaseEntry;
040    import com.sleepycat.je.OperationStatus;
041    
042    import org.opends.server.admin.std.server.DebugLogPublisherCfg;
043    import org.opends.server.config.ConfigException;
044    import org.opends.server.loggers.LogLevel;
045    import org.opends.server.loggers.debug.TraceSettings;
046    import org.opends.server.types.DebugLogLevel;
047    import org.opends.server.types.InitializationException;
048    import org.opends.server.types.DN;
049    
050    
051    
052    /**
053     * This class defines the set of methods and structures that must be
054     * implemented for a Directory Server debug log publisher.
055     *
056     * @param  <T>  The type of debug log publisher configuration handled
057     *              by this log publisher implementation.
058     */
059    @org.opends.server.types.PublicAPI(
060         stability=org.opends.server.types.StabilityLevel.VOLATILE,
061         mayInstantiate=false,
062         mayExtend=true,
063         mayInvoke=false)
064    public abstract class DebugLogPublisher
065           <T extends DebugLogPublisherCfg>
066    {
067      //The default global settings key.
068      private static final String GLOBAL= "_global";
069    
070      //The map of class names to their trace settings.
071      private Map<String,TraceSettings> classTraceSettings;
072    
073      //The map of class names to their method trace settings.
074      private Map<String,Map<String,TraceSettings>> methodTraceSettings;
075    
076    
077    
078      /**
079       * Construct a default configuration where the global scope will
080       * only log at the ERROR level.
081       */
082      protected DebugLogPublisher()
083      {
084        classTraceSettings = null;
085        methodTraceSettings = null;
086    
087        //Set the global settings so that only errors are logged.
088        addTraceSettings(null, new TraceSettings(DebugLogLevel.ERROR));
089      }
090    
091    
092    
093      /**
094       * Initializes this debug publisher provider based on the
095       * information in the provided debug publisher configuration.
096       *
097       * @param  config  The debug publisher configuration that contains
098       *                 the information to use to initialize this debug
099       *                 publisher.
100       *
101       * @throws  ConfigException  If an unrecoverable problem arises in
102       *                           the process of performing the
103       *                           initialization as a result of the
104       *                           server configuration.
105       *
106       * @throws   InitializationException  If a problem occurs during
107       *                                    initialization that is not
108       *                                    related to the server
109       *                                    configuration.
110       */
111      public abstract void initializeDebugLogPublisher(T config)
112             throws ConfigException, InitializationException;
113    
114    
115    
116      /**
117       * Indicates whether the provided configuration is acceptable for
118       * this debug log publisher.  It should be possible to call this
119       * method on an uninitialized debug log publisher instance in
120       * order to determine whether the debug log publisher would be able
121       * to use the provided configuration.
122       * <BR><BR>
123       * Note that implementations which use a subclass of the provided
124       * configuration class will likely need to cast the configuration
125       * to the appropriate subclass type.
126       *
127       * @param  configuration        The debug log publisher
128       *                              configuration for which to make the
129       *                              determination.
130       * @param  unacceptableReasons  A list that may be used to hold the
131       *                              reasons that the provided
132       *                              configuration is not acceptable.
133       *
134       * @return  {@code true} if the provided configuration is acceptable
135       *          for this debug log publisher, or {@code false} if not.
136       */
137      public boolean isConfigurationAcceptable(
138                          DebugLogPublisherCfg configuration,
139                          List<Message> unacceptableReasons)
140      {
141        // This default implementation does not perform any special
142        // validation.  It should be overridden by debug log publisher
143        // implementations that wish to perform more detailed validation.
144        return true;
145      }
146    
147    
148    
149      /**
150       * Gets the method trace levels for a specified class.
151       *
152       * @param  className  The fully-qualified name of the class for
153       *                    which to get the trace levels.
154       *
155       *@return  An unmodifiable map of trace levels keyed by method name,
156       *         or {@code null} if no method-level tracing is configured
157       *         for the scope.
158       */
159      public final Map<String,TraceSettings> getMethodSettings(
160                                                  String className)
161      {
162        if(methodTraceSettings == null)
163        {
164          return null;
165        }
166        else
167        {
168          return methodTraceSettings.get(className);
169        }
170      }
171    
172    
173    
174      /**
175       * Get the trace settings for a specified class.
176       *
177       * @param  className  The fully-qualified name of the class for
178       *                    which to get the trace levels.
179       *
180       * @return  The current trace settings for the class.
181       */
182      public final TraceSettings getClassSettings(String className)
183      {
184        TraceSettings settings = TraceSettings.DISABLED;
185    
186        // If we're not enabled, trace level is DISABLED.
187        if (classTraceSettings != null) {
188          // Find most specific trace setting which covers this
189          // fully qualified class name
190          // Search up the hierarchy for a match.
191          String searchName= className;
192          Object value= null;
193          value= classTraceSettings.get(searchName);
194          while (value == null && searchName != null) {
195            int clipPoint= searchName.lastIndexOf('$');
196            if (clipPoint == -1) clipPoint= searchName.lastIndexOf('.');
197            if (clipPoint != -1) {
198              searchName= searchName.substring(0, clipPoint);
199              value= classTraceSettings.get(searchName);
200            }
201            else {
202              searchName= null;
203            }
204          }
205    
206          // Use global settings, if nothing more specific was found.
207          if (value == null) value= classTraceSettings.get(GLOBAL);
208    
209          if (value != null) {
210            settings= (TraceSettings)value;
211          }
212        }
213        return settings;
214      }
215    
216    
217    
218      /**
219       * Adds a trace settings to the current set for a specified scope.
220       * If a scope is not specified, the settings will be set for the
221       * global scope. The global scope settings are used when no other
222       * scope matches.
223       *
224       * @param  scope     The scope for which to set the trace settings.
225       *                   This should be a fully-qualified class name, or
226       *                   {@code null} to set the trace settings for the
227       *                   global scope.
228       * @param  settings  The trace settings for the specified scope.
229       */
230      public final void addTraceSettings(String scope,
231                                         TraceSettings settings)
232      {
233        if (scope == null) {
234          setClassSettings(GLOBAL, settings);
235        }
236        else {
237          int methodPt= scope.lastIndexOf('#');
238          if (methodPt != -1) {
239            String methodName= scope.substring(methodPt+1);
240            scope= scope.substring(0, methodPt);
241            setMethodSettings(scope, methodName, settings);
242          }
243          else {
244            setClassSettings(scope, settings);
245          }
246        }
247      }
248    
249    
250    
251      /**
252       * Determine whether a trace setting is already defined for a
253       * particular scope.
254       *
255       * @param  scope  The scope for which to make the determination.
256       *                This should be a fully-qualified class name, or
257       *                {@code null} to make the determination for the
258       *                global scope.
259       *
260       * @return  The trace settings for the specified scope, or
261       *          {@code null} if no trace setting is defined for that
262       *          scope.
263       */
264      public final TraceSettings getTraceSettings(String scope)
265      {
266        if (scope == null) {
267          if(classTraceSettings != null)
268          {
269            return classTraceSettings.get(GLOBAL);
270          }
271          return null;
272        }
273        else {
274          int methodPt= scope.lastIndexOf('#');
275          if (methodPt != -1) {
276            String methodName= scope.substring(methodPt+1);
277            scope= scope.substring(0, methodPt);
278            if(methodTraceSettings != null)
279            {
280              Map<String, TraceSettings> methodLevels =
281                  methodTraceSettings.get(scope);
282              if(methodLevels != null)
283              {
284                return methodLevels.get(methodName);
285              }
286              return null;
287            }
288            return null;
289          }
290          else {
291            if(classTraceSettings != null)
292            {
293              return classTraceSettings.get(scope);
294            }
295            return null;
296          }
297        }
298      }
299    
300    
301    
302      /**
303       * Remove a trace setting by scope.
304       *
305       * @param  scope  The scope for which to remove the trace setting.
306       *                This should be a fully-qualified class name, or
307       *                {@code null} to remove the trace setting for the
308       *                global scope.
309       *
310       * @return  The trace settings for the specified scope, or
311       *          {@code null} if no trace setting is defined for that
312       *          scope.
313       */
314      public final TraceSettings removeTraceSettings(String scope)
315      {
316        TraceSettings removedSettings = null;
317        if (scope == null) {
318          if(classTraceSettings != null)
319          {
320            removedSettings =  classTraceSettings.remove(GLOBAL);
321          }
322        }
323        else {
324          int methodPt= scope.lastIndexOf('#');
325          if (methodPt != -1) {
326            String methodName= scope.substring(methodPt+1);
327            scope= scope.substring(0, methodPt);
328            if(methodTraceSettings != null)
329            {
330              Map<String, TraceSettings> methodLevels =
331                  methodTraceSettings.get(scope);
332              if(methodLevels != null)
333              {
334                removedSettings = methodLevels.remove(methodName);
335                if(methodLevels.isEmpty())
336                {
337                  methodTraceSettings.remove(scope);
338                }
339              }
340            }
341          }
342          else {
343            if(classTraceSettings != null)
344            {
345              removedSettings =  classTraceSettings.remove(scope);
346            }
347          }
348        }
349    
350        return removedSettings;
351      }
352    
353    
354    
355      /**
356       * Set the trace settings for a class.
357       *
358       * @param  className  The class name.
359       * @param  settings   The trace settings for the class.
360       */
361      private synchronized final void setClassSettings(String className,
362                                           TraceSettings settings)
363      {
364        if(classTraceSettings == null) classTraceSettings =
365            new HashMap<String, TraceSettings>();
366    
367        classTraceSettings.put(className, settings);
368      }
369    
370    
371    
372      /**
373       * Set the method settings for a particular method in a class.
374       *
375       * @param  className   The class name.
376       * @param  methodName  The method name.
377       * @param  settings    The trace settings for the method.
378       */
379      private synchronized final void setMethodSettings(String className,
380                                           String methodName,
381                                           TraceSettings settings)
382      {
383        if (methodTraceSettings == null) methodTraceSettings =
384            new HashMap<String, Map<String, TraceSettings>>();
385        Map<String, TraceSettings> methodLevels=
386            methodTraceSettings.get(className);
387        if (methodLevels == null) {
388          methodLevels= new TreeMap<String, TraceSettings>();
389          methodTraceSettings.put(className, methodLevels);
390        }
391    
392        methodLevels.put(methodName, settings);
393      }
394    
395    
396    
397      /**
398       * Log a constructor entry.
399       *
400       * @param  level           The log level for the message.
401       * @param  settings        The current trace settings in effect.
402       * @param  signature       The constuctor signature.
403       * @param  sourceLocation  The location of the method in the source.
404       * @param  args            The parameters provided to the
405       *                         constructor.
406       * @param  stackTrace      The stack trace at the time the
407       *                         constructor is executed or null if its
408       *                         not available.
409       */
410      public abstract void traceConstructor(LogLevel level,
411                                            TraceSettings settings,
412                                            String signature,
413                                            String sourceLocation,
414                                            Object[] args,
415                                          StackTraceElement[] stackTrace);
416    
417    
418    
419      /**
420       * Log a non-static method entry.
421       *
422       * @param  level           The log level for the message.
423       * @param  settings        The current trace settings in effect.
424       * @param  signature       The method signature.
425       * @param  sourceLocation  The location of the method in the source.
426       * @param  obj             The object instance on which the method
427       *                         has been invoked.
428       * @param  args            The parameters provided to the method.
429       * @param  stackTrace      The stack trace at the time the method
430       *                         is executed or null if its not available.
431       */
432      public abstract void traceMethodEntry(LogLevel level,
433                                                   TraceSettings settings,
434                                                   String signature,
435                                                   String sourceLocation,
436                                                   Object obj,
437                                                   Object[] args,
438                                          StackTraceElement[] stackTrace);
439    
440    
441    
442      /**
443       * Log a static method entry.
444       *
445       * @param  level           The log level for the message.
446       * @param  settings        The current trace settings in effect.
447       * @param  signature       The method signature.
448       * @param  sourceLocation  The location of the method in the source.
449       * @param  args            The parameters provided to the method.
450       * @param  stackTrace      The stack trace at the time the method
451       *                         is executed or null if its not available.
452       */
453      public abstract void traceStaticMethodEntry(LogLevel level,
454                                                  TraceSettings settings,
455                                                  String signature,
456                                                  String sourceLocation,
457                                                  Object[] args,
458                                          StackTraceElement[] stackTrace);
459    
460    
461    
462      /**
463       * Log a method return.
464       *
465       * @param  level           The log level for the message.
466       * @param  settings        The current trace settings in effect.
467       * @param  signature       The method signature.
468       * @param  sourceLocation  The location of the method in the source.
469       * @param  ret             The return value for the method.
470       * @param  stackTrace      The stack trace at the time the method
471       *                         is returned or null if its not available.
472       */
473      public abstract void traceReturn(LogLevel level,
474                                       TraceSettings settings,
475                                       String signature,
476                                       String sourceLocation,
477                                       Object ret,
478                                       StackTraceElement[] stackTrace);
479    
480    
481    
482      /**
483       * Log an arbitrary event in a method.
484       *
485       * @param  level           The log level for the message.
486       * @param  settings        The current trace settings in effect.
487       * @param  signature       The method signature.
488       * @param  sourceLocation  The location of the method in the source.
489       * @param  msg             The message to be logged.
490       * @param  stackTrace      The stack trace at the time the message
491       *                         is logged or null if its not available.
492       */
493      public abstract void traceMessage(LogLevel level,
494                                        TraceSettings settings,
495                                        String signature,
496                                        String sourceLocation,
497                                        String msg,
498                                        StackTraceElement[] stackTrace);
499    
500    
501    
502      /**
503       * Log a thrown exception in a method.
504       *
505       * @param  level           The log level for the message.
506       * @param  settings        The current trace settings in effect.
507       * @param  signature       The method signature.
508       * @param  sourceLocation  The location of the method in the source.
509       * @param  ex              The exception that was thrown.
510       * @param  stackTrace      The stack trace at the time the exception
511       *                         is thrown or null if its not available.
512       */
513      public abstract void traceThrown(LogLevel level,
514                                       TraceSettings settings,
515                                       String signature,
516                                       String sourceLocation,
517                                       Throwable ex,
518                                       StackTraceElement[] stackTrace);
519    
520    
521    
522      /**
523       * Log a caught exception in a method.
524       *
525       * @param  level           The log level for the message.
526       * @param  settings        The current trace settings in effect.
527       * @param  signature       The method signature.
528       * @param  sourceLocation  The location of the method in the source.
529       * @param  ex              The exception that was caught.
530       * @param  stackTrace      The stack trace at the time the exception
531       *                         is caught or null if its not available.
532       */
533      public abstract void traceCaught(LogLevel level,
534                                       TraceSettings settings,
535                                       String signature,
536                                       String sourceLocation,
537                                       Throwable ex,
538                                       StackTraceElement[] stackTrace);
539    
540    
541    
542      /**
543       * Log an JE database access in a method.
544       *
545       * @param  level           The log level for the message.
546       * @param  settings        The current trace settings in effect.
547       * @param  signature       The method signature.
548       * @param  sourceLocation  The location of the method in the source.
549       * @param  status          The status of the JE operation.
550       * @param  database        The database handle.
551       * @param  txn             The transaction handle (may be
552       *                         {@code null}).
553       * @param  key             The key to dump.
554       * @param  data            The data to dump.
555       * @param  stackTrace      The stack trace at the time the access
556       *                         occurred or null if its not available.
557       */
558      public abstract void traceJEAccess(LogLevel level,
559                                         TraceSettings settings,
560                                         String signature,
561                                         String sourceLocation,
562                                         OperationStatus status,
563                                         Database database,
564                                         Transaction txn,
565                                         DatabaseEntry key,
566                                         DatabaseEntry data,
567                                         StackTraceElement[] stackTrace);
568    
569    
570    
571      /**
572       * Log raw data in a method.
573       *
574       * @param  level           The log level for the message.
575       * @param  settings        The current trace settings in effect.
576       * @param  signature       The method signature.
577       * @param  sourceLocation  The location of the method in the source.
578       * @param  data            The data to dump.
579       * @param  stackTrace      The stack trace at the time the data
580       *                         is logged or null if its not available.
581       */
582      public abstract void traceData(LogLevel level,
583                                     TraceSettings settings,
584                                     String signature,
585                                     String sourceLocation,
586                                     byte[] data,
587                                     StackTraceElement[] stackTrace);
588    
589    
590    
591      /**
592       * Log a protocol element in a method.
593       *
594       * @param  level           The log level for the message.
595       * @param  settings        The current trace settings in effect.
596       * @param  signature       The method signature.
597       * @param  sourceLocation  The location of the method in the source.
598       * @param  element         The protocol element to dump.
599       * @param  stackTrace      The stack trace at the time the protocol
600       *                         element is logged or null if its not
601       *                         available.
602       */
603      public abstract void traceProtocolElement(LogLevel level,
604                                                TraceSettings settings,
605                                                String signature,
606                                                String sourceLocation,
607                                                ProtocolElement element,
608                                          StackTraceElement[] stackTrace);
609    
610      /**
611       * Close this publisher.
612       */
613      public abstract void close();
614    
615      /**
616       * Gets the DN of the configuration entry for this debug log
617       * publisher.
618       *
619       * @return The configuration entry DN.
620       */
621      public abstract DN getDN();
622    }
623