/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.sling.commons.threads.impl; import java.util.Locale; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import org.apache.sling.commons.threads.ThreadPoolConfig; /** * This class is responsible to create new Thread instances. * It's a very basic implementation. * */ public final class ExtendedThreadFactory implements ThreadFactory { /** Template for thread names, for use with String#format() */ private static final String THREAD_NAME_TEMPLATE = "sling-%s-%d"; /** The real factory. */ private final ThreadFactory factory; /** The name of the thread pool */ private final String name; /** The priority of newly created Threads */ private final int priority; /** The daemon mode */ private final boolean isDaemon; /** Thread counter for use in thread name */ private final AtomicInteger threadCounter; /** * Create a new wrapper for a thread factory handling the * * @param name The name of the thread pool. * @param priority A non null value. * @param isDaemon Whether new {@link Thread}s should run as daemons. */ public ExtendedThreadFactory(final ThreadFactory factory, final String name, final ThreadPoolConfig.ThreadPriority priority, final boolean isDaemon) { this.factory = factory; this.name = normalizeName(name); this.priority = convertPriority(priority); this.isDaemon = isDaemon; this.threadCounter = new AtomicInteger(1); } private String normalizeName(final String name) { final String n = name.toLowerCase(Locale.ENGLISH).replaceAll("\\s+", "-"); return stripPrefixes(n, "apache-sling-", "sling-"); } private int convertPriority(final ThreadPoolConfig.ThreadPriority priority) { if (priority == null) { throw new IllegalStateException("Prioriy must not be null."); } switch (priority) { case MIN : return Thread.MIN_PRIORITY; case MAX : return Thread.MAX_PRIORITY; case NORM : default: // this can never happen return Thread.NORM_PRIORITY; } } /** * Invoke the thread factory and set the daemon flag and priority. * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable) */ public Thread newThread( final Runnable command ) { final Thread thread = this.factory.newThread(command); thread.setName(nextThreadName()); thread.setPriority( this.priority ); thread.setDaemon( this.isDaemon ); return thread; } private String nextThreadName() { return String.format(THREAD_NAME_TEMPLATE, this.name, this.threadCounter.getAndIncrement()); } private static String stripPrefixes(final String name, final String... prefixes) { for (final String prefix : prefixes) { if (name.startsWith(prefix)) { return name.substring(prefix.length()); } } return name; } }