| /******************************************************************************* |
| * 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); |
| } |
| } |
| } |