public abstract class AbstractOSGiLaunchDelegate extends JavaLaunchDelegate { @SuppressWarnings("deprecation") private static final String ATTR_LOGLEVEL = LaunchConstants.ATTR_LOGLEVEL; private static final ILogger logger = Logger.getLogger(AbstractOSGiLaunchDelegate.class); protected Project model; protected abstract ProjectLauncher getProjectLauncher() throws CoreException; protected abstract void initialiseBndLauncher(ILaunchConfiguration configuration, Project model) throws Exception; protected abstract IStatus getLauncherStatus(); @Override public boolean buildForLaunch( ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException { boolean result = super.buildForLaunch(configuration, mode, monitor); model = LaunchUtils.getBndProject(configuration); try { initialiseBndLauncher(configuration, model); } catch (Exception e) { throw new CoreException( new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, "Error initialising bnd launcher", e)); } return result; } @Override public boolean finalLaunchCheck( ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException { // Check for existing launches of same resource BndPreferences prefs = new BndPreferences(); if (prefs.getWarnExistingLaunches()) { IResource launchResource = LaunchUtils.getTargetResource(configuration); if (launchResource == null) throw new CoreException( new Status( IStatus.ERROR, Plugin.PLUGIN_ID, 0, "Bnd launch target was not specified or does not exist.", null)); int processCount = 0; for (ILaunch l : DebugPlugin.getDefault().getLaunchManager().getLaunches()) { // ... is it the same launch resource? ILaunchConfiguration launchConfig = l.getLaunchConfiguration(); if (launchConfig == null) { continue; } if (launchResource.equals(LaunchUtils.getTargetResource(launchConfig))) { // Iterate existing processes for (IProcess process : l.getProcesses()) { if (!process.isTerminated()) processCount++; } } } // Warn if existing processes running if (processCount > 0) { Status status = new Status( IStatus.WARNING, Plugin.PLUGIN_ID, 0, "One or more OSGi Frameworks have already been launched for this configuration. Additional framework instances may interfere with each other due to the shared storage directory.", null); IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(status); if (prompter != null) { boolean okay = (Boolean) prompter.handleStatus(status, launchResource); if (!okay) return okay; } } } IStatus launchStatus = getLauncherStatus(); IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(launchStatus); if (prompter != null) return (Boolean) prompter.handleStatus(launchStatus, model); return true; } @Override public void launch( ILaunchConfiguration configuration, String mode, final ILaunch launch, IProgressMonitor monitor) throws CoreException { // Register listener to clean up temp files on exit of launched JVM final ProjectLauncher launcher = getProjectLauncher(); IDebugEventSetListener listener = new IDebugEventSetListener() { @Override public void handleDebugEvents(DebugEvent[] events) { for (DebugEvent event : events) { if (event.getKind() == DebugEvent.TERMINATE) { Object source = event.getSource(); if (source instanceof IProcess) { ILaunch processLaunch = ((IProcess) source).getLaunch(); if (processLaunch == launch) { // Not interested in any further events => // unregister this listener DebugPlugin.getDefault().removeDebugEventListener(this); // Cleanup. Guard with a draconian catch because // changes in the ProjectLauncher API // *may* cause LinkageErrors. try { launcher.cleanup(); } catch (Throwable t) { logger.logError("Error cleaning launcher temporary files", t); } } } } } } }; DebugPlugin.getDefault().addDebugEventListener(listener); // Now actually launch super.launch(configuration, mode, launch, monitor); } @Override public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException { Collection<String> paths = getProjectLauncher().getClasspath(); return paths.toArray(new String[paths.size()]); } @Override public String getMainTypeName(ILaunchConfiguration configuration) throws CoreException { return getProjectLauncher().getMainTypeName(); } @Override public File verifyWorkingDirectory(ILaunchConfiguration configuration) throws CoreException { try { return (model != null) ? model.getBase() : null; } catch (Exception e) { throw new CoreException( new Status( IStatus.ERROR, Plugin.PLUGIN_ID, 0, "Error getting working directory for Bnd project.", e)); } } @Override public String getVMArguments(ILaunchConfiguration configuration) throws CoreException { StringBuilder builder = new StringBuilder(); Collection<String> runVM = getProjectLauncher().getRunVM(); for (Iterator<String> iter = runVM.iterator(); iter.hasNext(); ) { builder.append(iter.next()); if (iter.hasNext()) builder.append(" "); } String args = builder.toString(); args = addJavaLibraryPath(configuration, args); return args; } @Override public String getProgramArguments(ILaunchConfiguration configuration) throws CoreException { StringBuilder builder = new StringBuilder(); Collection<String> args = getProjectLauncher().getRunProgramArgs(); for (Iterator<String> iter = args.iterator(); iter.hasNext(); ) { builder.append(iter.next()); if (iter.hasNext()) builder.append(" "); } return builder.toString(); } protected String addJavaLibraryPath(ILaunchConfiguration configuration, String args) throws CoreException { String a = args; // Following code copied from AbstractJavaLaunchConfigurationDelegate int libraryPath = a.indexOf("-Djava.library.path"); // $NON-NLS-1$ if (libraryPath < 0) { // if a library path is already specified, do not override String[] javaLibraryPath = getJavaLibraryPath(configuration); if (javaLibraryPath != null && javaLibraryPath.length > 0) { StringBuffer path = new StringBuffer(a); path.append(" -Djava.library.path="); // $NON-NLS-1$ path.append("\""); // $NON-NLS-1$ for (int i = 0; i < javaLibraryPath.length; i++) { if (i > 0) { path.append(File.pathSeparatorChar); } path.append(javaLibraryPath[i]); } path.append("\""); // $NON-NLS-1$ a = path.toString(); } } return a; } protected static void enableTraceOptionIfSetOnConfiguration( ILaunchConfiguration configuration, ProjectLauncher launcher) throws CoreException { if (configuration.hasAttribute(LaunchConstants.ATTR_TRACE)) { launcher.setTrace( configuration.getAttribute(LaunchConstants.ATTR_TRACE, LaunchConstants.DEFAULT_TRACE)); } String logLevelStr = configuration.getAttribute(ATTR_LOGLEVEL, (String) null); if (logLevelStr != null) { Plugin.getDefault() .getLog() .log( new Status( IStatus.WARNING, Plugin.PLUGIN_ID, 0, MessageFormat.format( "The {0} attribute is no longer supported, use {1} instead.", ATTR_LOGLEVEL, LaunchConstants.ATTR_TRACE), null)); Level logLevel = Level.parse(logLevelStr); launcher.setTrace(launcher.getTrace() || logLevel.intValue() <= Level.FINE.intValue()); } } protected static MultiStatus createStatus( String message, List<String> errors, List<String> warnings) { MultiStatus status = new MultiStatus(Plugin.PLUGIN_ID, 0, message, null); for (String error : errors) { status.add(new Status(IStatus.ERROR, Plugin.PLUGIN_ID, 0, error, null)); } for (String warning : warnings) { status.add(new Status(IStatus.WARNING, Plugin.PLUGIN_ID, 0, warning, null)); } return status; } }
public class PkgRenameParticipant extends RenameParticipant implements ISharableParticipant { private static final ILogger logger = Logger.getLogger(PkgRenameParticipant.class); private final Map<IPackageFragment, RenameArguments> pkgFragments = new HashMap<IPackageFragment, RenameArguments>(); private String changeTitle = null; @Override protected boolean initialize(Object element) { IPackageFragment pkgFragment = (IPackageFragment) element; RenameArguments args = getArguments(); pkgFragments.put(pkgFragment, args); StringBuilder sb = new StringBuilder(256); sb.append("Bndtools: rename package '"); sb.append(pkgFragment.getElementName()); sb.append("' "); if (((RenamePackageProcessor) this.getProcessor()).getRenameSubpackages()) sb.append("and subpackages "); sb.append("to '"); sb.append(args.getNewName()); sb.append("'"); changeTitle = sb.toString(); return true; } public void addElement(Object element, RefactoringArguments arguments) { this.pkgFragments.put((IPackageFragment) element, (RenameArguments) arguments); } @Override public String getName() { return "Bndtools Package Rename Participant"; } @Override public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException { return new RefactoringStatus(); } private static final String grammarSeparator = "[\\s,\"';]"; @Override public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException { final Map<IFile, TextChange> fileChanges = new HashMap<IFile, TextChange>(); IResourceProxyVisitor visitor = new IResourceProxyVisitor() { public boolean visit(IResourceProxy proxy) throws CoreException { if ((proxy.getType() == IResource.FOLDER) || (proxy.getType() == IResource.PROJECT)) { return true; } if (!((proxy.getType() == IResource.FILE) && proxy.getName().toLowerCase().endsWith(".bnd"))) { return false; } /* we're dealing with a *.bnd file */ /* get the proxied file */ IFile resource = (IFile) proxy.requestResource(); /* read the file as a single string */ String bndFileText = null; try { bndFileText = FileUtils.readFully(resource).get(); } catch (Exception e) { String str = "Could not read file " + proxy.getName(); logger.logError(str, e); throw new OperationCanceledException(str); } /* * get the previous change for this file if it exists, or otherwise create a new change for it, but do * not store it yet: wait until we know if there are actually changes in the file */ TextChange fileChange = getTextChange(resource); final boolean fileChangeIsNew = (fileChange == null); if (fileChange == null) { fileChange = new TextFileChange(proxy.getName(), resource); fileChange.setEdit(new MultiTextEdit()); } TextEdit rootEdit = fileChange.getEdit(); /* loop over all renames to perform */ for (Map.Entry<IPackageFragment, RenameArguments> entry : pkgFragments.entrySet()) { IPackageFragment pkgFragment = entry.getKey(); RenameArguments arguments = entry.getValue(); final String oldName = pkgFragment.getElementName(); final String newName = arguments.getNewName(); Pattern pattern = Pattern.compile( /* match start boundary */ "(^|" + grammarSeparator + ")" + /* match itself / package name */ "(" + Pattern.quote(oldName) + ")" + /* match end boundary */ "(" + grammarSeparator + "|" + Pattern.quote(".*") + "|" + Pattern.quote("\\") + "|$)"); /* find all matches to replace and add them to the root edit */ Matcher matcher = pattern.matcher(bndFileText); while (matcher.find()) { rootEdit.addChild( new ReplaceEdit(matcher.start(2), matcher.group(2).length(), newName)); } pattern = Pattern.compile( /* match start boundary */ "(^|" + grammarSeparator + ")" + /* match bundle activator */ "(Bundle-Activator\\s*:\\s*)" + /* match itself / package name */ "(" + Pattern.quote(oldName) + ")" + /* match class name */ "(\\.[^\\.]+)" + /* match end boundary */ "(" + grammarSeparator + "|" + Pattern.quote("\\") + "|$)"); /* find all matches to replace and add them to the root edit */ matcher = pattern.matcher(bndFileText); while (matcher.find()) { rootEdit.addChild( new ReplaceEdit(matcher.start(3), matcher.group(3).length(), newName)); } } /* * only store the changes when no changes were stored before for this file and when there are actually * changes. */ if (fileChangeIsNew && rootEdit.hasChildren()) { fileChanges.put(resource, fileChange); } return false; } }; /* determine which projects have to be visited */ Set<IProject> projectsToVisit = new HashSet<IProject>(); for (IPackageFragment pkgFragment : pkgFragments.keySet()) { projectsToVisit.add(pkgFragment.getResource().getProject()); for (IProject projectToVisit : pkgFragment.getResource().getProject().getReferencingProjects()) { projectsToVisit.add(projectToVisit); } for (IProject projectToVisit : pkgFragment.getResource().getProject().getReferencedProjects()) { projectsToVisit.add(projectToVisit); } } /* visit the projects */ for (IProject projectToVisit : projectsToVisit) { projectToVisit.accept(visitor, IContainer.NONE); } if (fileChanges.isEmpty()) { /* no changes at all */ return null; } /* build a composite change with all changes */ CompositeChange cs = new CompositeChange(changeTitle); for (TextChange fileChange : fileChanges.values()) { cs.add(fileChange); } return cs; } }
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 filter = null; private boolean showRepos = true; 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 filter; } public void setFilter(String filter) { this.filter = filter; } public void setShowRepos(boolean showRepos) { this.showRepos = showRepos; } public boolean isShowRepos() { return showRepos; } @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(new Object[result.size()]); } public void dispose() {} public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} 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; } public Object getParent(Object element) { if (element instanceof RepositoryBundle) { return ((RepositoryBundle) element).getRepo(); } if (element instanceof RepositoryBundleVersion) { return ((RepositoryBundleVersion) element).getBundle(); } return null; } 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 repo) { Object[] result = null; List<String> bsns = null; try { bsns = repo.list(filter); } catch (Exception e) { logger.logError(MessageFormat.format("Error querying repository {0}.", repo.getName()), e); } if (bsns != null) { Collections.sort(bsns); result = new RepositoryBundle[bsns.size()]; int i = 0; for (String bsn : bsns) { result[i++] = new RepositoryBundle(repo, bsn); } } return result; } }
class LaunchThread extends Thread implements IProcess { private static final ILogger logger = Logger.getLogger(OSGiRunLaunchDelegate.class); private final ProjectLauncher launcher; private final AtomicBoolean terminated = new AtomicBoolean(false); private final BundleContext context = FrameworkUtil.getBundle(LaunchThread.class).getBundleContext(); private final ILaunch launch; private final Map<String, String> attributes = new HashMap<String, String>(); private int exitValue; private BndStreamsProxy sproxy; private final RunSession session; LaunchThread(ProjectLauncher pl, RunSession session, ILaunch launch) { super("bnd::launch-" + pl.getProject()); super.setDaemon(true); this.launcher = pl; this.launch = launch; this.session = session; attributes.put(IProcess.ATTR_PROCESS_TYPE, session.getName()); attributes.put(IProcess.ATTR_PROCESS_LABEL, session.getLabel()); attributes.put(IProcess.ATTR_CMDLINE, session.getLabel()); } void doDebug(IProgressMonitor monitor) throws InterruptedException { monitor.setTaskName( "Connecting debugger " + session.getName() + " to " + session.getHost() + ":" + session.getJdb()); Map<String, String> parameters = new HashMap<String, String>(); parameters.put("hostname", session.getHost()); parameters.put("port", session.getJdb() + ""); parameters.put("timeout", session.getTimeout() + ""); IVMConnector connector = JavaRuntime.getDefaultVMConnector(); while (!monitor.isCanceled()) { try { connector.connect(parameters, monitor, launch); break; } catch (Exception e) { Thread.sleep(500); } } } /** This is the reason for this thread. We launch the remote process and wait until it returns. */ @Override public void run() { fireCreationEvent(); // // We wait for build changes. We never update during a build // and we will wait a bit after a build ends. // UpdateGuard guard = new UpdateGuard(context) { @Override protected void update() { LaunchThread.this.update(); } }; guard.open(); try { exitValue = session.launch(); } catch (Exception e) { logger.logWarning("Exception from launcher", e); e.printStackTrace(); } finally { guard.close(); terminate(); } } private void update() { if (isTerminated()) return; try { // // TODO Should use listener // if (launcher.getProject() instanceof Run) launcher.getProject().refresh(); launcher.update(); } catch (Exception e) { logger.logWarning("Exception from update", e); } fireChangeEvent(); } @Override public void terminate() { if (terminated.getAndSet(true)) return; if (sproxy != null) sproxy.close(); try { launcher.cancel(); } catch (Exception e) { // ignore } finally { fireTerminateEvent(); } IDebugTarget[] debugTargets = launch.getDebugTargets(); for (int i = 0; i < debugTargets.length; i++) { IDebugTarget target = debugTargets[i]; if (target.canDisconnect()) { try { target.disconnect(); } catch (Exception e) { e.printStackTrace(); } } } } @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class adapter) { if (adapter.equals(IProcess.class)) { return this; } if (adapter.equals(IDebugTarget.class)) { ILaunch launch = getLaunch(); IDebugTarget[] targets = launch.getDebugTargets(); for (int i = 0; i < targets.length; i++) { if (this.equals(targets[i].getProcess())) { return targets[i]; } } return null; } if (adapter.equals(ILaunch.class)) { return getLaunch(); } if (adapter.equals(ILaunchConfiguration.class)) { return getLaunch().getLaunchConfiguration(); } return null; } @Override public boolean canTerminate() { return !isTerminated(); } @Override public boolean isTerminated() { return terminated.get(); } @Override public String getLabel() { return launcher.getProject().toString(); } @Override public ILaunch getLaunch() { return launch; } @Override public IStreamsProxy getStreamsProxy() { if (sproxy == null) { sproxy = new BndStreamsProxy(launcher, session); } return sproxy; } @Override public void setAttribute(String key, String value) { attributes.put(key, value); } @Override public String getAttribute(String key) { return attributes.get(key); } @Override public int getExitValue() throws DebugException { if (!terminated.get()) throw new DebugException(new Status(IStatus.ERROR, BndtoolsConstants.CORE_PLUGIN_ID, "")); return exitValue; } /** Fires a creation event. */ protected void fireCreationEvent() { fireEvent(new DebugEvent(this, DebugEvent.CREATE)); } /** Fires a terminate event. */ protected void fireTerminateEvent() { fireEvent(new DebugEvent(this, DebugEvent.TERMINATE)); } /** Fires a change event. */ protected void fireChangeEvent() { fireEvent(new DebugEvent(this, DebugEvent.CHANGE)); } /** * Fires the given debug event. * * @param event debug event to fire */ protected void fireEvent(DebugEvent event) { DebugPlugin manager = DebugPlugin.getDefault(); if (manager != null) { manager.fireDebugEventSet(new DebugEvent[] {event}); } } }
public class RepositoriesView extends ViewPart implements RepositoryListenerPlugin { static final Pattern LABEL_PATTERN = Pattern.compile("(-)?(!)?([^{}]+)(?:\\{([^}]+)\\})?"); private static final String DROP_TARGET = "dropTarget"; private static final ILogger logger = Logger.getLogger(RepositoriesView.class); private final FilterPanelPart filterPart = new FilterPanelPart(Plugin.getDefault().getScheduler()); private final SearchableRepositoryTreeContentProvider contentProvider = new SearchableRepositoryTreeContentProvider(); private TreeViewer viewer; private Action collapseAllAction; private Action refreshAction; private Action addBundlesAction; private ServiceRegistration<RepositoryListenerPlugin> registration; @Override public void createPartControl(Composite parent) { // CREATE CONTROLS Composite mainPanel = new Composite(parent, SWT.NONE); Control filterPanel = filterPart.createControl(mainPanel, 5, 5); Tree tree = new Tree(mainPanel, SWT.FULL_SELECTION | SWT.MULTI); filterPanel.setBackground(tree.getBackground()); viewer = new TreeViewer(tree); viewer.setContentProvider(contentProvider); ColumnViewerToolTipSupport.enableFor(viewer); viewer.setLabelProvider(new RepositoryTreeLabelProvider(false)); getViewSite().setSelectionProvider(viewer); createActions(); JpmPreferences jpmPrefs = new JpmPreferences(); final boolean showJpmOnClick = jpmPrefs.getBrowserSelection() != JpmPreferences.PREF_BROWSER_EXTERNAL; // LISTENERS filterPart.addPropertyChangeListener( new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { String filter = (String) event.getNewValue(); updatedFilter(filter); } }); ViewerDropAdapter dropAdapter = new ViewerDropAdapter(viewer) { @Override public boolean validateDrop(Object target, int operation, TransferData transferType) { if (canDrop(target, transferType)) return true; boolean valid = false; if (target instanceof RepositoryPlugin) { if (((RepositoryPlugin) target).canWrite()) { if (URLTransfer.getInstance().isSupportedType(transferType)) return true; if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { ISelection selection = LocalSelectionTransfer.getTransfer().getSelection(); if (selection instanceof IStructuredSelection) { for (Iterator<?> iter = ((IStructuredSelection) selection).iterator(); iter.hasNext(); ) { Object element = iter.next(); if (element instanceof RepositoryBundle || element instanceof RepositoryBundleVersion) { valid = true; break; } if (element instanceof IFile) { valid = true; break; } if (element instanceof IAdaptable) { IFile file = (IFile) ((IAdaptable) element).getAdapter(IFile.class); if (file != null) { valid = true; break; } } } } } else { valid = true; } } } return valid; } @Override public void dragEnter(DropTargetEvent event) { super.dragEnter(event); event.detail = DND.DROP_COPY; } @Override public boolean performDrop(Object data) { if (RepositoriesView.this.performDrop( getCurrentTarget(), getCurrentEvent().currentDataType)) { viewer.refresh(getCurrentTarget(), true); return true; } boolean copied = false; if (URLTransfer.getInstance().isSupportedType(getCurrentEvent().currentDataType)) { try { URL url = new URL( (String) URLTransfer.getInstance() .nativeToJava(getCurrentEvent().currentDataType)); File tmp = File.createTempFile("dwnl", ".jar"); IO.copy(url, tmp); copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), new File[] {tmp}); } catch (Exception e) { return false; } } else if (data instanceof String[]) { String[] paths = (String[]) data; File[] files = new File[paths.length]; for (int i = 0; i < paths.length; i++) { files[i] = new File(paths[i]); } copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), files); } else if (data instanceof IResource[]) { IResource[] resources = (IResource[]) data; File[] files = new File[resources.length]; for (int i = 0; i < resources.length; i++) { files[i] = resources[i].getLocation().toFile(); } copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), files); } else if (data instanceof IStructuredSelection) { File[] files = convertSelectionToFiles((IStructuredSelection) data); if (files != null && files.length > 0) copied = addFilesToRepository((RepositoryPlugin) getCurrentTarget(), files); } return copied; } }; dropAdapter.setFeedbackEnabled(false); dropAdapter.setExpandEnabled(false); viewer.addDropSupport( DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] { URLTransfer.getInstance(), FileTransfer.getInstance(), ResourceTransfer.getInstance(), LocalSelectionTransfer.getTransfer() }, dropAdapter); viewer.addDragSupport( DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] {LocalSelectionTransfer.getTransfer()}, new SelectionDragAdapter(viewer)); viewer.addSelectionChangedListener( new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { boolean writableRepoSelected = false; IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); Object element = selection.getFirstElement(); if (element instanceof RepositoryPlugin) { RepositoryPlugin repo = (RepositoryPlugin) element; writableRepoSelected = repo.canWrite(); } addBundlesAction.setEnabled(writableRepoSelected); } }); tree.addMouseListener( new MouseAdapter() { @Override public void mouseUp(MouseEvent ev) { Object element = ((IStructuredSelection) viewer.getSelection()).getFirstElement(); if (element instanceof ContinueSearchElement) { try { getViewSite() .getPage() .showView( Plugin.JPM_BROWSER_VIEW_ID, null, showJpmOnClick ? IWorkbenchPage.VIEW_ACTIVATE : IWorkbenchPage.VIEW_CREATE); } catch (PartInitException e) { Plugin.getDefault().getLog().log(e.getStatus()); } } } }); viewer.addDoubleClickListener( new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { if (!event.getSelection().isEmpty()) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object element = selection.getFirstElement(); if (element instanceof IAdaptable) { URI uri = (URI) ((IAdaptable) element).getAdapter(URI.class); if (uri != null) { IWorkbenchPage page = getSite().getPage(); try { IFileStore fileStore = EFS.getLocalFileSystem().getStore(uri); IDE.openEditorOnFileStore(page, fileStore); } catch (PartInitException e) { logger.logError("Error opening editor for " + uri, e); } } } else if (element instanceof ContinueSearchElement) { ContinueSearchElement searchElement = (ContinueSearchElement) element; try { JpmPreferences jpmPrefs = new JpmPreferences(); if (jpmPrefs.getBrowserSelection() == JpmPreferences.PREF_BROWSER_EXTERNAL) getViewSite() .getWorkbenchWindow() .getWorkbench() .getBrowserSupport() .getExternalBrowser() .openURL(new URL("https://www.jpm4j.org/" + searchElement.getFilter())); else getViewSite() .getPage() .showView(Plugin.JPM_BROWSER_VIEW_ID, null, IWorkbenchPage.VIEW_VISIBLE); } catch (PartInitException e) { Plugin.getDefault().getLog().log(e.getStatus()); } catch (MalformedURLException e) { // ignore } } } } }); createContextMenu(); // LOAD Central.onWorkspaceInit( new Function<Workspace, Void>() { @Override public Void run(Workspace a) { final List<RepositoryPlugin> repositories = RepositoryUtils.listRepositories(true); SWTConcurrencyUtil.execForControl( viewer.getControl(), true, new Runnable() { @Override public void run() { viewer.setInput(repositories); } }); return null; } }); // LAYOUT GridLayout layout = new GridLayout(1, false); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginWidth = 0; layout.marginHeight = 0; mainPanel.setLayout(layout); tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); filterPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); // Toolbar createActions(); fillToolBar(getViewSite().getActionBars().getToolBarManager()); // Register as repository listener registration = Activator.getDefault() .getBundleContext() .registerService(RepositoryListenerPlugin.class, this, null); } @Override public void setFocus() { filterPart.setFocus(); } private static File[] convertSelectionToFiles(ISelection selection) { if (!(selection instanceof IStructuredSelection)) return new File[0]; IStructuredSelection structSel = (IStructuredSelection) selection; List<File> files = new ArrayList<File>(structSel.size()); for (Iterator<?> iter = structSel.iterator(); iter.hasNext(); ) { Object element = iter.next(); if (element instanceof IFile) files.add(((IFile) element).getLocation().toFile()); else if (element instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) element; IFile ifile = (IFile) adaptable.getAdapter(IFile.class); if (ifile != null) { files.add(ifile.getLocation().toFile()); } else { File file = (File) adaptable.getAdapter(File.class); if (file != null) { files.add(file); } } } } return files.toArray(new File[files.size()]); } @Override public void dispose() { registration.unregister(); super.dispose(); } boolean addFilesToRepository(RepositoryPlugin repo, File[] files) { AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(repo, files); WizardDialog dialog = new WizardDialog(getViewSite().getShell(), wizard); dialog.open(); viewer.refresh(repo); return true; } private void updatedFilter(String filterString) { String newFilter; if (filterString == null || filterString.length() == 0 || filterString.trim().equals("*")) newFilter = null; else newFilter = "*" + filterString.trim() + "*"; contentProvider.setFilter(newFilter); viewer.refresh(); if (newFilter != null) viewer.expandToLevel(2); } void createActions() { collapseAllAction = new Action() { @Override public void run() { viewer.collapseAll(); } }; collapseAllAction.setText("Collapse All"); collapseAllAction.setToolTipText("Collapse All"); collapseAllAction.setImageDescriptor( AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "/icons/collapseall.gif")); refreshAction = new Action() { @Override public void run() { doRefresh(); } }; refreshAction.setText("Refresh"); refreshAction.setToolTipText("Refresh Repositories Tree"); refreshAction.setImageDescriptor( AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "/icons/arrow_refresh.png")); addBundlesAction = new Action() { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); Object element = selection.getFirstElement(); if (element != null && element instanceof RepositoryPlugin) { RepositoryPlugin repo = (RepositoryPlugin) element; if (repo.canWrite()) { AddFilesToRepositoryWizard wizard = new AddFilesToRepositoryWizard(repo, new File[0]); WizardDialog dialog = new WizardDialog(getViewSite().getShell(), wizard); dialog.open(); viewer.refresh(repo); } } } }; addBundlesAction.setEnabled(false); addBundlesAction.setText("Add"); addBundlesAction.setToolTipText("Add Bundles to Repository"); addBundlesAction.setImageDescriptor( AbstractUIPlugin.imageDescriptorFromPlugin(Plugin.PLUGIN_ID, "/icons/brick_add.png")); } void createContextMenu() { MenuManager mgr = new MenuManager(); Menu menu = mgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); getSite().registerContextMenu(mgr, viewer); mgr.addMenuListener( new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { try { manager.removeAll(); IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); if (!selection.isEmpty()) { Object firstElement = selection.getFirstElement(); if (firstElement instanceof Actionable) { // // Use the Actionable interface to fill the menu // Should extend this to allow other menu entries // from the view, but currently there are none // final Actionable act = (Actionable) firstElement; Map<String, Runnable> actions = act.actions(); if (actions != null) { for (final Entry<String, Runnable> e : actions.entrySet()) { String label = e.getKey(); boolean enabled = true; boolean checked = false; String description = null; Matcher m = LABEL_PATTERN.matcher(label); if (m.matches()) { if (m.group(1) != null) enabled = false; if (m.group(2) != null) checked = true; label = m.group(3); description = m.group(4); } Action a = new Action(label) { @Override public void run() { try { e.getValue().run(); } catch (Exception e) { throw new RuntimeException(e); } viewer.refresh(act); } }; a.setEnabled(enabled); if (description != null) a.setDescription(description); a.setChecked(checked); manager.add(a); } } } } } catch (Exception e) { throw new RuntimeException(e); } } }); } private void doRefresh() { // Remember names of expanded repositories Set<String> expandedRepoNames = new HashSet<String>(); Object[] expandedElems = viewer.getExpandedElements(); for (Object expandedElem : expandedElems) { if (expandedElem instanceof RepositoryPlugin) { expandedRepoNames.add(((RepositoryPlugin) expandedElem).getName()); } } // Reload repositories List<RepositoryPlugin> repos = RepositoryUtils.listRepositories(true); viewer.setInput(repos); // Expand any repos that have the same name as a repository that // was expanded before the reload. for (RepositoryPlugin repo : repos) { if (expandedRepoNames.contains(repo.getName())) { viewer.setExpandedState(repo, true); } } } private void fillToolBar(IToolBarManager toolBar) { toolBar.add(refreshAction); toolBar.add(collapseAllAction); toolBar.add(addBundlesAction); toolBar.add(new Separator()); } @Override public void bundleAdded(final RepositoryPlugin repository, Jar jar, File file) { if (viewer != null) SWTConcurrencyUtil.execForControl( viewer.getControl(), true, new Runnable() { @Override public void run() { viewer.refresh(repository); } }); } @Override public void bundleRemoved(final RepositoryPlugin repository, Jar jar, File file) { if (viewer != null) SWTConcurrencyUtil.execForControl( viewer.getControl(), true, new Runnable() { @Override public void run() { viewer.refresh(repository); } }); } @Override public void repositoryRefreshed(final RepositoryPlugin repository) { if (viewer != null) SWTConcurrencyUtil.execForControl( viewer.getControl(), true, new Runnable() { @Override public void run() { viewer.refresh(repository); } }); } @Override public void repositoriesRefreshed() { if (viewer != null) SWTConcurrencyUtil.execForControl( viewer.getControl(), true, new Runnable() { @Override public void run() { doRefresh(); } }); } /** * Handle the drop on targets that understand drops. * * @param target The current target * @param data The transfer data * @return true if the data is acceptable, otherwise false */ boolean canDrop(Object target, TransferData data) { try { Class<?> type = toJavaType(data); if (type != null) { target.getClass().getMethod(DROP_TARGET, type); return true; } } catch (Exception e) { // Ignore } return false; } /** * Try a drop on the target. A drop is allowed if the target implements a {@code dropTarget} * method that returns a boolean. * * @param target the target being dropped upon * @param data the data * @return true if dropped and processed, false if not */ boolean performDrop(Object target, TransferData data) { try { Object java = toJava(data); if (java == null) return false; Method m = target.getClass().getMethod(DROP_TARGET, java.getClass()); return (Boolean) m.invoke(target, java); } catch (Exception e) { return false; } } /** * Return the class of the dropped object * * <pre> * URLTransfer URI * FileTransfer File[] * TextTransfer String * ImageTransfer ImageData * </pre> * * @param data the dropped object * @return the class of the dropped object, or null when it's unknown * @throws Exception upon error */ Class<?> toJavaType(TransferData data) throws Exception { if (URLTransfer.getInstance().isSupportedType(data)) return URI.class; if (FileTransfer.getInstance().isSupportedType(data)) return File[].class; if (TextTransfer.getInstance().isSupportedType(data)) return String.class; // if (ImageTransfer.getInstance().isSupportedType(data)) // return Image.class; return null; } /** * Return a native data type that represents the dropped object * * <pre> * URLTransfer URI * FileTransfer File[] * TextTransfer String * ImageTransfer ImageData * </pre> * * @param data the dropped object * @return a native data type that represents the dropped object, or null when the data type is * unknown * @throws Exception upon error */ Object toJava(TransferData data) throws Exception { if (URLTransfer.getInstance().isSupportedType(data)) return Converter.cnv(URI.class, URLTransfer.getInstance().nativeToJava(data)); else if (FileTransfer.getInstance().isSupportedType(data)) { return Converter.cnv(File[].class, FileTransfer.getInstance().nativeToJava(data)); } else if (TextTransfer.getInstance().isSupportedType(data)) { return TextTransfer.getInstance().nativeToJava(data); } // Need to write the transfer code since the ImageTransfer turns it into // something very Eclipsy // else if (ImageTransfer.getInstance().isSupportedType(data)) // return ImageTransfer.getInstance().nativeToJava(data); return null; } }