1 /*******************************************************************************
2  * Copyright (c) 2000, 2012 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  *******************************************************************************/
14 package org.eclipse.jdt.internal.debug.ui.actions;
15 
16 
17 import java.util.ArrayList;
18 import java.util.Iterator;
19 import java.util.List;
20 
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.core.resources.IResource;
23 import org.eclipse.core.resources.IWorkspaceRoot;
24 import org.eclipse.core.resources.ResourcesPlugin;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.MultiStatus;
27 import org.eclipse.jdt.core.IClasspathContainer;
28 import org.eclipse.jdt.core.IClasspathEntry;
29 import org.eclipse.jdt.core.IJavaModel;
30 import org.eclipse.jdt.core.IJavaProject;
31 import org.eclipse.jdt.core.JavaCore;
32 import org.eclipse.jdt.core.JavaModelException;
33 import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
34 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
35 import org.eclipse.jdt.internal.debug.ui.launcher.IClasspathViewer;
36 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
37 import org.eclipse.jdt.launching.JavaRuntime;
38 import org.eclipse.jface.action.IAction;
39 import org.eclipse.jface.viewers.IStructuredSelection;
40 import org.eclipse.jface.window.Window;
41 import org.eclipse.ui.actions.SelectionListenerAction;
42 
43 /**
44  * Adds a project to the runtime class path.
45  */
46 public class AddProjectAction extends RuntimeClasspathAction {
47 
48 
49 
AddProjectAction(IClasspathViewer viewer)50 	public AddProjectAction(IClasspathViewer viewer) {
51 		super(ActionMessages.AddProjectAction_Add_Project_1, viewer);
52 	}
53 
54 	/**
55 	 * Prompts for a project to add.
56 	 *
57 	 * @see IAction#run()
58 	 */
59 	@Override
run()60 	public void run() {
61 		List<IJavaProject> projects = getPossibleAdditions();
62 		ProjectSelectionDialog dialog= new ProjectSelectionDialog(getShell(),projects);
63 		dialog.setTitle(ActionMessages.AddProjectAction_Project_Selection_2);
64 		MultiStatus status = new MultiStatus(JDIDebugUIPlugin.getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "One or more exceptions occurred while adding projects.", null);  //$NON-NLS-1$
65 
66 		if (dialog.open() == Window.OK) {
67 			Object[] selections = dialog.getResult();
68 
69 			List<IJavaProject> additions = new ArrayList<>(selections.length);
70 			try {
71 				for (Object selection : selections) {
72 					IJavaProject jp = (IJavaProject) selection;
73 					if (dialog.isAddRequiredProjects()) {
74 						collectRequiredProjects(jp, additions);
75 					} else {
76 						additions.add(jp);
77 					}
78 				}
79 			} catch (JavaModelException e) {
80 				status.add(e.getStatus());
81 			}
82 
83 			List<IRuntimeClasspathEntry> runtimeEntries = new ArrayList<>(additions.size());
84 			Iterator<IJavaProject> iter = additions.iterator();
85 			while (iter.hasNext()) {
86 				IJavaProject jp = iter.next();
87 				runtimeEntries.add(JavaRuntime.newProjectRuntimeClasspathEntry(jp));
88 				if (dialog.isAddExportedEntries()) {
89 					try {
90 						collectExportedEntries(jp, runtimeEntries);
91 					} catch (CoreException e) {
92 						status.add(e.getStatus());
93 					}
94 				}
95 			}
96 			IRuntimeClasspathEntry[] entries = runtimeEntries.toArray(new IRuntimeClasspathEntry[runtimeEntries.size()]);
97 			getViewer().addEntries(entries);
98 		}
99 
100 		if (!status.isOK()) {
101 			JDIDebugUIPlugin.statusDialog(status);
102 		}
103 	}
104 
105 	/**
106 	 * @see SelectionListenerAction#updateSelection(IStructuredSelection)
107 	 */
108 	@Override
updateSelection(IStructuredSelection selection)109 	protected boolean updateSelection(IStructuredSelection selection) {
110 		return getViewer().updateSelection(getActionType(), selection) && !getPossibleAdditions().isEmpty();
111 	}
112 
113 	@Override
getActionType()114 	protected int getActionType() {
115 		return ADD;
116 	}
117 
118 	/**
119 	 * Returns the possible projects that can be added
120 	 * @return the list of projects
121 	 */
getPossibleAdditions()122 	protected List<IJavaProject> getPossibleAdditions() {
123 		IJavaProject[] projects;
124 		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
125 		try {
126 			projects= JavaCore.create(root).getJavaProjects();
127 		} catch (JavaModelException e) {
128 			JDIDebugUIPlugin.log(e);
129 			projects= new IJavaProject[0];
130 		}
131 		List<IJavaProject> remaining = new ArrayList<>();
132 		for (IJavaProject project : projects) {
133 			remaining.add(project);
134 		}
135 		List<IJavaProject> alreadySelected = new ArrayList<>();
136 		for (IRuntimeClasspathEntry entry : getViewer().getEntries()) {
137 			if (entry.getType() == IRuntimeClasspathEntry.PROJECT) {
138 				IResource res = root.findMember(entry.getPath());
139 				IJavaProject jp = (IJavaProject)JavaCore.create(res);
140 				alreadySelected.add(jp);
141 			}
142 		}
143 		remaining.removeAll(alreadySelected);
144 		return remaining;
145 	}
146 
147 	/**
148 	 * Adds all projects required by <code>proj</code> to the list
149 	 * <code>res</code>
150 	 *
151 	 * @param proj the project for which to compute required
152 	 *  projects
153 	 * @param res the list to add all required projects too
154 	 * @throws JavaModelException if there is a problem accessing the Java model
155 	 */
collectRequiredProjects(IJavaProject proj, List<IJavaProject> res)156 	protected void collectRequiredProjects(IJavaProject proj, List<IJavaProject> res) throws JavaModelException {
157 		if (!res.contains(proj)) {
158 			res.add(proj);
159 
160 			IJavaModel model= proj.getJavaModel();
161 
162 			for (IClasspathEntry curr : proj.getRawClasspath()) {
163 				if (curr.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
164 					IJavaProject ref= model.getJavaProject(curr.getPath().segment(0));
165 					if (ref.exists()) {
166 						collectRequiredProjects(ref, res);
167 					}
168 				}
169 			}
170 		}
171 	}
172 
173 	/**
174 	 * Adds all exported entries defined by <code>proj</code> to the list
175 	 * <code>runtimeEntries</code>.
176 	 *
177 	 * @param proj the project
178 	 * @param runtimeEntries the entries
179 	 * @throws CoreException if an exception occurs
180 	 */
collectExportedEntries(IJavaProject proj, List<IRuntimeClasspathEntry> runtimeEntries)181 	protected void collectExportedEntries(IJavaProject proj, List<IRuntimeClasspathEntry> runtimeEntries) throws CoreException {
182 		for (IClasspathEntry entry : proj.getRawClasspath()) {
183 			if (entry.isExported()) {
184 				IRuntimeClasspathEntry rte = null;
185 				switch (entry.getEntryKind()) {
186 				case IClasspathEntry.CPE_CONTAINER:
187 					IClasspathContainer container = JavaCore.getClasspathContainer(entry.getPath(), proj);
188 					int kind = 0;
189 					switch (container.getKind()) {
190 					case IClasspathContainer.K_APPLICATION:
191 						kind = IRuntimeClasspathEntry.USER_CLASSES;
192 						break;
193 					case IClasspathContainer.K_SYSTEM:
194 						kind = IRuntimeClasspathEntry.BOOTSTRAP_CLASSES;
195 						break;
196 					case IClasspathContainer.K_DEFAULT_SYSTEM:
197 						kind = IRuntimeClasspathEntry.STANDARD_CLASSES;
198 						break;
199 					}
200 					rte = JavaRuntime.newRuntimeContainerClasspathEntry(entry.getPath(), kind, proj);
201 					break;
202 				case IClasspathEntry.CPE_LIBRARY:
203 					rte = JavaRuntime.newArchiveRuntimeClasspathEntry(entry.getPath());
204 					rte.setSourceAttachmentPath(entry.getSourceAttachmentPath());
205 					rte.setSourceAttachmentRootPath(entry.getSourceAttachmentRootPath());
206 					break;
207 				case IClasspathEntry.CPE_PROJECT:
208 					String name = entry.getPath().segment(0);
209 					IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
210 					if (p.exists()) {
211 						IJavaProject jp = JavaCore.create(p);
212 						if (jp.exists()) {
213 							rte = JavaRuntime.newProjectRuntimeClasspathEntry(jp);
214 						}
215 					}
216 					break;
217 				case IClasspathEntry.CPE_VARIABLE:
218 					rte = JavaRuntime.newVariableRuntimeClasspathEntry(entry.getPath());
219 					break;
220 				default:
221 					break;
222 				}
223 				if (rte != null) {
224 					if (!runtimeEntries.contains(rte)) {
225 						runtimeEntries.add(rte);
226 					}
227 				}
228 			}
229 		}
230 	}
231 }
232