001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.util.concurrent;
018
019 import java.util.concurrent.atomic.AtomicLong;
020 import java.util.regex.Matcher;
021 import java.util.regex.Pattern;
022
023 import org.apache.camel.util.ObjectHelper;
024
025 /**
026 * Various helper method for thread naming.
027 */
028 public final class ThreadHelper {
029 public static final String DEFAULT_PATTERN = "Camel Thread ##counter# - #name#";
030 private static final Pattern INVALID_PATTERN = Pattern.compile(".*#\\w+#.*");
031
032 private static AtomicLong threadCounter = new AtomicLong();
033
034 private ThreadHelper() {
035 }
036
037 private static long nextThreadCounter() {
038 return threadCounter.getAndIncrement();
039 }
040
041 /**
042 * Creates a new thread name with the given pattern
043 * <p/>
044 * See {@link org.apache.camel.spi.ExecutorServiceManager#setThreadNamePattern(String)} for supported patterns.
045 *
046 * @param pattern the pattern
047 * @param name the name
048 * @return the thread name, which is unique
049 */
050 public static String resolveThreadName(String pattern, String name) {
051 if (pattern == null) {
052 pattern = DEFAULT_PATTERN;
053 }
054
055 // we support #longName# and #name# as name placeholders
056 String longName = name;
057 String shortName = name.contains("?") ? ObjectHelper.before(name, "?") : name;
058 // must quote the names to have it work as literal replacement
059 shortName = Matcher.quoteReplacement(shortName);
060 longName = Matcher.quoteReplacement(longName);
061
062 // replace tokens
063 String answer = pattern.replaceFirst("#counter#", "" + nextThreadCounter());
064 answer = answer.replaceFirst("#longName#", longName);
065 answer = answer.replaceFirst("#name#", shortName);
066
067 // are there any #word# combos left, if so they should be considered invalid tokens
068 if (INVALID_PATTERN.matcher(answer).matches()) {
069 throw new IllegalArgumentException("Pattern is invalid: " + pattern);
070 }
071
072 return answer;
073 }
074
075 }