code: public static String getString(String key, @CheckForNull String def, Level logLevel) {
          String value = System.getProperty(key); // keep passing on any exceptions
          if (value != null) {
              if (LOGGER.isLoggable(logLevel)) {
                  LOGGER.log(logLevel, "Property (system): {0} => {1}", new Object[] {key, value});
              }
              return value;
          } 
          
          value = handler.getString(key);
          if (value != null) {
              if (LOGGER.isLoggable(logLevel)) {
                  LOGGER.log(logLevel, "Property (context): {0} => {1}", new Object[]{key, value});
              }
              return value;
          }
          
          value = def;
          if (LOGGER.isLoggable(logLevel)) {
              LOGGER.log(logLevel, "Property (default): {0} => {1}", new Object[] {key, value});
          }
          return value;
      }
docs: Gets the system property indicated by the specified key, or a default value.
  This behaves just like {@link System#getProperty(java.lang.String, java.lang.String)}, except
  that it also consults the {@link ServletContext}'s "init" parameters.
  
  @param      key   the name of the system property.
  @param      def   a default value.
  @param      logLevel the level of the log if the provided key is not found.
  @return     the string value of the system property,
  or {@code null} if the property is missing and the default value is {@code null}.
  
  @exception  NullPointerException if {@code key} is {@code null}.
  @exception  IllegalArgumentException if {@code key} is empty.