All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hudson.DescriptorExtensionList Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2004-2009, Oracle Corporation
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *
 *
 *
 *
 *******************************************************************************/ 

package hudson;

import hudson.model.Descriptor;
import hudson.model.Describable;
import hudson.model.Hudson;
import hudson.model.ViewDescriptor;
import hudson.model.Descriptor.FormException;
import hudson.util.AdaptedIterator;
import hudson.util.Memoizer;
import hudson.util.Iterators.FlattenIterator;
import hudson.slaves.NodeDescriptor;
import hudson.tasks.Publisher;
import hudson.tasks.Publisher.DescriptorExtensionListImpl;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Logger;
import java.util.concurrent.CopyOnWriteArrayList;
import java.lang.reflect.Type;
import java.lang.reflect.ParameterizedType;

import org.jvnet.tiger_types.Types;
import org.kohsuke.stapler.Stapler;
import net.sf.json.JSONObject;

/**
 * {@link ExtensionList} for holding a set of {@link Descriptor}s, which is a
 * group of descriptors for the same extension point.
 *
 * Use {@link Hudson#getDescriptorList(Class)} to obtain instances.
 *
 * @param  Represents the descriptor type. This is {@code Descriptor}
 * normally but often there are subtypes of descriptors, like
 * {@link ViewDescriptor}, {@link NodeDescriptor}, etc, and this parameter
 * points to those for better type safety of users.
 *
 * The actual value of 'D' is not necessary for the operation of this code, so
 * it's purely for convenience of the users of this class.
 *
 * @since 1.286
 */
public class DescriptorExtensionList, D extends Descriptor> extends ExtensionList {

    /**
     * Creates a new instance.
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static , D extends Descriptor> DescriptorExtensionList createDescriptorList(Hudson hudson, Class describableType) {
        if (describableType == (Class) Publisher.class) {
            return (DescriptorExtensionList) new DescriptorExtensionListImpl(hudson);
        }
        return new DescriptorExtensionList(hudson, describableType);
    }
    /**
     * Type of the {@link Describable} that this extension list retains.
     */
    private final Class describableType;

    protected DescriptorExtensionList(Hudson hudson, Class describableType) {
        super(hudson, (Class) Descriptor.class, (CopyOnWriteArrayList) getLegacyDescriptors(describableType));
        this.describableType = describableType;
    }

    /**
     * Finds the descriptor that has the matching fully-qualified class name.
     *
     * @param fqcn Fully qualified name of the descriptor, not the describable.
     */
    public D find(String fqcn) {
        return Descriptor.find(this, fqcn);
    }

    /**
     * Finds the descriptor that describes the given type. That is, if this
     * method returns d, {@code d.clazz==type}
     */
    public D find(Class type) {
        for (D d : this) {
            if (d.clazz == type) {
                return d;
            }
        }
        return null;
    }

    /**
     * Creates a new instance of a {@link Describable} from the structured form
     * submission data posted by a radio button group.
     */
    public T newInstanceFromRadioList(JSONObject config) throws FormException {
        if (config.isNullObject()) {
            return null;    // none was selected
        }
        int idx = config.getInt("value");
        return get(idx).newInstance(Stapler.getCurrentRequest(), config);
    }

    public T newInstanceFromRadioList(JSONObject parent, String name) throws FormException {
        return newInstanceFromRadioList(parent.getJSONObject(name));
    }

    /**
     * Finds a descriptor by their {@link Descriptor#getId()}.
     *
     * If none is found, null is returned.
     */
    public Descriptor findByName(String id) {
        for (Descriptor d : this) {
            if (d.getId().equals(id)) {
                return d;
            }
        }
        return null;
    }

    /**
     * {@link #load()} in the descriptor is not a real load activity, so locking
     * against "this" is enough.
     */
    @Override
    protected Object getLoadLock() {
        return this;
    }

    /**
     * Loading the descriptors in this case means filtering the descriptor from
     * the master {@link ExtensionList}.
     */
    @Override
    protected List> load() {
        List> r = new ArrayList>();
        for (ExtensionComponent c : hudson.getExtensionList(Descriptor.class).getComponents()) {
            Descriptor d = c.getInstance();
            Type subTyping = Types.getBaseClass(d.getClass(), Descriptor.class);
            if (!(subTyping instanceof ParameterizedType)) {
                LOGGER.severe(d.getClass() + " doesn't extend Descriptor with a type parameter");
                continue;   // skip this one
            }
            if (Types.erasure(Types.getTypeArgument(subTyping, 0)) == (Class) describableType) {
                r.add((ExtensionComponent) c);
            }
        }
        return r;
    }
    /**
     * Stores manually registered Descriptor instances. Keyed by the
     * {@link Describable} type.
     */
    private static final Memoizer>> legacyDescriptors = new Memoizer>>() {
        public CopyOnWriteArrayList compute(Class key) {
            return new CopyOnWriteArrayList();
        }
    };

    private static > CopyOnWriteArrayList>> getLegacyDescriptors(Class type) {
        return (CopyOnWriteArrayList) legacyDescriptors.get(type);
    }

    /**
     * List up all the legacy instances currently in use.
     */
    public static Iterable listLegacyInstances() {
        return new Iterable() {
            public Iterator iterator() {
                return new AdaptedIterator, Descriptor>(
                        new FlattenIterator, CopyOnWriteArrayList>>(legacyDescriptors.values()) {
                            protected Iterator> expand(CopyOnWriteArrayList> v) {
                                return v.iterator();
                            }
                        }) {
                    protected Descriptor adapt(ExtensionComponent item) {
                        return item.getInstance();
                    }
                };
            }
        };
    }

    /**
     * Exposed just for the test harness. Clear legacy instances.
     */
    public static void clearLegacyInstances() {
        legacyDescriptors.clear();
    }
    private static final Logger LOGGER = Logger.getLogger(DescriptorExtensionList.class.getName());
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy