001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  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,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.mina.util;
020
021import org.slf4j.Logger;
022import org.slf4j.LoggerFactory;
023
024/**
025 * A {@link Runnable} wrapper that preserves the name of the thread after the runnable is
026 * complete (for {@link Runnable}s that change the name of the Thread they use.)
027 *
028 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
029 */
030public class NamePreservingRunnable implements Runnable {
031    private final static Logger LOGGER = LoggerFactory.getLogger(NamePreservingRunnable.class);
032
033    /** The runnable name */
034    private final String newName;
035
036    /** The runnable task */
037    private final Runnable runnable;
038
039    /**
040     * Creates a new instance of NamePreservingRunnable.
041     *
042     * @param runnable The underlying runnable
043     * @param newName The runnable's name
044     */
045    public NamePreservingRunnable(Runnable runnable, String newName) {
046        this.runnable = runnable;
047        this.newName = newName;
048    }
049
050    /**
051     * Run the runnable after having renamed the current thread's name 
052     * to the new name. When the runnable has completed, set back the 
053     * current thread name back to its origin. 
054     */
055    public void run() {
056        Thread currentThread = Thread.currentThread();
057        String oldName = currentThread.getName();
058
059        if (newName != null) {
060            setName(currentThread, newName);
061        }
062
063        try {
064            runnable.run();
065        } finally {
066            setName(currentThread, oldName);
067        }
068    }
069
070    /**
071     * Wraps {@link Thread#setName(String)} to catch a possible {@link Exception}s such as
072     * {@link SecurityException} in sandbox environments, such as applets
073     */
074    private void setName(Thread thread, String name) {
075        try {
076            thread.setName(name);
077        } catch (SecurityException se) {
078            if (LOGGER.isWarnEnabled()) {
079                LOGGER.warn("Failed to set the thread name.", se);
080            }
081        }
082    }
083}