blob: ed825f5ec095233f7e2dcfb48d7d1670e9a46e68 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.persistence.indirection;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Map;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
/**
* Provides factory methods to create JDK specific implementation
* of particular type of {@link IndirectCollection}.
*
* @author Lukas Jungmann
* @see IndirectCollection
* @see IndirectList
* @see IndirectMap
* @see IndirectSet
* @since EclipseLink 2.6.0
*/
public final class IndirectCollectionsFactory {
//loaded using reflection to avoid runtime (and compile time) dependency on JDK 8
private static final String JDK8_SUPPORT_PROVIDER = "org.eclipse.persistence.internal.indirection.jdk8.IndirectCollectionsProvider";
private static final IndirectCollectionsProvider provider = getProvider();
/**
* Class implementing {@link IndirectList}.
*/
public static final Class IndirectList_Class = provider.getListClass();
/**
* Class implementing {@link IndirectSet}.
*/
public static final Class IndirectSet_Class = provider.getSetClass();
/**
* Class implementing {@link IndirectMap}.
*/
public static final Class IndirectMap_Class = provider.getMapClass();
/**
* Construct an empty {@link IndirectList} with the default initial capacity (10)
* and default capacity increment (0).
*
* @param <E> the class of the objects in the list
* @return an empty {@link IndirectList} with the default initial capacity
* and default capacity increment
*/
public static <E> IndirectList<E> createIndirectList() {
return provider.createIndirectList(10, 0);
}
/**
* Construct an empty {@link IndirectList} with the specified initial capacity
* and default capacity increment (0).
*
* @param <E> the class of the objects in the list
* @param initialCapacity the initial capacity of the vector
*
* @return an empty {@link IndirectList} with the specified initial capacity
* and default capacity increment
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public static <E> IndirectList<E> createIndirectList(int initialCapacity) {
return provider.createIndirectList(initialCapacity, 0);
}
/**
* Construct an {@link IndirectList} containing the elements of the specified
* collection, in the order they are returned by the collection's iterator.
*
* @param <E> the class of the objects in the list
* @param collection a collection containing the elements to construct
* the {@link IndirectList} with.
* @return an {@link IndirectList} containing the elements of the specified
* collection
*/
public static <E> IndirectList<E> createIndirectList(Collection<? extends E> collection) {
return provider.createIndirectList(collection);
}
/**
* Construct an empty {@link IndirectSet} with the default initial capacity (10)
* and the default load factor (0.75).
*
* @return an empty {@link IndirectSet} with the default initial capacity
* and the default load factor
*/
public static <E> IndirectSet<E> createIndirectSet() {
return provider.createIndirectSet(10, 0.75f);
}
/**
* Construct an empty {@link IndirectSet} with the specified initial capacity
* and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the set
*
* @return an empty {@link IndirectSet} with the specified initial capacity
* and the default load factor
* @throws IllegalArgumentException if the specified initial capacity is negative
*/
public static <E> IndirectSet<E> createIndirectSet(int initialCapacity) {
return provider.createIndirectSet(initialCapacity, 0.75f);
}
/**
* Constructs an {@link IndirectSet} containing the elements of the specified
* collection.
*
* @param collection a collection containing the elements to construct
* the {@link IndirectSet} with
*
* @return an {@link IndirectSet} containing the elements of the specified collection
* @throws NullPointerException if the specified collection is null
*/
public static <E> IndirectSet<E> createIndirectSet(Collection<? extends E> collection) {
return provider.createIndirectSet(collection);
}
/**
* Construct a new, empty {@link IndirectMap} with the default initial
* capacity (11) and the default load factor (0.75).
*
* @return a new, empty {@link IndirectMap} with the default initial
* capacity and the default load factor
*/
public static <K, V> IndirectMap<K, V> createIndirectMap() {
return provider.createIndirectMap(11, 0.75f);
}
/**
* Construct a new, empty {@link IndirectMap} with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the {@link IndirectMap}
*
* @return a new, empty {@link IndirectMap} with the specified initial
* capacity and the default load factor
* @throws IllegalArgumentException if the initial capacity is less than
* or equal to zero
*/
public static <K, V> IndirectMap<K, V> createIndirectMap(int initialCapacity) {
return provider.createIndirectMap(initialCapacity, 0.75f);
}
/**
* Construct a new {@link IndirectMap} with the same mappings as the given Map.
* The {@link IndirectMap} is created with a capacity of twice the number of entries
* in the given Map or 11 (whichever is greater), and a default load factor, which is 0.75.
*
* @param map the map whose mappings are to be placed into created {@link IndirectMap}
*
* @return a new {@link IndirectMap} with the same mappings as the given Map
* @throws NullPointerException if the specified map is null
*/
public static <K, V> IndirectMap<K, V> createIndirectMap(Map<? extends K, ? extends V> map) {
return provider.createIndirectMap(map);
}
/**
* As of EclipseLink 2.6.0 this returns Java SE 7- compatible provider by default
* on Java SE 7 and Java SE 8+ compatible provider if Java SE 8+ is detected.
*
* @return default provider responsible for creating Java SE specific implementations
* of {@link IndirectCollection}s
*/
private static IndirectCollectionsProvider getProvider() {
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
final Class support = (Class) AccessController.doPrivileged(new PrivilegedClassForName(JDK8_SUPPORT_PROVIDER, true, IndirectCollectionsFactory.class.getClassLoader()));
return AccessController.doPrivileged(new PrivilegedAction<IndirectCollectionsProvider>() {
@Override
public IndirectCollectionsProvider run() {
try {
return (IndirectCollectionsProvider) support.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
});
} else {
Class support = PrivilegedAccessHelper.getClassForName(JDK8_SUPPORT_PROVIDER, true, IndirectCollectionsFactory.class.getClassLoader());
return (IndirectCollectionsProvider) PrivilegedAccessHelper.newInstanceFromClass(support);
}
} catch (Throwable t) {
AbstractSessionLog.getLog().logThrowable(SessionLog.FINEST, SessionLog.MISC, t);
}
return new DefaultProvider();
}
/**
* Define API providers of {@link IndirectCollection} implementations must conform to.
*/
public static interface IndirectCollectionsProvider {
/**
* Class implementing {@link IndirectList}.
*
* @return class implementing {@link IndirectList}
*/
Class getListClass();
/**
* Construct an empty {@link IndirectList} with the specified initial capacity
* and capacity increment.
*
* @param <E> the class of the objects in the list
* @param initialCapacity the initial capacity of the list
* @param capacityIncrement the amount by which the capacity is increased
* when the list overflows
*
* @return an empty {@link IndirectList} with the specified initial capacity
* and capacity increment
* @throws IllegalArgumentException if the specified initial capacity is negative
*/
<E> IndirectList<E> createIndirectList(int initialCapacity, int capacityIncrement);
/**
* Constructs an {@link IndirectList} containing the elements of the specified
* collection, in the order they are returned by the collection's iterator.
*
* @param <E> the class of the objects in the list
* @param collection a collection containing the elements to construct
* the {@link IndirectList} with
*
* @return an {@link IndirectList} containing the elements of the specified collection
* @throws NullPointerException if the specified collection is null
*/
<E> IndirectList<E> createIndirectList(Collection<? extends E> collection);
/**
* Class implementing {@link IndirectSet}.
*
* @return class implementing {@link IndirectSet}
*/
Class getSetClass();
/**
* Construct an empty {@link IndirectSet} with the specified initial capacity
* and the specified load factor.
*
* @param initialCapacity the initial capacity of the set
* @param loadFactor the load factor of the set
*
* @return an empty {@link IndirectSet} with the specified initial capacity
* and the specified load factor
* @throws IllegalArgumentException if the specified initial capacity is negative
*/
<E> IndirectSet<E> createIndirectSet(int initialCapacity, float loadFactor);
/**
* Constructs an {@link IndirectSet} containing the elements of the specified
* collection.
*
* @param collection a collection containing the elements to construct
* the {@link IndirectSet} with
*
* @return an {@link IndirectSet} containing the elements of the specified collection
* @throws NullPointerException if the specified collection is null
*/
<E> IndirectSet<E> createIndirectSet(Collection<? extends E> collection);
/**
* Class implementing {@link IndirectMap}.
*
* @return class implementing {@link IndirectMap}
*/
Class getMapClass();
/**
* Construct a new, empty {@link IndirectMap} with the specified initial
* capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the {@link IndirectMap}
* @param loadFactor a number between 0.0 and 1.0
*
* @return a new, empty {@link IndirectMap} with the specified initial
* capacity and the specified load factor
* @throws IllegalArgumentException if the initial capacity is less than
* or equal to zero, or if the load factor is less than or equal to zero
*/
<K, V> IndirectMap<K, V> createIndirectMap(int initialCapacity, float loadFactor);
/**
* Construct a new {@link IndirectMap} with the same mappings as the given Map.
* The {@link IndirectMap} is created with a capacity of twice the number of entries
* in the given Map or 11 (whichever is greater), and a default load factor, which is 0.75.
*
* @param map the map whose mappings are to be placed into created {@link IndirectMap}
*
* @return a new {@link IndirectMap} with the same mappings as the given Map
* @throws NullPointerException if the specified map is null
*/
<K, V> IndirectMap<K, V> createIndirectMap(Map<? extends K, ? extends V> map);
}
/**
* Provider for creating Java SE 7 (and older) compatible
* {@link IndirectCollection} implementations.
*/
private static final class DefaultProvider implements IndirectCollectionsProvider {
@Override
public Class getListClass() {
return IndirectList.class;
}
@Override
public <E> IndirectList<E> createIndirectList(int initialCapacity, int capacityIncrement) {
return new IndirectList<>(initialCapacity, capacityIncrement);
}
@Override
public <E> IndirectList<E> createIndirectList(Collection<? extends E> collection) {
return new IndirectList<>(collection);
}
@Override
public Class getSetClass() {
return IndirectSet.class;
}
@Override
public <E> IndirectSet<E> createIndirectSet(int initialCapacity, float loadFactor) {
return new IndirectSet<>(initialCapacity, loadFactor);
}
@Override
public <E> IndirectSet<E> createIndirectSet(Collection<? extends E> collection) {
return new IndirectSet<>(collection);
}
@Override
public Class getMapClass() {
return IndirectMap.class;
}
@Override
public <K, V> IndirectMap<K, V> createIndirectMap(int initialCapacity, float loadFactor) {
return new IndirectMap<>(initialCapacity, loadFactor);
}
@Override
public <K, V> IndirectMap<K, V> createIndirectMap(Map<? extends K, ? extends V> map) {
return new IndirectMap<>(map);
}
}
}