Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java')
-rw-r--r--bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java515
1 files changed, 515 insertions, 0 deletions
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java
new file mode 100644
index 00000000..1a5addaf
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/resourcelocator/TargetPlatformContributionCollector.java
@@ -0,0 +1,515 @@
+/*******************************************************************************
+ * Copyright (c) 2014 TwelveTone LLC 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:
+ * Steven Spungin <steven@spungin.tv> - initial API and implementation, Bug 424730
+ *******************************************************************************/
+
+package org.eclipse.e4.tools.emf.ui.internal.common.resourcelocator;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.e4.tools.emf.ui.common.FilterEx;
+import org.eclipse.e4.tools.emf.ui.common.IClassContributionProvider;
+import org.eclipse.e4.tools.emf.ui.common.IClassContributionProvider.ContributionData;
+import org.eclipse.e4.tools.emf.ui.common.IModelElementProvider;
+import org.eclipse.e4.tools.emf.ui.common.ResourceSearchScope;
+import org.eclipse.e4.tools.emf.ui.internal.common.ClassContributionCollector;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.FilteredContributionDialog;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.tabs.empty.E;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.pde.core.plugin.IPluginBase;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.TargetPlatformHelper;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+/**
+ * A contribution collector encompassing the current target platform.<br />
+ * Uses FilterEx for bundle, package, and location filtering.<br />
+ * This implementation finds resources based on file names, not by parsing file
+ * contents.
+ *
+ * @author Steven Spungin
+ *
+ */
+public abstract class TargetPlatformContributionCollector extends ClassContributionCollector {
+
+ ArrayList<Entry> cacheEntry = new ArrayList<Entry>();
+ HashSet<String> cacheBundleId = new HashSet<String>();
+ HashSet<String> cachePackage = new HashSet<String>();
+ HashSet<String> cacheLocation = new HashSet<String>();
+ private Pattern patternFile;
+ protected String cacheName;
+
+ static class Entry {
+ String name;
+ String path;
+ String installLocation;
+ String relativePath;
+ String bundleSymName;
+ String pakage;
+ }
+
+ @SuppressWarnings("unused")
+ private TargetPlatformContributionCollector() {
+ }
+
+ protected TargetPlatformContributionCollector(String cacheName) {
+
+ this.cacheName = cacheName;
+ patternFile = getFilePattern();
+
+ addContributor(new IClassContributionProvider() {
+
+ @Override
+ public void findContribution(Filter filter, ContributionResultHandler handler) {
+
+ Pattern patternName = Pattern.compile(filter.namePattern, Pattern.CASE_INSENSITIVE);
+
+ reloadCache(false);
+
+ int maxResults = filter.maxResults;
+ if (maxResults == 0) {
+ maxResults = 100;
+ }
+
+ int found = 0;
+ boolean more = false;
+ for (Entry e : cacheEntry) {
+ // Check for FilterEx filters
+ if (filter instanceof FilterEx) {
+ FilterEx filterEx = (FilterEx) filter;
+ if (E.notEmpty(filterEx.getBundles())) {
+ if (!filterEx.getBundles().contains(e.bundleSymName)) {
+ continue;
+ }
+ }
+ if (E.notEmpty(filterEx.getPackages())) {
+ if (!filterEx.getPackages().contains(e.pakage)) {
+ continue;
+ }
+ }
+ if (E.notEmpty(filterEx.getLocations())) {
+ boolean locationFound = false;
+ for (String location : filterEx.getLocations()) {
+ if (e.installLocation.startsWith(location)) {
+ locationFound = true;
+ break;
+ }
+ }
+ if (!locationFound) {
+ continue;
+ }
+ }
+ if (filterEx.isIncludeNonBundles() == false) {
+ if (e.bundleSymName == null) {
+ continue;
+ }
+ }
+ if (filterEx.getSearchScope().contains(ResourceSearchScope.WORKSPACE)) {
+ if (filter.project != null) {
+ IWorkspace workspace = filter.project.getWorkspace();
+ boolean fnd = false;
+ for (IProject project : workspace.getRoot().getProjects()) {
+ // String path =
+ // project.getLocationURI().getPath();
+ String path = project.getName();
+ if (e.installLocation.contains(path)) {
+ fnd = true;
+ break;
+ }
+ }
+ if (!fnd) {
+ continue;
+ }
+ }
+ }
+ }
+ Matcher m = patternName.matcher(e.name);
+ if (m.find()) {
+ found++;
+ if (found > maxResults) {
+ more = true;
+ handler.moreResults(-1, filter);
+ break;
+ } else {
+ handler.result(makeData(e));
+ }
+ }
+
+ }
+ if (!more) {
+ handler.moreResults(0, filter);
+ }
+ }
+ });
+
+ addModelElementContributor(new IModelElementProvider() {
+
+ @Override
+ public void getModelElements(Filter filter, ModelResultHandler handler) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void clearCache() {
+ cacheEntry.clear();
+ cacheBundleId.clear();
+ cachePackage.clear();
+ cacheLocation.clear();
+ outputDirectories.clear();
+ }
+ });
+ }
+
+ protected ContributionData makeData(Entry e) {
+ // If class is in a java project, strip the source directory
+ // String path = e.path;// .replace("/", ".") + e.name;
+ // path = stripSourceDirectory(path, e.installLocation);
+ IPath ip = Path.fromOSString(e.path);
+ ip = ip.addTrailingSeparator().makeRelative();
+ ip = ip.append(e.name);
+ String className = ip.toOSString().replace('/', '.');
+ ContributionData data = new ContributionData(e.bundleSymName, className, "Java", e.installLocation); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ data.installLocation = e.installLocation;
+ data.resourceRelativePath = e.relativePath;
+ return data;
+ }
+
+ /**
+ *
+ * @return A copy of the bundle IDs in the cache.
+ */
+ public Collection<String> getBundleIds() {
+ reloadCache(false);
+ return new ArrayList<String>(cacheBundleId);
+ }
+
+ /**
+ *
+ * @return A copy of the bundle IDs in the cache.
+ */
+ public Collection<String> getPackages() {
+ reloadCache(false);
+ return new ArrayList<String>(cachePackage);
+ }
+
+ /**
+ *
+ * @return A copy of the bundle IDs in the cache.
+ */
+ public Collection<String> getLocations() {
+ reloadCache(false);
+ return new ArrayList<String>(cacheLocation);
+ }
+
+ /**
+ * Ensures the cache is loaded. By default it is loaded on first access, and
+ * kept static until forced to reloaded.
+ *
+ * @param force
+ * true to force reload the cache
+ */
+ private void reloadCache(boolean force) {
+ if (cacheEntry.isEmpty() || force) {
+ cacheEntry.clear();
+ cacheBundleId.clear();
+ cachePackage.clear();
+ cacheLocation.clear();
+ outputDirectories.clear();
+
+ ProgressMonitorDialog dlg = new ProgressMonitorDialog(Display.getDefault().getActiveShell()) {
+
+ @Override
+ protected Control createContents(Composite parent) {
+ // TODO odd this is not a bean.
+ Composite ret = (Composite) super.createContents(parent);
+ Label label = new Label(ret, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
+ label.setText(Messages.TargetPlatformContributionCollector_pleaseWait);
+
+ return ret;
+ }
+ };
+ try {
+ dlg.run(true, true, new IRunnableWithProgress() {
+
+ @Override
+ public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+
+ // load workspace projects
+ for (final IProject pj : PDECore.getWorkspace().getRoot().getProjects()) {
+ if (monitor.isCanceled()) {
+ break;
+ }
+ String rootDirectory = pj.getLocation().toOSString();
+ TargetPlatformContributionCollector.this.visit(monitor, FilteredContributionDialog.getBundle(rootDirectory), rootDirectory, new File(rootDirectory));
+ }
+
+ // load target platform bundles
+ IPluginModelBase[] models = TargetPlatformHelper.getPDEState().getTargetModels();
+ monitor.beginTask(Messages.TargetPlatformContributionCollector_updatingTargetPlatformCache + cacheName + ")", models.length); //$NON-NLS-2$
+ for (IPluginModelBase pluginModelBase : models) {
+ monitor.subTask(pluginModelBase.getPluginBase().getId());
+ monitor.worked(1);
+ if (monitor.isCanceled()) {
+ break;
+ }
+
+ IPluginBase pluginBase = pluginModelBase.getPluginBase();
+ if (pluginBase == null) {
+ // bundle = getBundle(new File())
+ continue;
+ }
+ URL url;
+ try {
+ String installLocation = pluginModelBase.getInstallLocation();
+ if (installLocation.endsWith(".jar")) { //$NON-NLS-1$
+ url = new URL("file://" + installLocation); //$NON-NLS-1$
+ ZipInputStream zis = new ZipInputStream(url.openStream());
+ while (true) {
+ ZipEntry entry = zis.getNextEntry();
+ if (entry == null) {
+ break;
+ } else {
+ String name2 = entry.getName();
+ if (shouldIgnore(name2)) {
+ continue;
+ }
+ Matcher m = patternFile.matcher(name2);
+ if (m.matches()) {
+ Entry e = new Entry();
+ e.installLocation = installLocation;
+ cacheLocation.add(installLocation);
+ e.name = m.group(2);
+ e.path = m.group(1);
+ if (e.path != null) {
+ e.pakage = e.path.replace("/", "."); //$NON-NLS-1$ //$NON-NLS-2$
+ if (e.pakage.startsWith(".")) { //$NON-NLS-1$
+ e.pakage = e.pakage.substring(1);
+ }
+ if (e.pakage.endsWith(".")) { //$NON-NLS-1$
+ e.pakage = e.pakage.substring(0, e.pakage.length() - 1);
+ }
+ } else {
+ e.pakage = ""; //$NON-NLS-1$
+ }
+ cachePackage.add(e.pakage);
+
+ e.bundleSymName = pluginBase.getId();
+ if (e.path == null) {
+ e.path = ""; //$NON-NLS-1$
+ }
+ cacheEntry.add(e);
+ cacheBundleId.add(pluginBase.getId());
+
+ //
+ // System.out.println(group
+ // + " -> "
+ // +
+ // m.group(2));
+ }
+ }
+ }
+ } else {
+ // not a jar file
+ String bundle = getBundle(new File(installLocation));
+ if (bundle != null) {
+ visit(monitor, bundle, installLocation, new File(installLocation));
+ }
+ }
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ monitor.done();
+ }
+ });
+ } catch (InvocationTargetException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ } catch (InterruptedException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ // @Refactor
+ static public String getBundle(File file) {
+ if (file.isDirectory() == false) {
+ return null;
+ }
+
+ File f = new File(file, "META-INF/MANIFEST.MF"); //$NON-NLS-1$
+
+ if (f.exists() && f.isFile()) {
+ BufferedReader r = null;
+ try {
+ InputStream s = new FileInputStream(f);
+ r = new BufferedReader(new InputStreamReader(s));
+ String line;
+ while ((line = r.readLine()) != null) {
+ if (line.startsWith("Bundle-SymbolicName:")) { //$NON-NLS-1$
+ int start = line.indexOf(':');
+ int end = line.indexOf(';');
+ if (end == -1) {
+ end = line.length();
+ }
+ return line.substring(start + 1, end).trim();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (r != null) {
+ try {
+ r.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ protected void visit(IProgressMonitor monitor, String bundleName, String installLocation, File file) {
+ for (File fChild : file.listFiles()) {
+ if (fChild.isDirectory()) {
+ visit(monitor, bundleName, installLocation, fChild);
+ } else {
+ String name2 = fChild.getAbsolutePath().substring(installLocation.length() + 1);
+ name2 = stripOutputDirectory(name2, installLocation);
+ if (shouldIgnore(name2)) {
+ continue;
+ }
+ Matcher m = patternFile.matcher(name2);
+ if (m.matches()) {
+ Entry e = new Entry();
+ e.installLocation = installLocation;
+ cacheLocation.add(installLocation);
+ e.name = m.group(2);
+ if (e.name.contains("$")) { //$NON-NLS-1$
+ continue;
+ }
+ e.path = m.group(1);
+ if (e.path != null) {
+ e.pakage = e.path.replace("/", "."); //$NON-NLS-1$ //$NON-NLS-2$
+ if (e.pakage.startsWith(".")) { //$NON-NLS-1$
+ e.pakage = e.pakage.substring(1);
+ }
+ if (e.pakage.endsWith(".")) { //$NON-NLS-1$
+ e.pakage = e.pakage.substring(0, e.pakage.length() - 1);
+ }
+ } else {
+ e.pakage = ""; //$NON-NLS-1$
+ }
+ if (e.path == null) {
+ e.path = ""; //$NON-NLS-1$
+ }
+ e.relativePath = Path.fromOSString(file.getAbsolutePath().replace(e.installLocation, "")).makeRelative().toOSString(); //$NON-NLS-1$
+
+ e.bundleSymName = bundleName;
+ // TODO we need project to strip source paths.
+ // e.pakage = e.pakage.replaceAll("^bin.", "");
+ cachePackage.add(e.pakage);
+ cacheEntry.add(e);
+ if (bundleName != null) {
+ cacheBundleId.add(bundleName);
+ }
+ }
+ }
+ }
+
+ }
+
+ static private String stripOutputDirectory(String path, String installLocation) {
+ if (installLocation.matches(".*\\.jar")) { //$NON-NLS-1$
+ return path;
+ }
+ for (String sourceDirectory : getOutputDirectories(installLocation)) {
+ if (path.startsWith(sourceDirectory)) {
+ path = path.substring(sourceDirectory.length());
+ break;
+ }
+ }
+ return path;
+ }
+
+ /**
+ * A cache of the output directories for install locations (if install
+ * location has a classpath file with appropriate output entries)
+ */
+ static private HashMap<String, List<String>> outputDirectories = new HashMap<String, List<String>>();
+
+ // Returns the Eclipse output directories for an install location. The
+ // directories are relative to the install location.
+ // <classpathentry kind="output" path="bin"/>
+ static private List<String> getOutputDirectories(String installLocation) {
+ List<String> ret = outputDirectories.get(installLocation);
+ if (ret == null) {
+ ret = new ArrayList<String>();
+ outputDirectories.put(installLocation, ret);
+ try {
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(installLocation + File.separator + ".classpath")); //$NON-NLS-1$
+ XPath xp = XPathFactory.newInstance().newXPath();
+ NodeList list = (NodeList) xp.evaluate("//classpathentry[@kind='output']/@path", doc, XPathConstants.NODESET); //$NON-NLS-1$
+ for (int i = 0; i < list.getLength(); i++) {
+ String value = list.item(i).getNodeValue();
+ ret.add(value);
+ }
+ } catch (Exception e) {
+ }
+ }
+ return ret;
+ }
+
+ protected boolean shouldIgnore(String name) {
+ return false;
+ }
+
+ protected abstract Pattern getFilePattern();
+
+}

Back to the top