package bndtools.model.repo; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; import org.bndtools.api.ILogger; import org.bndtools.api.Logger; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.osgi.resource.Capability; import org.osgi.resource.Requirement; import org.osgi.service.repository.Repository; import aQute.bnd.build.Project; import aQute.bnd.build.Workspace; import aQute.bnd.build.WorkspaceRepository; import aQute.bnd.osgi.Builder; import aQute.bnd.service.IndexProvider; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.ResolutionPhase; import aQute.bnd.version.Version; import bndtools.central.Central; import bndtools.central.WorkspaceR5Repository; public class RepositoryTreeContentProvider implements ITreeContentProvider { private static final String CACHE_REPOSITORY = "cache"; private static final ILogger logger = Logger.getLogger(RepositoryTreeContentProvider.class); private final EnumSet<ResolutionPhase> phases; private String rawFilter = null; private String wildcardFilter = null; private boolean showRepos = true; private Requirement requirementFilter = null; public RepositoryTreeContentProvider() { this.phases = EnumSet.allOf(ResolutionPhase.class); } public RepositoryTreeContentProvider(ResolutionPhase mode) { this.phases = EnumSet.of(mode); } public RepositoryTreeContentProvider(EnumSet<ResolutionPhase> modes) { this.phases = modes; } public String getFilter() { return rawFilter; } public void setFilter(String filter) { this.rawFilter = filter; if (filter == null || filter.length() == 0 || filter.trim().equals("*")) wildcardFilter = null; else wildcardFilter = "*" + filter.trim() + "*"; } public void setRequirementFilter(Requirement requirement) { this.requirementFilter = requirement; } public void setShowRepos(boolean showRepos) { this.showRepos = showRepos; } public boolean isShowRepos() { return showRepos; } @Override @SuppressWarnings("unchecked") public Object[] getElements(Object inputElement) { Collection<Object> result; if (inputElement instanceof Workspace) { result = new ArrayList<Object>(); Workspace workspace = (Workspace) inputElement; addRepositoryPlugins(result, workspace); } else if (inputElement instanceof Collection) { result = new ArrayList<Object>(); addCollection(result, (Collection<Object>) inputElement); } else if (inputElement instanceof Object[]) { result = new ArrayList<Object>(); addCollection(result, Arrays.asList(inputElement)); } else { result = Collections.emptyList(); } return result.toArray(); } @Override public void dispose() {} @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} @Override public Object[] getChildren(Object parentElement) { Object[] result = null; if (parentElement instanceof RepositoryPlugin) { RepositoryPlugin repo = (RepositoryPlugin) parentElement; result = getRepositoryBundles(repo); } else if (parentElement instanceof RepositoryBundle) { RepositoryBundle bundle = (RepositoryBundle) parentElement; result = getRepositoryBundleVersions(bundle); } else if (parentElement instanceof Project) { Project project = (Project) parentElement; result = getProjectBundles(project); } return result; } @Override public Object getParent(Object element) { if (element instanceof RepositoryBundle) { return ((RepositoryBundle) element).getRepo(); } if (element instanceof RepositoryBundleVersion) { return ((RepositoryBundleVersion) element).getParentBundle(); } return null; } @Override public boolean hasChildren(Object element) { return element instanceof RepositoryPlugin || element instanceof RepositoryBundle || element instanceof Project; } private void addRepositoryPlugins(Collection<Object> result, Workspace workspace) { workspace.getErrors().clear(); List<RepositoryPlugin> repoPlugins = workspace.getPlugins(RepositoryPlugin.class); for (String error : workspace.getErrors()) { logger.logError(error, null); } for (RepositoryPlugin repoPlugin : repoPlugins) { if (CACHE_REPOSITORY.equals(repoPlugin.getName())) continue; if (repoPlugin instanceof IndexProvider) { IndexProvider indexProvider = (IndexProvider) repoPlugin; if (!supportsPhase(indexProvider)) continue; } if (showRepos) result.add(repoPlugin); else result.addAll(Arrays.asList(getRepositoryBundles(repoPlugin))); } } private void addCollection(Collection<Object> result, Collection<Object> inputs) { for (Object input : inputs) { if (input instanceof RepositoryPlugin) { RepositoryPlugin repo = (RepositoryPlugin) input; if (repo instanceof IndexProvider) { if (!supportsPhase((IndexProvider) repo)) continue; } if (showRepos) { result.add(repo); } else { Object[] bundles = getRepositoryBundles(repo); if (bundles != null && bundles.length > 0) result.addAll(Arrays.asList(bundles)); } } } } private boolean supportsPhase(IndexProvider provider) { Set<ResolutionPhase> supportedPhases = provider.getSupportedPhases(); for (ResolutionPhase phase : phases) { if (supportedPhases.contains(phase)) return true; } return false; } Object[] getProjectBundles(Project project) { ProjectBundle[] result = null; try { Collection< ? extends Builder> builders = project.getSubBuilders(); result = new ProjectBundle[builders.size()]; int i = 0; for (Builder builder : builders) { ProjectBundle bundle = new ProjectBundle(project, builder.getBsn()); result[i++] = bundle; } } catch (Exception e) { logger.logError(MessageFormat.format("Error querying sub-bundles for project {0}.", project.getName()), e); } return result; } Object[] getRepositoryBundleVersions(RepositoryBundle bundle) { RepositoryBundleVersion[] result = null; SortedSet<Version> versions = null; try { versions = bundle.getRepo().versions(bundle.getBsn()); } catch (Exception e) { logger.logError(MessageFormat.format("Error querying versions for bundle {0} in repository {1}.", bundle.getBsn(), bundle.getRepo().getName()), e); } if (versions != null) { result = new RepositoryBundleVersion[versions.size()]; int i = 0; for (Version version : versions) { result[i++] = new RepositoryBundleVersion(bundle, version); } } return result; } Object[] getRepositoryBundles(RepositoryPlugin repoPlugin) { Object[] result = null; if (requirementFilter != null) { if (repoPlugin instanceof Repository) { result = searchR5Repository(repoPlugin, (Repository) repoPlugin); } else if (repoPlugin instanceof WorkspaceRepository) { try { WorkspaceR5Repository workspaceRepo = Central.getWorkspaceR5Repository(); result = searchR5Repository(repoPlugin, workspaceRepo); } catch (Exception e) { logger.logError("Error querying workspace repository", e); } } return result; } List<String> bsns = null; try { bsns = repoPlugin.list(wildcardFilter); } catch (Exception e) { logger.logError(MessageFormat.format("Error querying repository {0}.", repoPlugin.getName()), e); } if (bsns != null) { Collections.sort(bsns); result = new RepositoryBundle[bsns.size()]; int i = 0; for (String bsn : bsns) { result[i++] = new RepositoryBundle(repoPlugin, bsn); } } return result; } private Object[] searchR5Repository(RepositoryPlugin repoPlugin, Repository osgiRepo) { Object[] result; Set<RepositoryResourceElement> resultSet = new LinkedHashSet<RepositoryResourceElement>(); Map<Requirement,Collection<Capability>> providers = osgiRepo.findProviders(Collections.singleton(requirementFilter)); for (Entry<Requirement,Collection<Capability>> providersEntry : providers.entrySet()) { for (Capability providerCap : providersEntry.getValue()) resultSet.add(new RepositoryResourceElement(repoPlugin, providerCap.getResource())); } result = resultSet.toArray(); return result; } }