alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui;


import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IThreeWayDiff;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command.KSubstOption;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.core.util.KnownRepositories;
import org.eclipse.team.internal.ccvs.core.util.ResourceStateChangeListeners;
import org.eclipse.team.internal.core.ExceptionCollector;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.ui.TeamUI;
import org.eclipse.team.ui.mapping.SynchronizationStateTester;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.themes.ITheme;
import org.osgi.framework.Bundle;

import com.ibm.icu.text.SimpleDateFormat;

public class CVSLightweightDecorator extends LabelProvider implements ILightweightLabelDecorator, IResourceStateChangeListener, IPropertyChangeListener {

	// Decorator id as defined in the decorator extension point
	public final static String ID = "org.eclipse.team.cvs.ui.decorator"; //$NON-NLS-1$

	private static ExceptionCollector exceptions = new ExceptionCollector(CVSUIMessages.CVSDecorator_exceptionMessage, CVSUIPlugin.ID, IStatus.ERROR, CVSUIPlugin.getPlugin().getLog()); //;
	
	private static String DECORATOR_FORMAT = "yyyy/MM/dd HH:mm:ss"; //$NON-NLS-1$
	private static SimpleDateFormat decorateFormatter = new SimpleDateFormat(DECORATOR_FORMAT, Locale.getDefault());
	
	private static String[] fonts = new String[]  {
			CVSDecoratorConfiguration.IGNORED_FONT,
			CVSDecoratorConfiguration.OUTGOING_CHANGE_FONT};
	
	private static String[] colors = new String[] {
			 CVSDecoratorConfiguration.OUTGOING_CHANGE_BACKGROUND_COLOR,
			 CVSDecoratorConfiguration.OUTGOING_CHANGE_FOREGROUND_COLOR,
			 CVSDecoratorConfiguration.IGNORED_BACKGROUND_COLOR,
			 CVSDecoratorConfiguration.IGNORED_FOREGROUND_COLOR};
	
	private static final SynchronizationStateTester DEFAULT_TESTER = new SynchronizationStateTester();

	public CVSLightweightDecorator() {
		ResourceStateChangeListeners.getListener().addResourceStateChangeListener(this);
		TeamUI.addPropertyChangeListener(this);
		CVSUIPlugin.addPropertyChangeListener(this);
		
		// This is an optimization to ensure that while decorating our fonts and colors are
		// pre-created and decoration can occur without having to syncExec.
		ensureFontAndColorsCreated(fonts, colors);
		
		PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().addPropertyChangeListener(this);
		CVSProviderPlugin.broadcastDecoratorEnablementChanged(true /* enabled */);
	}
	
	/**
	 * This method will ensure that the fonts and colors used by the decorator
	 * are cached in the registries. This avoids having to syncExec when
	 * decorating since we ensure that the fonts and colors are pre-created.
	 * 
	 * @param fonts fonts ids to cache
	 * @param colors color ids to cache
	 */
	private void ensureFontAndColorsCreated(final String[] fonts, final String[] colors) {
		CVSUIPlugin.getStandardDisplay().syncExec(new Runnable() {
			public void run() {
				ITheme theme  = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
				for (int i = 0; i < colors.length; i++) {
					theme.getColorRegistry().get(colors[i]);
					
				}
				for (int i = 0; i < fonts.length; i++) {
					theme.getFontRegistry().get(fonts[i]);
				}
			}
		});
	}

	public static boolean isDirty(final ICVSResource resource) throws CVSException {
		return getSubscriber().isDirty(resource, null);
	}

	public static boolean isDirty(IResource resource) {
		try {
			return getSubscriber().isDirty(resource, null);
		} catch (CVSException e) {
			handleException(resource, e);
			return true;
		}
	}
	
	/*
	 * Answers null if a provider does not exist or the provider is not a CVS provider. These resources
	 * will be ignored by the decorator.
	 */
	private static CVSTeamProvider getCVSProviderFor(IResource resource) {
		if (resource == null) return null;
		RepositoryProvider p =
			RepositoryProvider.getProvider(
				resource.getProject(),
				CVSProviderPlugin.getTypeId());
		if (p == null) {
			return null;
		}
		return (CVSTeamProvider) p;
	}
	
