001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.node.event;
020
021import static org.jppf.node.event.NodeLifeCycleEventType.*;
022
023import java.util.*;
024
025import org.jppf.utils.*;
026import org.slf4j.*;
027
028/**
029 * The default node life cycle error handler, used when the life cycle listener implementation does not implement {@link NodeLifeCycleErrorHandler}.
030 * @author Laurent Cohen
031 */
032public class DefaultLifeCycleErrorHandler implements NodeLifeCycleErrorHandler {
033  /**
034   * Logger for this class.
035   */
036  private static Logger log = LoggerFactory.getLogger(LifeCycleEventHandler.class);
037  /**
038   * Determines whether debug-level logging is enabled.
039   */
040  private static boolean debugEnabled = LoggingUtils.isDebugEnabled(log);
041  /**
042   * If <code>true</code> (the default), then {@link Error}s caught in the listeners methods will be propagated, otherwise they will be just logged.
043   */
044  protected static final boolean propagateErrors = JPPFConfiguration.getProperties().getBoolean("jppf.node.listener.errors.propagate", true);
045  /**
046   * Mapping of event type to listener method name.
047   */
048  public static final Map<NodeLifeCycleEventType, String> methodsNamesMap = generateMethodsNamesMap();
049
050  /**
051   * {@inheritDoc}
052   * <p>
053   * This method logs the uncaught throwable, with a level of detail based on the configured logging level. If debug level is enabled, then the full stack trace will be logged, otherwise only the
054   * throwable class and its message will be logged.
055   * <p>
056   * if the value of the boolean configuration property &quot;jppf.node.listener.errors.propagate&quot; is true, and if the throwable is an {@link Error}, then it will be propagated up the call stack.
057   */
058  @Override
059  public void handleError(final NodeLifeCycleListener listener, final NodeLifeCycleEvent event, final Throwable t) {
060    final String s = StringUtils.build("error executing ", methodsNamesMap.get(event.getType()), " on an instance of ", listener.getClass(), ", event=", event, ", listener=", listener, " : ");
061    if (debugEnabled) log.debug(s, t);
062    else log.error(s + ExceptionUtils.getMessage(t));
063    if (propagateErrors && (t instanceof Error)) throw (Error) t;
064  }
065
066  /**
067   * Generate a mapping of event type to listener method name.
068   * @return a map of {@link NodeLifeCycleEventType} to associated strings.
069   */
070  private static Map<NodeLifeCycleEventType, String> generateMethodsNamesMap() {
071    final Map<NodeLifeCycleEventType, String> map = new HashMap<>();
072    map.put(NODE_STARTING, "nodeStarting()");
073    map.put(NODE_ENDING, "nodeEnding()");
074    map.put(JOB_HEADER_LOADED, "jobHeaderLoaded()");
075    map.put(JOB_STARTING, "jobStarting()");
076    map.put(JOB_ENDING, "jobEnding()");
077    map.put(BEFORE_NEXT_JOB, "beforeNextJob()");
078    return Collections.unmodifiableMap(map);
079  }
080}