package org.bndtools.builder.decorator.ui; import java.io.File; import org.bndtools.api.BndtoolsConstants; import org.bndtools.api.ILogger; import org.bndtools.api.Logger; import org.bndtools.builder.BndtoolsBuilder; import org.bndtools.utils.swt.SWTConcurrencyUtil; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.plugin.AbstractUIPlugin; import aQute.bnd.build.Project; import aQute.bnd.header.Attrs; import aQute.bnd.version.Version; /** * A decorator for {@link IPackageFragment}s that adds an icon if the package is exported by the bundle manifest. * * @author duckAsteroid */ public class PackageDecorator extends LabelProvider implements ILightweightLabelDecorator { private static final ILogger logger = Logger.getLogger(PackageDecorator.class); private static final String packageDecoratorId = "bndtools.packageDecorator"; private static final QualifiedName packageDecoratorKey = new QualifiedName(BndtoolsBuilder.PLUGIN_ID, packageDecoratorId); private static final String excluded = " <excluded>"; private final ImageDescriptor exportedIcon = AbstractUIPlugin.imageDescriptorFromPlugin(BndtoolsBuilder.PLUGIN_ID, "icons/plus-decorator.png"); private final ImageDescriptor excludedIcon = AbstractUIPlugin.imageDescriptorFromPlugin(BndtoolsBuilder.PLUGIN_ID, "icons/excluded_ovr.gif"); @Override public void decorate(Object element, IDecoration decoration) { try { IPackageFragment pkg = (IPackageFragment) element; if (pkg.getKind() != IPackageFragmentRoot.K_SOURCE) { return; } if (!pkg.getJavaProject().getProject().hasNature(BndtoolsConstants.NATURE_ID)) { return; } IResource pkgResource = pkg.getCorrespondingResource(); if (pkgResource == null) { return; } String text = pkgResource.getPersistentProperty(packageDecoratorKey); if (text == null) { return; } if (excluded.equals(text)) { decoration.addOverlay(excludedIcon); } else { decoration.addOverlay(exportedIcon); } decoration.addSuffix(text); } catch (CoreException e) { logger.logError("Package Decorator error", e); } } public static void updateDecoration(IProject project, Project model) throws Exception { if (!project.isOpen()) { return; } IJavaProject javaProject = JavaCore.create(project); if (javaProject == null) { return; // project is not a java project } boolean changed = false; for (IClasspathEntry cpe : javaProject.getRawClasspath()) { if (cpe.getEntryKind() != IClasspathEntry.CPE_SOURCE) { continue; } for (IPackageFragmentRoot pkgRoot : javaProject.findPackageFragmentRoots(cpe)) { assert pkgRoot.getKind() == IPackageFragmentRoot.K_SOURCE; IResource pkgRootResource = pkgRoot.getCorrespondingResource(); if (pkgRootResource == null) { continue; } File pkgRootFile = pkgRootResource.getLocation().toFile(); boolean pkgInSourcePath = model.getSourcePath().contains(pkgRootFile); for (IJavaElement child : pkgRoot.getChildren()) { IPackageFragment pkg = (IPackageFragment) child; assert pkg.getKind() == IPackageFragmentRoot.K_SOURCE; IResource pkgResource = pkg.getCorrespondingResource(); if (pkgResource == null) { continue; } String text = pkgResource.getPersistentProperty(packageDecoratorKey); if (pkgInSourcePath) { String pkgName = pkg.getElementName(); // Decorate if exported package Attrs pkgAttrs = model.getExports().getByFQN(pkgName); if (pkgAttrs != null) { StringBuilder sb = new StringBuilder(" ").append(Version.parseVersion(pkgAttrs.getVersion())); pkgAttrs = model.getImports().getByFQN(pkgName); if (pkgAttrs != null) { String versionRange = pkgAttrs.getVersion(); if (versionRange != null) { sb.append('\u2194').append(versionRange); } } String version = sb.toString(); if (!version.equals(text)) { pkgResource.setPersistentProperty(packageDecoratorKey, version); changed = true; } continue; } // Decorate if non-empty, non-contained package if (pkg.containsJavaResources() && !model.getContained().containsFQN(pkgName)) { if (!excluded.equals(text)) { pkgResource.setPersistentProperty(packageDecoratorKey, excluded); changed = true; } continue; } } // Clear decoration if (text != null) { pkgResource.setPersistentProperty(packageDecoratorKey, null); changed = true; } } } } // If decoration change, update display if (changed) { Display display = PlatformUI.getWorkbench().getDisplay(); SWTConcurrencyUtil.execForDisplay(display, true, new Runnable() { @Override public void run() { PlatformUI.getWorkbench().getDecoratorManager().update(packageDecoratorId); } }); } } }