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

hudson.model.LazyTopLevelItem Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *
 * Copyright (c) 2013 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:
 *
 *    Roy Varghese
 *
 *******************************************************************************/
package hudson.model;

import hudson.PermalinkList;
import hudson.XmlFile;
import hudson.search.Search;
import hudson.search.SearchIndex;
import hudson.security.ACL;
import hudson.security.Permission;
import hudson.tasks.LogRotator;
import hudson.util.RunList;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import org.eclipse.hudson.api.model.IJob;
import org.eclipse.hudson.graph.Graph;
import org.kohsuke.stapler.StaplerProxy;
import org.springframework.security.access.AccessDeniedException;


/**
 * A decorator around a top-level job that loads the real job lazily and hangs
 * onto it with a weak reference.
 *
 * @author Roy Varghese
 */
final class LazyTopLevelItem implements TopLevelItem, IJob, StaplerProxy {
    
    // Parameters to the Item
    class Key {
        final XmlFile configFile;
        final ItemGroup parent;
        final String name;
        
        private boolean loadError = false;
        
        Key(XmlFile configFile, ItemGroup parent, String name) {
            this.configFile = configFile;
            this.parent = parent;
            this.name = name;
        }
        
        public boolean equals(Object o) {
            boolean equal = false;
            if ( o.getClass() == Key.class) {
                Key other = (Key) o;
                equal = name.equals(other.name) && 
                        configFile.equals(other.configFile) && 
                        parent.equals(other.parent);
                       
            }
            return equal;
                
        }
        
        @Override
        public int hashCode() {
            return name.hashCode();
        }
        
        public void setLoadErrorFlag() {
            loadError = true;
        }
        public void clearLoadErrorFlag() {
            loadError = false;
        }
    }
    
    private final Key key;
    
    private WeakReference ref;
    
    // The cache reference
    private final TopLevelItemsCache itemsCache;
    
    // Log non-loadable Item only once.
    private boolean loggedError = false;
    
    // Type of the item. This is used to satisfy 'instanceof' checks against
    // LazyTopLevelItem for backward compatibility. Such checks are really intended
    // for the wrapped object, not for the wrapper.
    private Class itemType = null;

    LazyTopLevelItem(XmlFile configFile, ItemGroup parent, String name, TopLevelItem item) {
        this.key = new Key(configFile, parent, name);
        
        itemsCache = Hudson.getInstance().itemsCache();
        
        // Add to cache if value is already created/available.
        if ( item != null ) {
            itemsCache.put(key, item);
        }
    }

    private Class itemType() {
        if ( itemType == null) {
            Item item = item();
            if ( item != null) {
                itemType = item.getClass();
            }
        }
        return itemType;
    }
    
    /**
     * Unwrap and return the decorated item from a LazyTopLevelItem.
     * 
     * @return null if item is not LazyTopLevelItem, or if neither the
     * decorated nor the item itself can be cast into requested type.
     */
    static  T getIfInstanceOf(Item item, Class clazz) {
        
        if ( item.getClass() == LazyTopLevelItem.class) {

            LazyTopLevelItem lazyItem = (LazyTopLevelItem) item;
            TopLevelItem realItem = lazyItem.item();
            if (clazz.isAssignableFrom(realItem.getClass())) {
                return (T) realItem;
            }
                
        }
        
        return clazz.isInstance(item)? clazz.cast(item): null;
        
    }
    
    /**
     * Load the item if not already loaded.
     *
     * @return
     */
    private synchronized TopLevelItem item() {
        TopLevelItem item = (ref != null? ref.get(): null);
        
        if ( item  == null ) {
            item = itemsCache.get(key);
            ref = new WeakReference( item );
            
        }
        return item;
    }

    private IJob job() {
        final Item item = item();
        assert IJob.class.isAssignableFrom(item.getClass());
        return (IJob) item;
    }

    @Override
    public TopLevelItemDescriptor getDescriptor() {
        return item().getDescriptor();
    }

    @Override
    public ItemGroup getParent() {
        return key.parent;
    }

    @Override
    public Collection getAllJobs() {
        return item().getAllJobs();
    }

    @Override
    public String getName() {
        if ( key.loadError ) {
            return key.name +"[In Error]";
        }
        else {
            return key.name;
        }
    }

    @Override
    public String getFullName() {
        return item().getFullName();
    }

    @Override
    public String getDisplayName() {
        return item().getDisplayName();
    }

    @Override
    public String getFullDisplayName() {
        return item().getFullDisplayName();
    }

    @Override
    public String getUrl() {
        return item().getUrl();
    }

    @Override
    public String getShortUrl() {
        return item().getShortUrl();
    }

    @Override
    public String getAbsoluteUrl() {
        return item().getAbsoluteUrl();
    }

    @Override
    public void onLoad(ItemGroup parent, String name) throws IOException {
        // No-op;
    }

    @Override
    public void onCopiedFrom(Item src) {
        item().onCopiedFrom(src);
    }

