1 /*******************************************************************************
2  *  Copyright (c) 2005, 2017 IBM Corporation and others.
3  *
4  *  This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License 2.0
6  *  which accompanies this distribution, and is available at
7  *  https://www.eclipse.org/legal/epl-2.0/
8  *
9  *  SPDX-License-Identifier: EPL-2.0
10  *
11  *  Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Remy Chi Jian Suen <remy.suen@gmail.com> - bug 200756
14  *     Joern Dinkla <devnull@dinkla.com> - bug 200757
15  *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 487988
16  *     Martin Karpisek <martin.karpisek@gmail.com> - Bug 351356
17  *******************************************************************************/
18 
19 package org.eclipse.pde.internal.ui.editor.plugin;
20 
21 import java.util.*;
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.jdt.core.*;
26 import org.eclipse.jdt.ui.JavaElementLabelProvider;
27 import org.eclipse.jdt.ui.JavaUI;
28 import org.eclipse.jdt.ui.actions.FindReferencesAction;
29 import org.eclipse.jdt.ui.actions.ShowInPackageViewAction;
30 import org.eclipse.jface.action.*;
31 import org.eclipse.jface.viewers.*;
32 import org.eclipse.jface.window.Window;
33 import org.eclipse.pde.core.IBaseModel;
34 import org.eclipse.pde.core.IModelChangedEvent;
35 import org.eclipse.pde.core.plugin.IPluginModelBase;
36 import org.eclipse.pde.internal.core.ICoreConstants;
37 import org.eclipse.pde.internal.core.bundle.BundlePluginBase;
38 import org.eclipse.pde.internal.core.ibundle.*;
39 import org.eclipse.pde.internal.core.text.bundle.*;
40 import org.eclipse.pde.internal.core.util.PDEJavaHelper;
41 import org.eclipse.pde.internal.ui.*;
42 import org.eclipse.pde.internal.ui.editor.*;
43 import org.eclipse.pde.internal.ui.editor.context.InputContextManager;
44 import org.eclipse.pde.internal.ui.parts.ConditionalListSelectionDialog;
45 import org.eclipse.pde.internal.ui.parts.TablePart;
46 import org.eclipse.pde.internal.ui.search.dependencies.CalculateUsesAction;
47 import org.eclipse.pde.internal.ui.util.SWTUtil;
48 import org.eclipse.pde.internal.ui.util.TextUtil;
49 import org.eclipse.search.ui.NewSearchUI;
50 import org.eclipse.swt.SWT;
51 import org.eclipse.swt.custom.BusyIndicator;
52 import org.eclipse.swt.layout.GridData;
53 import org.eclipse.swt.widgets.*;
54 import org.eclipse.ui.*;
55 import org.eclipse.ui.actions.ActionFactory;
56 import org.eclipse.ui.forms.widgets.FormToolkit;
57 import org.eclipse.ui.forms.widgets.Section;
58 import org.osgi.framework.Constants;
59 
60 public class ExportPackageSection extends TableSection {
61 
62 	private static final int ADD_INDEX = 0;
63 	private static final int REMOVE_INDEX = 1;
64 	private static final int PROPERTIES_INDEX = 2;
65 	private static final int CALCULATE_USE_INDEX = 3;
66 
67 	class ExportPackageContentProvider implements IStructuredContentProvider {
68 		@Override
getElements(Object parent)69 		public Object[] getElements(Object parent) {
70 			if (fHeader == null) {
71 				Bundle bundle = (Bundle) getBundle();
72 				fHeader = (ExportPackageHeader) bundle.getManifestHeader(getExportedPackageHeader());
73 			}
74 			return fHeader == null ? new Object[0] : fHeader.getPackages();
75 		}
76 	}
77 
78 	private TableViewer fPackageViewer;
79 
80 	private Action fAddAction;
81 	private Action fGoToAction;
82 	private Action fRemoveAction;
83 	private Action fPropertiesAction;
84 	private ExportPackageHeader fHeader;
85 
ExportPackageSection(PDEFormPage page, Composite parent)86 	public ExportPackageSection(PDEFormPage page, Composite parent) {
87 		super(page, parent, Section.DESCRIPTION, new String[] {PDEUIMessages.ExportPackageSection_add, PDEUIMessages.ExportPackageSection_remove, PDEUIMessages.ExportPackageSection_properties, PDEUIMessages.ExportPackageSection_uses});
88 	}
89 
isFragment()90 	private boolean isFragment() {
91 		IPluginModelBase model = (IPluginModelBase) getPage().getPDEEditor().getAggregateModel();
92 		return model != null && model.isFragmentModel();
93 	}
94 
95 	@Override
createClient(Section section, FormToolkit toolkit)96 	protected void createClient(Section section, FormToolkit toolkit) {
97 		section.setText(PDEUIMessages.ExportPackageSection_title);
98 		if (isFragment())
99 			section.setDescription(PDEUIMessages.ExportPackageSection_descFragment);
100 		else
101 			section.setDescription(PDEUIMessages.ExportPackageSection_desc);
102 
103 		Composite container = createClientContainer(section, 2, toolkit);
104 		createViewerPartControl(container, SWT.MULTI, 2, toolkit);
105 		TablePart tablePart = getTablePart();
106 		fPackageViewer = tablePart.getTableViewer();
107 		fPackageViewer.setContentProvider(new ExportPackageContentProvider());
108 		fPackageViewer.setLabelProvider(PDEPlugin.getDefault().getLabelProvider());
109 		fPackageViewer.setComparator(new ViewerComparator() {
110 			@Override
111 			public int compare(Viewer viewer, Object e1, Object e2) {
112 				String s1 = e1.toString();
113 				String s2 = e2.toString();
114 				if (s1.contains(" ")) //$NON-NLS-1$
115 					s1 = s1.substring(0, s1.indexOf(' '));
116 				if (s2.contains(" ")) //$NON-NLS-1$
117 					s2 = s2.substring(0, s2.indexOf(' '));
118 				return super.compare(viewer, s1, s2);
119 			}
120 		});
121 		toolkit.paintBordersFor(container);
122 		section.setClient(container);
123 		GridData gd = new GridData(GridData.FILL_BOTH);
124 		if (((ManifestEditor) getPage().getEditor()).isEquinox()) {
125 			gd.verticalSpan = 2;
126 			gd.minimumWidth = 300;
127 		}
128 		section.setLayout(FormLayoutFactory.createClearGridLayout(false, 1));
129 		section.setLayoutData(gd);
130 		makeActions();
131 
132 		IBundleModel model = getBundleModel();
133 		fPackageViewer.setInput(model);
134 		model.addModelChangedListener(this);
135 		updateButtons();
136 	}
137 
138 	@Override
doGlobalAction(String actionId)139 	public boolean doGlobalAction(String actionId) {
140 
141 		if (!isEditable()) {
142 			return false;
143 		}
144 
145 		if (actionId.equals(ActionFactory.DELETE.getId())) {
146 			handleRemove();
147 			return true;
148 		}
149 		if (actionId.equals(ActionFactory.CUT.getId())) {
150 			// delete here and let the editor transfer
151 			// the selection to the clipboard
152 			handleRemove();
153 			return false;
154 		}
155 		if (actionId.equals(ActionFactory.PASTE.getId())) {
156 			doPaste();
157 			return true;
158 		}
159 		return super.doGlobalAction(actionId);
160 	}
161 
162 	@Override
dispose()163 	public void dispose() {
164 		IBundleModel model = getBundleModel();
165 		if (model != null)
166 			model.removeModelChangedListener(this);
167 		super.dispose();
168 	}
169 
170 	@Override
canPaste(Object targetObject, Object[] sourceObjects)171 	protected boolean canPaste(Object targetObject, Object[] sourceObjects) {
172 		HashMap<?, ?> currentPackageFragments = null;
173 		// Only export package objects that represent existing package
174 		// fragments within the Java project that this plugin.xml is stored
175 		// can be pasted
176 		for (Object sourceObject : sourceObjects) {
177 			// Only export package objects are allowed
178 			if ((sourceObject instanceof ExportPackageObject) == false) {
179 				return false;
180 			}
181 			// Get the package fragments that are allowed and store them to
182 			// assist in searching
183 			if (currentPackageFragments == null) {
184 				currentPackageFragments = createCurrentExportPackageMap();
185 			}
186 			// Only export packages that are in the list of allowed package
187 			// fragments are allowed
188 			ExportPackageObject exportPackageObject = (ExportPackageObject) sourceObject;
189 			if (currentPackageFragments.containsKey(exportPackageObject.getName()) == false) {
190 				return false;
191 			}
192 		}
193 		return true;
194 	}
195 
canAddExportedPackages()196 	private boolean canAddExportedPackages() {
197 		// Ensure model is editable
198 		if (isEditable() == false) {
199 			return false;
200 		}
201 		// Get the model
202 		IPluginModelBase model = getModel();
203 		// Ensure model is defined
204 		if (model == null) {
205 			return false;
206 		}
207 		// Get the underlying resource
208 		IResource resource = model.getUnderlyingResource();
209 		// Ensure resource is defined
210 		if (resource == null) {
211 			return false;
212 		}
213 		// Get the project
214 		IProject project = resource.getProject();
215 		// Ensure the project is defined
216 		if (project == null) {
217 			return false;
218 		}
219 		// Ensure the project is a Java project
220 		try {
221 			if (project.hasNature(JavaCore.NATURE_ID) == false) {
222 				return false;
223 			}
224 		} catch (CoreException e) {
225 			return false;
226 		}
227 		return true;
228 	}
229 
createCurrentExportPackageMap()230 	private HashMap<?, ?> createCurrentExportPackageMap() {
231 		// Dummy hash map created in order to return a defined but empty map
232 		HashMap<?, ?> packageFragments = new HashMap<>(0);
233 		// Get the model
234 		IPluginModelBase model = getModel();
235 		// Ensure model is defined
236 		if (model == null) {
237 			return packageFragments;
238 		}
239 		// Get the underlying resource
240 		IResource resource = model.getUnderlyingResource();
241 		// Ensure resource is defined
242 		if (resource == null) {
243 			return packageFragments;
244 		}
245 		// Get the project
246 		IProject project = resource.getProject();
247 		// Ensure the project is defined
248 		if (project == null) {
249 			return packageFragments;
250 		}
251 		// Ensure the project is a Java project
252 		try {
253 			if (project.hasNature(JavaCore.NATURE_ID) == false) {
254 				return packageFragments;
255 			}
256 		} catch (CoreException e) {
257 			return packageFragments;
258 		}
259 		// Get the Java project
260 		IJavaProject javaProject = JavaCore.create(project);
261 		// Ensure the Java project is defined
262 		if (javaProject == null) {
263 			return packageFragments;
264 		}
265 		// Get the current packages associated with the export package header
266 		Vector<?> currentExportPackages = null;
267 		if (fHeader == null) {
268 			currentExportPackages = new Vector<>();
269 		} else {
270 			currentExportPackages = fHeader.getPackageNames();
271 		}
272 		// Get a hashtable of all the package fragments that are allowed to
273 		// be added to the current export package header
274 		// Generally, all package fragments contained in the same Java project
275 		// as the plugin manifest file
276 		// No duplicates are allowed and all current packages are excluded
277 		return PDEJavaHelper.getPackageFragmentsHash(javaProject, currentExportPackages, allowJavaPackages());
278 	}
279 
getModel()280 	private IPluginModelBase getModel() {
281 		return (IPluginModelBase) getPage().getModel();
282 	}
283 
allowJavaPackages()284 	private boolean allowJavaPackages() {
285 		return "true".equals(getBundle().getHeader(ICoreConstants.ECLIPSE_JREBUNDLE)); //$NON-NLS-1$
286 	}
287 
288 	@Override
doPaste(Object targetObject, Object[] sourceObjects)289 	protected void doPaste(Object targetObject, Object[] sourceObjects) {
290 		// Get the model
291 		IBundleModel model = getBundleModel();
292 		// Ensure the model is defined
293 		if (model == null) {
294 			return;
295 		}
296 		// Get the bundle
297 		IBundle bundle = model.getBundle();
298 		// Paste all source objects
299 		for (Object sourceObject : sourceObjects) {
300 			if (sourceObject instanceof ExportPackageObject) {
301 				ExportPackageObject exportPackageObject = (ExportPackageObject) sourceObject;
302 				// Export package object
303 				// Adjust all the source object transient field values to
304 				// acceptable values
305 				exportPackageObject.reconnect(model, fHeader, getVersionAttribute());
306 				// Add the object to the header
307 				if (fHeader == null) {
308 					// Export package header not defined yet
309 					// Define one
310 					// Value will get inserted into a new export package object
311 					// created by a factory
312 					// Value needs to be empty string so no export package
313 					// object is created as the initial value
314 					bundle.setHeader(getExportedPackageHeader(), ""); //$NON-NLS-1$
315 				}
316 				// Add the export package to the header
317 				fHeader.addPackage(exportPackageObject);
318 			}
319 		}
320 	}
321 
322 	@Override
selectionChanged(IStructuredSelection sel)323 	protected void selectionChanged(IStructuredSelection sel) {
324 		getPage().getPDEEditor().setSelection(sel);
325 		updateButtons();
326 	}
327 
updateButtons()328 	private void updateButtons() {
329 		Object[] selected = fPackageViewer.getStructuredSelection().toArray();
330 
331 		TablePart tablePart = getTablePart();
332 		tablePart.setButtonEnabled(ADD_INDEX, canAddExportedPackages());
333 		tablePart.setButtonEnabled(REMOVE_INDEX, isEditable() && selected.length > 0);
334 		tablePart.setButtonEnabled(PROPERTIES_INDEX, shouldEnableProperties(selected));
335 		tablePart.setButtonEnabled(CALCULATE_USE_INDEX, isEditable() && fPackageViewer.getTable().getItemCount() > 0);
336 
337 	}
338 
shouldEnableProperties(Object[] selected)339 	private boolean shouldEnableProperties(Object[] selected) {
340 		if (selected.length == 0)
341 			return false;
342 		if (selected.length == 1)
343 			return true;
344 
345 		String version = ((ExportPackageObject) selected[0]).getVersion();
346 		for (int i = 1; i < selected.length; i++) {
347 			ExportPackageObject object = (ExportPackageObject) selected[i];
348 			if (version == null) {
349 				if (object.getVersion() != null) {
350 					return false;
351 				}
352 			} else if (!version.equals(object.getVersion())) {
353 				return false;
354 			}
355 		}
356 		return true;
357 	}
358 
359 	@Override
handleDoubleClick(IStructuredSelection selection)360 	protected void handleDoubleClick(IStructuredSelection selection) {
361 		handleGoToPackage(selection);
362 	}
363 
getPackageFragment(ISelection sel)364 	private IPackageFragment getPackageFragment(ISelection sel) {
365 		if (sel instanceof IStructuredSelection) {
366 			IStructuredSelection selection = (IStructuredSelection) sel;
367 			if (selection.size() != 1)
368 				return null;
369 
370 			IBaseModel model = getPage().getModel();
371 			if (!(model instanceof IPluginModelBase))
372 				return null;
373 
374 			return PDEJavaHelper.getPackageFragment(((PackageObject) selection.getFirstElement()).getName(), ((IPluginModelBase) model).getPluginBase().getId(), getPage().getPDEEditor().getCommonProject());
375 		}
376 		return null;
377 	}
378 
handleGoToPackage(ISelection selection)379 	private void handleGoToPackage(ISelection selection) {
380 		IPackageFragment frag = getPackageFragment(selection);
381 		if (frag != null)
382 			try {
383 				IViewPart part = PDEPlugin.getActivePage().showView(JavaUI.ID_PACKAGES);
384 				ShowInPackageViewAction action = new ShowInPackageViewAction(part.getSite());
385 				action.run(frag);
386 			} catch (PartInitException e) {
387 			}
388 	}
389 
390 	@Override
buttonSelected(int index)391 	protected void buttonSelected(int index) {
392 		switch (index) {
393 			case ADD_INDEX :
394 				handleAdd();
395 				break;
396 			case REMOVE_INDEX :
397 				handleRemove();
398 				break;
399 			case PROPERTIES_INDEX :
400 				handleOpenProperties();
401 				break;
402 			case CALCULATE_USE_INDEX :
403 				calculateUses();
404 		}
405 	}
406 
handleOpenProperties()407 	private void handleOpenProperties() {
408 		Object[] selected = fPackageViewer.getStructuredSelection().toArray();
409 		ExportPackageObject first = (ExportPackageObject) selected[0];
410 		DependencyPropertiesDialog dialog = new DependencyPropertiesDialog(isEditable(), first);
411 		dialog.create();
412 		PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IHelpContextIds.EXPORTED_PACKAGE_PROPERTIES);
413 		SWTUtil.setDialogSize(dialog, 400, -1);
414 		if (selected.length == 1)
415 			dialog.setTitle(((ExportPackageObject) selected[0]).getName());
416 		else
417 			dialog.setTitle(PDEUIMessages.ExportPackageSection_props);
418 		if (dialog.open() == Window.OK && isEditable()) {
419 			String newVersion = dialog.getVersion();
420 			for (Object selectedObject : selected) {
421 				ExportPackageObject object = (ExportPackageObject) selectedObject;
422 				if (!newVersion.equals(object.getVersion()))
423 					object.setVersion(newVersion);
424 			}
425 		}
426 	}
427 
handleRemove()428 	private void handleRemove() {
429 		Object[] removed = fPackageViewer.getStructuredSelection().toArray();
430 		for (Object removedObject : removed) {
431 			fHeader.removePackage((PackageObject) removedObject);
432 		}
433 	}
434 
handleAdd()435 	private void handleAdd() {
436 		IPluginModelBase model = (IPluginModelBase) getPage().getModel();
437 		final IProject project = model.getUnderlyingResource().getProject();
438 		try {
439 			if (project.hasNature(JavaCore.NATURE_ID)) {
440 				ILabelProvider labelProvider = new JavaElementLabelProvider();
441 				final ConditionalListSelectionDialog dialog = new ConditionalListSelectionDialog(PDEPlugin.getActiveWorkbenchShell(), labelProvider, PDEUIMessages.ExportPackageSection_dialogButtonLabel);
442 				final Collection<?> pckgs = fHeader == null ? new Vector<>() : fHeader.getPackageNames();
443 				final boolean allowJava = "true".equals(getBundle().getHeader(ICoreConstants.ECLIPSE_JREBUNDLE)); //$NON-NLS-1$
444 				Runnable runnable = () -> {
445 					ArrayList<IPackageFragment> elements = new ArrayList<>();
446 					ArrayList<IPackageFragment> conditional = new ArrayList<>();
447 					IPackageFragment[] fragments = PDEJavaHelper.getPackageFragments(JavaCore.create(project), pckgs, allowJava);
448 					for (IPackageFragment fragment : fragments) {
449 						try {
450 							if (fragment.containsJavaResources()) {
451 								elements.add(fragment);
452 							} else {
453 								conditional.add(fragment);
454 							}
455 						} catch (JavaModelException e) {
456 						}
457 					}
458 					dialog.setElements(elements.toArray());
459 					dialog.setConditionalElements(conditional.toArray());
460 					dialog.setMultipleSelection(true);
461 					dialog.setMessage(PDEUIMessages.PackageSelectionDialog_label);
462 					dialog.setTitle(PDEUIMessages.ExportPackageSection_title);
463 					dialog.create();
464 					PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IHelpContextIds.EXPORT_PACKAGES);
465 					SWTUtil.setDialogSize(dialog, 400, 500);
466 				};
467 				BusyIndicator.showWhile(Display.getCurrent(), runnable);
468 				if (dialog.open() == Window.OK) {
469 					Object[] selected = dialog.getResult();
470 					if (fHeader != null) {
471 						for (Object selectedObject : selected) {
472 							IPackageFragment candidate = (IPackageFragment) selectedObject;
473 							fHeader.addPackage(new ExportPackageObject(fHeader, candidate, getVersionAttribute()));
474 						}
475 					} else {
476 						getBundle().setHeader(getExportedPackageHeader(), getValue(selected));
477 						// the way events get triggered, updateButtons isn't called
478 						if (selected.length > 0)
479 							getTablePart().setButtonEnabled(CALCULATE_USE_INDEX, true);
480 					}
481 				}
482 				labelProvider.dispose();
483 			}
484 		} catch (CoreException e) {
485 		}
486 	}
487 
getValue(Object[] objects)488 	private String getValue(Object[] objects) {
489 		StringBuilder buffer = new StringBuilder();
490 		for (Object object : objects) {
491 			IPackageFragment fragment = (IPackageFragment) object;
492 			if (buffer.length() > 0)
493 				buffer.append("," + getLineDelimiter() + " "); //$NON-NLS-1$ //$NON-NLS-2$
494 			buffer.append(fragment.getElementName());
495 		}
496 		return buffer.toString();
497 	}
498 
499 	@Override
modelChanged(IModelChangedEvent event)500 	public void modelChanged(IModelChangedEvent event) {
501 		if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
502 			fHeader = null;
503 			markStale();
504 			return;
505 		}
506 
507 		if (getExportedPackageHeader().equals(event.getChangedProperty())) {
508 			refresh();
509 			// Bug 171896
510 			// Since the model sends a CHANGE event instead of
511 			// an INSERT event on the very first addition to the empty table
512 			// Selection should fire here to take this first insertion into account
513 			Object lastElement = fPackageViewer.getElementAt(fPackageViewer.getTable().getItemCount() - 1);
514 			if (lastElement != null) {
515 				fPackageViewer.setSelection(new StructuredSelection(lastElement));
516 			}
517 
518 			return;
519 		}
520 
521 		Object[] objects = event.getChangedObjects();
522 		for (Object changedObject : objects) {
523 			if (changedObject instanceof ExportPackageObject) {
524 				ExportPackageObject object = (ExportPackageObject) changedObject;
525 				switch (event.getChangeType()) {
526 					case IModelChangedEvent.INSERT :
527 						fPackageViewer.add(object);
528 						fPackageViewer.setSelection(new StructuredSelection(object), false);
529 						fPackageViewer.getTable().setFocus();
530 						break;
531 					case IModelChangedEvent.REMOVE :
532 						Table table = fPackageViewer.getTable();
533 						int index = table.getSelectionIndex();
534 						fPackageViewer.remove(object);
535 						table.setSelection(index < table.getItemCount() ? index : table.getItemCount() - 1);
536 						break;
537 					default :
538 						fPackageViewer.refresh(object);
539 				}
540 			}
541 		}
542 	}
543 
544 	@Override
545 	public void refresh() {
546 		fPackageViewer.refresh();
547 		super.refresh();
548 	}
549 
550 	private void makeActions() {
551 		fAddAction = new Action(PDEUIMessages.RequiresSection_add) {
552 			@Override
553 			public void run() {
554 				handleAdd();
555 			}
556 		};
557 		fAddAction.setEnabled(isEditable());
558 		fGoToAction = new Action(PDEUIMessages.ImportPackageSection_goToPackage) {
559 			@Override
560 			public void run() {
561 				handleGoToPackage(fPackageViewer.getStructuredSelection());
562 			}
563 		};
564 		fRemoveAction = new Action(PDEUIMessages.RequiresSection_delete) {
565 			@Override
566 			public void run() {
567 				handleRemove();
568 			}
569 		};
570 		fRemoveAction.setEnabled(isEditable());
571 
572 		fPropertiesAction = new Action(PDEUIMessages.ExportPackageSection_propertyAction) {
573 			@Override
574 			public void run() {
575 				handleOpenProperties();
576 			}
577 		};
578 	}
579 
580 	@Override
581 	protected void fillContextMenu(IMenuManager manager) {
582 		IStructuredSelection selection = fPackageViewer.getStructuredSelection();
583 		manager.add(fAddAction);
584 		boolean singleSelection = selection.size() == 1;
585 		if (singleSelection)
586 			manager.add(fGoToAction);
587 		manager.add(new Separator());
588 		if (!selection.isEmpty())
589 			manager.add(fRemoveAction);
590 		getPage().getPDEEditor().getContributor().contextMenuAboutToShow(manager);
591 		if (singleSelection)
592 			manager.add(new Action(PDEUIMessages.ExportPackageSection_findReferences) {
593 				@Override
594 				public void run() {
595 					doSearch(fPackageViewer.getStructuredSelection());
596 				}
597 			});
598 		if (shouldEnableProperties(fPackageViewer.getStructuredSelection().toArray())) {
599 			manager.add(new Separator());
600 			manager.add(fPropertiesAction);
601 		}
602 	}
603 
604 	private void doSearch(ISelection sel) {
605 		IPackageFragment frag = getPackageFragment(sel);
606 		if (frag != null) {
607 			FindReferencesAction action = new FindReferencesAction(getPage().getEditorSite());
608 			action.run(frag);
609 		} else if (sel instanceof IStructuredSelection) {
610 			IStructuredSelection selection = (IStructuredSelection) sel;
611 			PackageObject exportObject = (PackageObject) selection.getFirstElement();
612 			NewSearchUI.runQueryInBackground(new BlankQuery(exportObject));
613 		}
614 	}
615 
616 	private BundleInputContext getBundleContext() {
617 		InputContextManager manager = getPage().getPDEEditor().getContextManager();
618 		return (BundleInputContext) manager.findContext(BundleInputContext.CONTEXT_ID);
619 	}
620 
621 	private IBundleModel getBundleModel() {
622 		BundleInputContext context = getBundleContext();
623 		return (context != null) ? (IBundleModel) context.getModel() : null;
624 
625 	}
626 
627 	private String getLineDelimiter() {
628 		BundleInputContext inputContext = getBundleContext();
629 		if (inputContext != null) {
630 			return inputContext.getLineDelimiter();
631 		}
632 		return TextUtil.getDefaultLineDelimiter();
633 	}
634 
635 	private IBundle getBundle() {
636 		IBundleModel model = getBundleModel();
637 		return (model != null) ? model.getBundle() : null;
638 	}
639 
640 	private String getVersionAttribute() {
641 		int manifestVersion = BundlePluginBase.getBundleManifestVersion(getBundle());
642 		return (manifestVersion < 2) ? ICoreConstants.PACKAGE_SPECIFICATION_VERSION : Constants.VERSION_ATTRIBUTE;
643 	}
644 
645 	public String getExportedPackageHeader() {
646 		int manifestVersion = BundlePluginBase.getBundleManifestVersion(getBundle());
647 		return (manifestVersion < 2) ? ICoreConstants.PROVIDE_PACKAGE : Constants.EXPORT_PACKAGE;
648 	}
649 
650 	@Override
651 	protected boolean createCount() {
652 		return true;
653 	}
654 
655 	private void calculateUses() {
656 		final IProject proj = getPage().getPDEEditor().getCommonProject();
657 		Action action = new CalculateUsesAction(proj, (IBundlePluginModelBase) getPage().getModel());
658 		action.run();
659 	}
660 }
661