	/**
	 * This method should only be called by the decorator thread.
	 * 
	 * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration)
	 */
	public void decorate(Object element, IDecoration decoration) {
		
		// Don't decorate the workspace root
		IResource resource = getResource(element);
		if (resource != null && resource.getType() == IResource.ROOT)
			return;
		
		// Get the mapping for the object and ensure it overlaps with CVS projects
		ResourceMapping mapping = Utils.getResourceMapping(element);
		if (mapping == null)
			return;
		if (!isMappedToCVS(mapping))
			return;	
		
		// Get the sync state tester from the context
		IDecorationContext context = decoration.getDecorationContext();
		SynchronizationStateTester tester = DEFAULT_TESTER;
		Object property = context.getProperty(SynchronizationStateTester.PROP_TESTER);
		if (property instanceof SynchronizationStateTester) {
			tester = (SynchronizationStateTester) property;
		}
		
		// Calculate and apply the decoration
		try {
			if (tester.isDecorationEnabled(element)) {
				CVSDecoration cvsDecoration = decorate(element, tester);
				cvsDecoration.apply(decoration);
			}
		} catch(CoreException e) {
			handleException(element, e);
		} catch (IllegalStateException e) {
		    // This is thrown by Core if the workspace is in an illegal state
		    // If we are not active, ignore it. Otherwise, propagate it.
		    // (see bug 78303)
		    if (Platform.getBundle(CVSUIPlugin.ID).getState() == Bundle.ACTIVE) {
		        throw e;
		    }
		}
	}

	private static IResource getResource(Object element) {
		if (element instanceof ResourceMapping) {
			element = ((ResourceMapping) element).getModelObject();
		}
		return Utils.getResource(element);
	}

	/*
	 * Return whether any of the projects of the mapping are mapped to CVS
	 */
    private boolean isMappedToCVS(ResourceMapping mapping) {
        IProject[] projects = mapping.getProjects();
        boolean foundOne = false;
        for (int i = 0; i < projects.length; i++) {
            IProject project = projects[i];
            if (project != null) {
	            RepositoryProvider provider = RepositoryProvider.getProvider(project);
				if (provider instanceof CVSTeamProvider) {
					foundOne = true;
	            } else if (provider != null) {
	            	return false;
	            }
            }
        }
        return foundOne;
    }
    
    public static CVSDecoration decorate(Object element, SynchronizationStateTester tester) throws CoreException {
    	IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
        CVSDecoration result = new CVSDecoration();
        
        // First, decorate the synchronization state
    	int state = IDiff.NO_CHANGE;
		if (isSupervised(element)) {
			// TODO: Not quite right
			result.setHasRemote(true);
			state = tester.getState(element, 
					store.getBoolean(ICVSUIConstants.PREF_CALCULATE_DIRTY) 
						? IDiff.ADD | IDiff.REMOVE | IDiff.CHANGE | IThreeWayDiff.OUTGOING 
						: 0, 
					new NullProgressMonitor());
			result.setStateFlags(state);
        } else {
        	result.setIgnored(true);
        }
		// Tag
		if (!result.isIgnored()) {
			CVSTag tag = getTagToShow(element);
			if (tag != null) {
				String name = tag.getName();
				if (tag.getType() == CVSTag.DATE) {
					Date date = tag.asDate();
					if (date != null) {
						name = decorateFormatter.format(date);
					}
				}
				result.setTag(name);
			}
		}
		
		// If the element adapts to a single resource, add additional decorations
		IResource resource = getResource(element);
		if (resource == null) {
			result.setResourceType(CVSDecoration.MODEL);
		} else {
			decorate(resource, result);
		}
		tester.elementDecorated(element, result.asTeamStateDescription(null));
        return result;
    }
    
	private static boolean isSupervised(Object element) throws CoreException {
		IResource[] resources = getTraversalRoots(element);
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			if (getSubscriber().isSupervised(resource))
				return true;
		}
		return false;
	}
	
	private static IResource[] getTraversalRoots(Object element) throws CoreException {
		Set result = new HashSet();
		ResourceMapping mapping = Utils.getResourceMapping(element);
		if (mapping != null) {
			ResourceTraversal[] traversals = mapping.getTraversals(ResourceMappingContext.LOCAL_CONTEXT, null);
			for (int i = 0; i < traversals.length; i++) {
				ResourceTraversal traversal = traversals[i];
				IResource[] resources = traversal.getResources();
				for (int j = 0; j < resources.length; j++) {
					IResource resource = resources[j];
					result.add(resource);
				}
			}
		}
		return (IResource[]) result.toArray(new IResource[result.size()]);
	}

	private static void decorate(IResource resource, CVSDecoration cvsDecoration) throws CVSException {
		IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
		ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource);
		cvsDecoration.setResourceType(resource.getType());
		
		cvsDecoration.setHasRemote(hasRemote(cvsResource));
		if (cvsResource.isIgnored()) {
			cvsDecoration.setIgnored(true);
		}
		if (!cvsDecoration.isIgnored()) {
			// Dirty: Only decorate dirty state if we're not set to decorate models
			boolean decorateModel = store.getBoolean(ICVSUIConstants.PREF_CALCULATE_DIRTY);
			if (!decorateModel) {
				// Dirty
				try {
					IDiff node = getSubscriber().getDiff(resource);
					if (node != null) {
						if (node instanceof IThreeWayDiff) {
							IThreeWayDiff twd = (IThreeWayDiff) node;
							cvsDecoration.setDirty(twd.getDirection() == IThreeWayDiff.OUTGOING 
								|| twd.getDirection() == IThreeWayDiff.CONFLICTING);
						}
					}
				} catch (CoreException e) {
					handleException(resource, e);
				}
				// Has a remote
				//cvsDecoration.setHasRemote(CVSWorkspaceRoot.hasRemote(resource));
			}
			// Is a new resource
			if (store.getBoolean(ICVSUIConstants.PREF_SHOW_NEWRESOURCE_DECORATION)) {
				if (cvsResource.exists()) {
					if (cvsResource.isFolder()) {
						if (!((ICVSFolder) cvsResource).isCVSFolder()) {
							cvsDecoration.setNewResource(true);
						}
					} else if (!cvsResource.isManaged()) {
						cvsDecoration.setNewResource(true);
					}
				}
			}
			// Extract type specific properties
			if (resource.getType() == IResource.FILE) {
				extractFileProperties((IFile) resource, cvsDecoration);
			} else {
				extractContainerProperties((IContainer) resource, cvsDecoration);
			}
		}
	}

	private static boolean hasRemote(ICVSResource cvsResource) {
		try {
			return (cvsResource.isManaged() || cvsResource.isFolder() && ((ICVSFolder)cvsResource).isCVSFolder());
		} catch (CVSException e) {
			return false;
		}
	}

	public static CVSDecoration decorate(IResource resource, boolean includeDirtyCheck) throws CVSException {
		IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
		ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource);
		CVSDecoration cvsDecoration = new CVSDecoration();
		cvsDecoration.setResourceType(resource.getType());
		
		if (cvsResource.isIgnored()) {
			cvsDecoration.setIgnored(true);
		}
		if (!cvsDecoration.isIgnored()) {
			// Dirty
            if (includeDirtyCheck) {
    			boolean computeDeepDirtyCheck = store.getBoolean(ICVSUIConstants.PREF_CALCULATE_DIRTY);
    			int type = resource.getType();
    			if (type == IResource.FILE || computeDeepDirtyCheck) {
    				cvsDecoration.setDirty(CVSLightweightDecorator.isDirty(resource));
    			}
            }
		}
		decorate(resource, cvsDecoration);
		return cvsDecoration;
	}

	private static void extractContainerProperties(IContainer resource, CVSDecoration cvsDecoration) throws CVSException {
		ICVSFolder folder = CVSWorkspaceRoot.getCVSFolderFor(resource);
		FolderSyncInfo folderInfo = folder.getFolderSyncInfo();
		if (folderInfo != null) {
			cvsDecoration.setLocation(KnownRepositories.getInstance().getRepository(folderInfo.getRoot()));
			
			// Ignore the relative 'repository' path if it is the same locally 
			if (!resource.getFullPath().toString().substring(1).equals(folderInfo.getRepository()))
				cvsDecoration.setRepository(folderInfo.getRepository());
			cvsDecoration.setVirtualFolder(folderInfo.isVirtualDirectory());
		}
	}

	private static void extractFileProperties(IFile resource, CVSDecoration cvsDecoration) throws CVSException {
		ICVSFile file = CVSWorkspaceRoot.getCVSFileFor(resource);
		ResourceSyncInfo fileInfo = file.getSyncInfo();
		KSubstOption option = KSubstOption.fromFile(resource);
		if (fileInfo != null) {
			cvsDecoration.setAdded(fileInfo.isAdded());
			cvsDecoration.setRevision(fileInfo.getRevision());
			cvsDecoration.setReadOnly(file.isReadOnly());
			cvsDecoration.setNeedsMerge(fileInfo.isNeedsMerge(file.getTimeStamp()));
			option = fileInfo.getKeywordMode();
		}
		cvsDecoration.setKeywordSubstitution(option.getShortDisplayText());
		CVSTeamProvider provider = getCVSProviderFor(resource);
		if (provider != null)
			cvsDecoration.setWatchEditEnabled(provider.isWatchEditEnabled());	
	}

	protected static CVSTag getTagToShow(Object element) throws CoreException {
		IResource r = getResource(element);
		if (r != null)
			return getTagToShow(r);
		IResource[] resources = getTraversalRoots(element);
		boolean first = true;
		CVSTag tag = null;
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			if (getSubscriber().isSupervised(resource)) {
				CVSTag nextTag = getTagToShow(resource);
				if (first) {
					tag = nextTag;
					first = false;
				} else if (!equals(tag, nextTag)) {
					return null;
				}
				
			}
		}
		return tag;
	}
	
	private static boolean equals(CVSTag tag, CVSTag nextTag) {
		if (tag == nextTag)
			return true;
		if (tag == null || nextTag == null)
			return false;
		return tag.getName().equals(nextTag.getName());
	}

	/**
	 * Only show the tag if the resources tag is different than the parents. Or else, tag
	 * names will clutter the text decorations.
	 */
	protected static CVSTag getTagToShow(IResource resource) throws CVSException {
		ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource);
		CVSTag tag = null;

		// for unmanaged resources don't show a tag since they will be added in
		// the context of their parents tag. For managed resources only show tags
		// if different than parent.
		boolean managed = false;

		if(cvsResource.isFolder()) {
			FolderSyncInfo folderInfo = ((ICVSFolder)cvsResource).getFolderSyncInfo();
			if(folderInfo != null) {
				tag = folderInfo.getTag();
				managed = true;
			}
		} else {
			ResourceSyncInfo info = ((ICVSFile)cvsResource).getSyncInfo();
			if(info != null) {
				tag = info.getTag();
				managed = true;
			}
		}

		ICVSFolder parent = cvsResource.getParent();
		if(parent != null && managed) {
			FolderSyncInfo parentInfo = parent.getFolderSyncInfo();
			if(parentInfo != null) {
				CVSTag parentTag = parentInfo.getTag();
				parentTag = (parentTag == null ? CVSTag.DEFAULT : parentTag);
				tag = (tag == null ? CVSTag.DEFAULT : tag);
				// must compare tags by name because CVS doesn't do a good job of
				// using  T and N prefixes for folders and files.
				if( parentTag.getName().equals(tag.getName())) {
					tag = null;
				}
			}
		}
		return tag;
	}

	/*
	 * Add resource and its parents to the List
	 */
	 
	private void addWithParents(IResource resource, Set resources) {
		IResource current = resource;

		while (current.getType() != IResource.ROOT) {
			resources.add(current);
			current = current.getParent();
		}
	}
	
	/*
	* Perform a blanket refresh of all CVS decorations
	*/
	public static void refresh() {
		CVSUIPlugin.getPlugin().getWorkbench().getDecoratorManager().update(CVSUIPlugin.DECORATOR_ID);
	}

	/*
	 * Update the decorators for every resource in project
	 */
	 
	public void refresh(IProject project) {
		final List resources = new ArrayList();
		try {
			project.accept(new IResourceVisitor() {
				public boolean visit(IResource resource) {
					resources.add(resource);
					return true;
				}
			});
			postLabelEvent(new LabelProviderChangedEvent(this, resources.toArray()));
		} catch (CoreException e) {
			handleException(project, e);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#resourceSyncInfoChanged(org.eclipse.core.resources.IResource[])
	 */
	public void resourceSyncInfoChanged(IResource[] changedResources) {
		resourceStateChanged(changedResources);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#externalSyncInfoChange(org.eclipse.core.resources.IResource[])
	 */
	public void externalSyncInfoChange(IResource[] changedResources) {
		resourceStateChanged(changedResources);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#resourceModificationStateChanged(org.eclipse.core.resources.IResource[])
	 */
	public void resourceModified(IResource[] changedResources) {
		resourceStateChanged(changedResources);
	}

	/**
	 * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#resourceStateChanged(org.eclipse.core.resources.IResource[])
	 */
	public void resourceStateChanged(IResource[] changedResources) {
		// add depth first so that update thread processes parents first.
		//System.out.println(">> State Change Event");
		Set resourcesToUpdate = new HashSet();

		IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
		boolean showingDeepDirtyIndicators = store.getBoolean(ICVSUIConstants.PREF_CALCULATE_DIRTY);

		for (int i = 0; i < changedResources.length; i++) {
			IResource resource = changedResources[i];

			if(showingDeepDirtyIndicators) {
				addWithParents(resource, resourcesToUpdate);
			} else {
				resourcesToUpdate.add(resource);
			}
		}

		postLabelEvent(new LabelProviderChangedEvent(this, resourcesToUpdate.toArray()));
	}
	
	/**
	 * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#projectConfigured(org.eclipse.core.resources.IProject)
	 */
	public void projectConfigured(IProject project) {
		refresh(project);
	}
	/**
	 * @see org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener#projectDeconfigured(org.eclipse.core.resources.IProject)
	 */
	public void projectDeconfigured(IProject project) {
		refresh(project);
	}

	/**
	 * Post the label event to the UI thread
	 *
	 * @param events  the events to post
	 */
	private void postLabelEvent(final LabelProviderChangedEvent event) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				fireLabelProviderChanged(event);
			}
		});
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
	 */
	public void dispose() {
		super.dispose();
		PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().removePropertyChangeListener(this);
		CVSProviderPlugin.broadcastDecoratorEnablementChanged(false /* disabled */);
		TeamUI.removePropertyChangeListener(this);
		CVSUIPlugin.removePropertyChangeListener(this);
	}
	
	/**
	 * Handle exceptions that occur in the decorator.
	 * Exceptions are only logged for resources that
	 * are accessible (i.e. exist in an open project).
	 */
	private static void handleException(IResource resource, CoreException e) {
		if (resource == null || resource.isAccessible())
			exceptions.handleException(e);
	}
	
	/**
	 * Handle exceptions that occur in the decorator.
	 * Exceptions are only logged for resources that
	 * are accessible (i.e. exist in an open project).
	 */
	private void handleException(Object element, CoreException e) {
		IResource resource = Utils.getResource(element);
		if (resource != null) {
			handleException(resource, e);
		}
		ResourceMapping mapping = Utils.getResourceMapping(element);
		IProject[] projects = mapping.getProjects();
		for (int i = 0; i < projects.length; i++) {
			IProject project = projects[i];
			if (!project.isAccessible()) {
				return;
			}
		}
		exceptions.handleException(e);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
	 */
	public void propertyChange(PropertyChangeEvent event) {
		if (isEventOfInterest(event)) {
			ensureFontAndColorsCreated(fonts, colors);
		    refresh();
		}	
	}

    private boolean isEventOfInterest(PropertyChangeEvent event) {
        String prop = event.getProperty();
        return prop.equals(TeamUI.GLOBAL_IGNORES_CHANGED) 
        	|| prop.equals(TeamUI.GLOBAL_FILE_TYPES_CHANGED) 
        	|| prop.equals(CVSUIPlugin.P_DECORATORS_CHANGED)
			|| prop.equals(CVSDecoratorConfiguration.OUTGOING_CHANGE_BACKGROUND_COLOR)
			|| prop.equals(CVSDecoratorConfiguration.OUTGOING_CHANGE_FOREGROUND_COLOR)
			|| prop.equals(CVSDecoratorConfiguration.OUTGOING_CHANGE_FONT)
			|| prop.equals(CVSDecoratorConfiguration.IGNORED_FOREGROUND_COLOR)
			|| prop.equals(CVSDecoratorConfiguration.IGNORED_BACKGROUND_COLOR)
			|| prop.equals(CVSDecoratorConfiguration.IGNORED_FONT);
    }
	
	private static CVSWorkspaceSubscriber getSubscriber() {
		return CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
	}
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.