    @Override
    public void onCreatedFromScratch() {
        item().onCreatedFromScratch();
    }

    @Override
    public void save() throws IOException {
        item().save();
    }

    @Override
    public void delete() throws IOException, InterruptedException {
        item().delete();
    }

    @Override
    public File getRootDir() {
        return item().getRootDir();
    }

    @Override
    public Search getSearch() {
        return item().getSearch();
    }

    @Override
    public String getSearchName() {
        return item().getSearchName();
    }

    @Override
    public String getSearchUrl() {
        return item().getSearchUrl();
    }

    @Override
    public SearchIndex getSearchIndex() {
        return item().getSearchIndex();
    }

    @Override
    public ACL getACL() {
        return item().getACL();
    }

    @Override

    public void checkPermission(Permission permission) throws AccessDeniedException {
        item().checkPermission(permission);
    }

    
    @Override
    public boolean hasPermission(Permission permission) {
        return item().hasPermission(permission);
    }

    @Override
    public Object getTarget() {
        return item();
    }
    @Override
    public boolean isNameEditable() {
        return job().isNameEditable();
    }

    @Override
    public LogRotator getLogRotator() {
        return job().getLogRotator();
    }

    @Override
    public void setLogRotator(LogRotator logRotator) {
        job().setLogRotator(logRotator);
    }

    @Override
    public boolean supportsLogRotator() {
        return job().supportsLogRotator();
    }

    @Override
    public Map getProperties() {
        return job().getProperties();
    }

    @Override
    public List getAllProperties() {
        return job().getAllProperties();
    }

    @Override
    public boolean isInQueue() {
        return job().isInQueue();
    }

    @Override
    public Queue.Item getQueueItem() {
        return job().getQueueItem();
    }

    @Override
    public boolean isBuilding() {
        return job().isBuilding();
    }

    @Override
    public boolean isKeepDependencies() {
        return job().isKeepDependencies();
    }

    @Override
    public int assignBuildNumber() throws IOException {
        return job().assignBuildNumber();
    }

    @Override
    public int getNextBuildNumber() {
        return job().getNextBuildNumber();
    }

    @Override
    public void updateNextBuildNumber(int next) throws IOException {
        job().updateNextBuildNumber(next);
    }

    @Override
    public void logRotate() throws IOException, InterruptedException {
        job().logRotate();
    }

    @Override
    public List getWidgets() {
        return job().getWidgets();
    }

    @Override
    public boolean isBuildable() {
        return job().isBuildable();
    }

    @Override
    public PermalinkList getPermalinks() {
        return job().getPermalinks();
    }

    @Override
    public RunList getBuilds() {
        return job().getBuilds();
    }

    @Override
    public List getBuilds(Fingerprint.RangeSet rs) {
        return job().getBuilds(rs);
    }

    @Override
    public SortedMap getBuildsAsMap() {
        return job().getBuildsAsMap();
    }

    @Override
    public Run getBuildByNumber(int n) {
        return job().getBuildByNumber(n);
    }

    @Override
    public Run getNearestBuild(int n) {
        return job().getNearestBuild(n);
    }

    @Override
    public Run getNearestOldBuild(int n) {
        return job().getNearestOldBuild(n);
    }

    @Override
    public Run getLastBuild() {
        return job().getLastBuild();
    }

    @Override
    public Run getFirstBuild() {
        return job().getFirstBuild();
    }

    @Override
    public Run getLastSuccessfulBuild() {
        return job().getLastSuccessfulBuild();
    }

    @Override
    public Run getLastUnsuccessfulBuild() {
        return job().getLastUnsuccessfulBuild();
    }

    @Override
    public Run getLastUnstableBuild() {
        return job().getLastUnstableBuild();
    }

    @Override
    public Run getLastStableBuild() {
        return job().getLastStableBuild();
    }

    @Override
    public Run getLastFailedBuild() {
        return job().getLastFailedBuild();
    }

    @Override
    public Run getLastCompletedBuild() {
        return job().getLastCompletedBuild();
    }

    @Override
    public List getLastBuildsOverThreshold(int numberOfBuilds, Result threshold) {
        return job().getLastBuildsOverThreshold(numberOfBuilds, threshold);
    }

    @Override
    public String getBuildStatusUrl() {
        return job().getBuildStatusUrl();
    }

    @Override
    public BallColor getIconColor() {
        return job().getIconColor();
    }

    @Override
    public HealthReport getBuildHealth() {
        return job().getBuildHealth();
    }

    @Override
    public List getBuildHealthReports() {
        return job().getBuildHealthReports();
    }

    @Override
    public Graph getBuildTimeGraph() {
        return job().getBuildTimeGraph();
    }

    @Override
    public BuildTimelineWidget getTimeline() {
        return job().getTimeline();
    }

    @Override
    public String getCreatedBy() {
        return job().getCreatedBy();
    }

    @Override
    public long getCreationTime() {
        return job().getCreationTime();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy