1 package net.sourceforge.phpeclipse.xdebug.php.launching;
4 import java.util.ArrayList;
5 import java.util.Iterator;
9 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
10 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
11 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
13 import org.eclipse.core.resources.IFile;
14 import org.eclipse.core.resources.IProject;
15 import org.eclipse.core.resources.IWorkspaceRoot;
16 import org.eclipse.core.resources.ResourcesPlugin;
17 import org.eclipse.core.runtime.CoreException;
18 import org.eclipse.core.runtime.IPath;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.MultiStatus;
21 import org.eclipse.core.runtime.Path;
22 import org.eclipse.debug.core.DebugPlugin;
23 import org.eclipse.debug.core.ILaunchConfigurationType;
24 import org.eclipse.debug.core.model.IStackFrame;
25 import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
26 import org.eclipse.debug.core.sourcelookup.ISourceContainer;
27 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages;
29 public class PHPSourceLookupParticipant extends AbstractSourceLookupParticipant {
31 private Map pathMap = null;
32 private boolean remoteDebug = true;
33 private IPath remoteSourcePath;
34 private String projectName;
37 * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#getSourceName(Object)
39 public String getSourceName(Object object) throws CoreException {
40 if (object instanceof XDebugStackFrame) {
41 return ((XDebugStackFrame) object).getFullSourceName();
47 * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
49 * Return the client side source filename for the server side source file.
50 * E.g. when cross debugging, the server side filename could be /var/www/index.php
51 * on the client side it is either a Eclipse_PHP_projectname\index.php (when it is a linked file)
54 * @param stackFrame The stackframe for which we want the client side source file name
55 * @return The filename as it appears on the client side
57 public Object getSourceElement (IStackFrame stackFrame) throws CoreException {
67 PathMapItem pmi = null;
71 projectName = getDirector().getLaunchConfiguration().getAttribute (IXDebugConstants.ATTR_PHP_PROJECT, "");
72 pathMap = getDirector().getLaunchConfiguration().getAttribute (IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
73 project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
75 if (getDirector ().getLaunchConfiguration ().getType ().getName ().equals ("PHP XDebug Script")) {
82 fileName = ((XDebugStackFrame) stackFrame).getFullSourceName (); // Get the filename as it is submitted by XDebug
84 if (remoteDebug) { // Is it a remote debugging session
85 path = new Path (fileName); // Create a IPath object for the server side filename
87 if (!remoteSourcePath.isEmpty()) {
88 if (remoteSourcePath.isPrefixOf (path)) { // Is the server side filename with the remote source path
89 path = path.removeFirstSegments (remoteSourcePath.matchingFirstSegments (path)); // Remove the remote source path
90 //file = path.toString (); // The filename without the remote source path
91 projectPath = (ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
93 return (projectPath.append (path)).toOSString (); // Return the filename as absolute client side path
98 if (pathMap == null) { // Do we have path mapping (e.g. for cross platform debugging)
99 return fileName; // No, then return the filename as it given by DBG (the full server side path)
104 for (int k = 0; k < pathMap.size(); k++) {
105 pmi = new PathMapItem ((String) pathMap.get(k));
107 local = pmi.getLocalPath ().toString(); //
108 localPath = new Path (pmi.getLocalPath().toString()); // Get the local/client side path of the mapping
109 remotePath = new Path (pmi.getRemotePath().toString()); // Get the remote/server side path of the mapping
111 if (remotePath.isPrefixOf (path)) { // Starts the remote/server side file path with the remote/server side mapping path
112 path = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
114 return path.toString ();
116 localPath = new Path (local); // Create new IPath object for the local/client side path
117 path = localPath.append (path); // Prepend the project relative path to filename
119 projectPath = (ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
122 return (projectPath.append (path)).toString (); // Return the filename as absolute client side path
128 if (pathMap == null) { // Do we have path mapping (e.g. for cross platform debugging)
129 return fileName; // No, then return the filename as it given by DBG (the full server side path)
134 for (int k = 0; k < pathMap.size(); k++) {
135 pmi = new PathMapItem((String) pathMap.get(k));
137 local = pmi.getLocalPath().toString(); // Get the local/client side path of the mapping
138 localPath = new Path (pmi.getLocalPath().toString()); // Get the local/client side path of the mapping
139 remotePath = new Path (pmi.getRemotePath().toString()); // Get the remote/server side path of the mapping
141 if (remotePath.isPrefixOf (path)) { // Starts the remote/server side file path with the remote/server side mapping path
142 path = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
143 localPath = new Path (local); // Create new IPath object for the local/client side path
145 return localPath.append (path).toOSString (); // Append the remote filename to the client side path (So we return the absolute path
146 // to the source file as the client side sees it.
152 } else { // no remote debug
153 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
154 IPath filePath = new Path(fileName);
156 if (root.getFileForLocation(filePath) == null) {
157 IProject proj = root.getProject (projectName);
158 IFile[] files = root.findFilesForLocation (filePath);
160 for (int i = 0; i < files.length; i++) {
161 if (files[i].getProject().equals(proj)) {
162 fileName = proj.getFullPath().append(files[i].getProjectRelativePath()).toOSString();
168 projectPath = (ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getLocation());
169 filePath = filePath.removeFirstSegments (projectPath.matchingFirstSegments (filePath));
171 return filePath.toString ();
179 * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#findSourceElements(java.lang.Object)
181 public Object[] findSourceElements (Object object) throws CoreException {
184 if (object == null) {
185 return new Object[] {};
187 XDebugStackFrame stackFrame = null;
188 if (object instanceof XDebugStackFrame) {
189 stackFrame = (XDebugStackFrame) object;
191 return new Object[] {};
195 CoreException single = null;
196 MultiStatus multiStatus = null;
198 if (isFindDuplicates()) {
199 results = new ArrayList();
203 name = (String) getSourceElement (stackFrame);
205 catch (CoreException e) {
208 if (name == null || name.length() == 0) {
209 return new Object[] {};
212 // here our stackframe is guaranteed not to be null
213 IPath sLocalPath = null;
215 if (((XDebugStackFrame) object).getThread() == null) {
216 IPath sPath = new Path(stackFrame.getFullName().getPath());
217 List pathMap = getDirector().getLaunchConfiguration()
218 .getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
220 PathMapItem pmi = null;
221 for (int k = 0; k < pathMap.size(); k++) {
222 pmi = new PathMapItem((String) pathMap.get(k));
224 IPath local = new Path(pmi.getLocalPath().toString());
225 IPath remote = new Path(pmi.getRemotePath().toString());
227 if (remote.matchingFirstSegments(sPath) == remote.segmentCount()) {
235 String Type = stackFrame.getType();
237 if (Type.equals("eval")) {
238 results.add("pippo");
239 return results.toArray();
242 ISourceContainer[] containers = getSourceContainers();
243 for (int i = 0; i < containers.length; i++) {
244 ISourceContainer container = getDelegateContainer(containers[i]);
245 if (container == null) {
250 Object[] objects = container.findSourceElements(name);
251 if (objects.length > 0) {
252 if (isFindDuplicates()) {
253 if (((XDebugStackFrame) object).getThread() == null) {
254 addMatching(results, sLocalPath, objects);
259 if (objects.length == 1) {
262 return new Object[] { objects[0] };
265 } catch (CoreException e) {
266 if (single == null) {
268 } else if (multiStatus == null) {
269 multiStatus = new MultiStatus(DebugPlugin
270 .getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR,
271 new IStatus[] { single.getStatus() },
272 SourceLookupMessages.DefaultSourceContainer_0,
274 multiStatus.add(e.getStatus());
276 multiStatus.add(e.getStatus());
280 if (results == null) {
281 if (multiStatus != null) {
282 throw new CoreException(multiStatus);
283 } else if (single != null) {
289 return results.toArray();
292 static void addMatching(List results, IPath localPath, Object[] objects) {
293 if (results == null || localPath == null || objects == null) {
296 for (int j = 0; j < objects.length; j++) {
297 if (objects[j] == null || !(objects[j] instanceof IFile)) {
300 IFile file = (IFile) objects[j];
302 IPath path = new Path(file.getLocation().toString());
303 if (localPath.matchingFirstSegments(path) == localPath
305 results.add(objects[j]);