/*
 * 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.logging.log4j.core.config;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.util.PerformanceSensitive;

Data structure with similar semantics to CopyOnWriteArraySet, but giving direct access to the underlying array.
Since:2.6
/** * Data structure with similar semantics to CopyOnWriteArraySet, but giving direct access to the underlying array. * * @since 2.6 */
@PerformanceSensitive public class AppenderControlArraySet { private final AtomicReference<AppenderControl[]> appenderArray = new AtomicReference<>(new AppenderControl[0]);
Adds an AppenderControl to this set. If this set already contains the element, the call leaves the set unchanged and returns false.
Params:
  • control – The AppenderControl to add.
Returns:true if this set did not already contain the specified element
/** * Adds an AppenderControl to this set. If this set already contains the element, the call leaves the set unchanged * and returns false. * * @param control The AppenderControl to add. * @return true if this set did not already contain the specified element */
public boolean add(final AppenderControl control) { boolean success; do { final AppenderControl[] original = appenderArray.get(); for (final AppenderControl existing : original) { if (existing.equals(control)) { return false; // the appender is already in the list } } final AppenderControl[] copy = Arrays.copyOf(original, original.length + 1); copy[copy.length - 1] = control; success = appenderArray.compareAndSet(original, copy); } while (!success); // could not swap: array was modified by another thread return true; // successfully added }
Removes the AppenderControl with the specific name and returns it (or null if no such appender existed).
Params:
  • name – The name of the AppenderControl to remove
Returns:the removed AppenderControl or null
/** * Removes the AppenderControl with the specific name and returns it (or {@code null} if no such appender existed). * * @param name The name of the AppenderControl to remove * @return the removed AppenderControl or {@code null} */
public AppenderControl remove(final String name) { boolean success; do { success = true; final AppenderControl[] original = appenderArray.get(); for (int i = 0; i < original.length; i++) { final AppenderControl appenderControl = original[i]; if (Objects.equals(name, appenderControl.getAppenderName())) { final AppenderControl[] copy = removeElementAt(i, original); if (appenderArray.compareAndSet(original, copy)) { return appenderControl; // successfully removed } success = false; // could not swap: array was modified by another thread break; } } } while (!success); return null; // not found } private AppenderControl[] removeElementAt(final int i, final AppenderControl[] array) { final AppenderControl[] result = Arrays.copyOf(array, array.length - 1); System.arraycopy(array, i + 1, result, i, result.length - i); return result; }
Returns all Appenders as a Map.
Returns:a Map with the Appender name as the key and the Appender as the value.
/** * Returns all Appenders as a Map. * * @return a Map with the Appender name as the key and the Appender as the value. */
public Map<String, Appender> asMap() { final Map<String, Appender> result = new HashMap<>(); for (final AppenderControl appenderControl : appenderArray.get()) { result.put(appenderControl.getAppenderName(), appenderControl.getAppender()); } return result; }
Atomically sets the values to an empty array and returns the old array.
Returns:the contents before this collection was cleared.
/** * Atomically sets the values to an empty array and returns the old array. * * @return the contents before this collection was cleared. */
public AppenderControl[] clear() { return appenderArray.getAndSet(new AppenderControl[0]); } public boolean isEmpty() { return appenderArray.get().length == 0; }
Returns the underlying array.
Returns:the array supporting this collection
/** * Returns the underlying array. * * @return the array supporting this collection */
public AppenderControl[] get() { return appenderArray.get(); } @Override public String toString() { return "AppenderControlArraySet [appenderArray=" + appenderArray + "]"; } }