001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2010-2011 ApexIdentity Inc.
015 * Portions Copyright 2011-2014 ForgeRock AS.
016 */
017
018package org.forgerock.openig.heap;
019
020import static java.util.Collections.*;
021
022import java.util.List;
023
024import org.forgerock.http.util.Loader;
025
026/**
027 * Loads {@link Heaplet} classes based on the class of object they create. Three methods of
028 * locating the heaplet class are attempted, in the following order:
029 * <ol>
030 * <li>The {@link Loader} class attempts to locate a {@code HeapletFactory}
031 * interface implementation suitable for the class being created.</li>
032 * <li>A nested {@code Heaplet} class is searched for. Example: creating
033 * {@code com.example.Foo} would search for a heaplet class named
034 * {@code com.example.Foo$Heaplet}.</li>
035 * <li>A standalone class with the name {@code Heaplet} appended. Example: creating
036 * {@code com.example.Foo} would search for a heaplet class named
037 * {@code com.example.FooHeaplet}. </li>
038 * </ol>
039 */
040public final class Heaplets {
041
042    /** List of classpath-discovered {@link HeapletFactory} services. */
043    private static final List<HeapletFactory> SERVICES = unmodifiableList(Loader.loadList(HeapletFactory.class));
044
045    /** Static methods only. */
046    private Heaplets() {
047    }
048
049    /**
050     * Returns the heaplet that creates an instance of the specified class, or {@code null}
051     * if no such heaplet could be found.
052     *
053     * @param c the class that the heaplet is responsible for creating.
054     * @return the heaplet that creates the specified class, or {@code null} if not found.
055     */
056    public static Heaplet getHeaplet(Class<?> c) {
057
058        Heaplet heaplet;
059
060        // try service loader
061        for (HeapletFactory factory : SERVICES) {
062            heaplet = factory.newInstance(c);
063            if (heaplet != null) {
064                return heaplet;
065            }
066        }
067
068        // try nested class
069        heaplet = Loader.newInstance(c.getName() + "$Heaplet", Heaplet.class);
070
071        if (heaplet == null) {
072            // try standalone class
073            heaplet = Loader.newInstance(c.getName() + "Heaplet", Heaplet.class);
074        }
075        return heaplet;
076    }
077}