1 package net.sourceforge.phpeclipse.xdebug.php.launching;
3 import java.util.ArrayList;
4 import java.util.Iterator;
8 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
9 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
10 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
12 import org.eclipse.core.resources.IFile;
13 import org.eclipse.core.resources.IProject;
14 import org.eclipse.core.resources.IWorkspaceRoot;
15 import org.eclipse.core.runtime.CoreException;
16 import org.eclipse.core.runtime.IPath;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.MultiStatus;
19 import org.eclipse.core.runtime.Path;
20 import org.eclipse.debug.core.DebugPlugin;
21 import org.eclipse.debug.core.model.IStackFrame;
22 import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
23 import org.eclipse.debug.core.sourcelookup.ISourceContainer;
24 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages;
26 public class PHPSourceLookupParticipant extends AbstractSourceLookupParticipant {
28 private Map pathMap = null;
29 private boolean remoteDebug = true;
30 private IPath remoteSourcePath;
31 private String projectName;
34 * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#getSourceName(Object)
36 public String getSourceName(Object object) throws CoreException {
37 if (object instanceof XDebugStackFrame) {
38 return ((XDebugStackFrame) object).getFullSourceName();
44 * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
46 * Return the client side source filename for the server side source file.
47 * E.g. when cross debugging, the server side filename could be /var/www/index.php
48 * on the client side it is either a Eclipse_PHP_projectname\index.php (when it is a linked file)
51 * @param stackFrame The stackframe for which we want the client side source file name
52 * @return The filename as it appears on the client side
54 public Object getSourceElement (IStackFrame stackFrame) throws CoreException {
64 PathMapItem pmi = null;
66 projectName = getDirector().getLaunchConfiguration().getAttribute (IXDebugConstants.ATTR_PHP_PROJECT, "");
67 pathMap = getDirector().getLaunchConfiguration().getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
69 fileName = ((XDebugStackFrame) stackFrame).getFullSourceName (); // Get the filename as it is submitted by XDebug
72 if (remoteDebug) { // Is it a remote debugging session
73 path = new Path (fileName); // Create a IPath object for the server side filename
75 if (!remoteSourcePath.isEmpty()) {
76 if (remoteSourcePath.isPrefixOf (path)) { // Is the server side filename with the remote source path
77 path = path.removeFirstSegments (remoteSourcePath.matchingFirstSegments (path)); // Remove the remote source path
78 //file = path.toString (); // The filename without the remote source path
79 projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
81 return (projectPath.append (path)).toOSString (); // Return the filename as absolute client side path
86 if (pathMap == null) { // Do we have path mapping (e.g. for cross platform debugging)
87 return fileName; // No, then return the filename as it given by DBG (the full server side path)
92 for (int k = 0; k < pathMap.size(); k++) {
93 pmi = new PathMapItem ((String) pathMap.get(k));
95 local = pmi.getLocalPath ().toString(); //
96 localPath = new Path (pmi.getLocalPath().toString()); // Get the local/client side path of the mapping
97 remotePath = new Path (pmi.getRemotePath().toString()); // Get the remote/server side path of the mapping
99 if (remotePath.isPrefixOf (path)) { // Starts the remote/server side file path with the remote/server side mapping path
100 path = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
102 return path.toString ();
104 localPath = new Path (local); // Create new IPath object for the local/client side path
105 path = localPath.append (path); // Prepend the project relative path to filename
107 projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
110 return (projectPath.append (path)).toString (); // Return the filename as absolute client side path
116 if (pathMap == null) { // Do we have path mapping (e.g. for cross platform debugging)
117 return fileName; // No, then return the filename as it given by DBG (the full server side path)
122 for (int k = 0; k < pathMap.size(); k++) {
123 pmi = new PathMapItem((String) pathMap.get(k));
125 local = pmi.getLocalPath().toString(); // Get the local/client side path of the mapping
126 localPath = new Path (pmi.getLocalPath().toString()); // Get the local/client side path of the mapping
127 remotePath = new Path (pmi.getRemotePath().toString()); // Get the remote/server side path of the mapping
129 if (remotePath.isPrefixOf (path)) { // Starts the remote/server side file path with the remote/server side mapping path
130 path = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
131 localPath = new Path (local); // Create new IPath object for the local/client side path
133 return localPath.append (path).toOSString (); // Append the remote filename to the client side path (So we return the absolute path
134 // to the source file as the client side sees it.
140 } else { // no remote debug
142 IWorkspaceRoot root = PHPLaunchingPlugin.getWorkspace().getRoot();
143 Path filePath = new Path(fileName);
145 if (root.getFileForLocation(filePath) == null) {
146 IProject proj = root.getProject(projectName);
147 IFile[] files = root.findFilesForLocation(filePath);
148 for (int i = 0; i < files.length; i++) {
149 if (files[i].getProject().equals(proj)) {
150 fileName = proj.getFullPath().append(files[i].getProjectRelativePath()).toOSString();
161 * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#findSourceElements(java.lang.Object)
163 public Object[] findSourceElements(Object object) throws CoreException {
166 if (object == null) {
167 return new Object[] {};
169 XDebugStackFrame stackFrame = null;
170 if (object instanceof XDebugStackFrame) {
171 stackFrame = (XDebugStackFrame) object;
173 return new Object[] {};
177 CoreException single = null;
178 MultiStatus multiStatus = null;
180 if (isFindDuplicates()) {
181 results = new ArrayList();
185 name = (String) getSourceElement (stackFrame);
187 catch (CoreException e) {
190 if (name == null || name.length() == 0) {
191 return new Object[] {};
194 // here our stackframe is guaranteed not to be null
195 IPath sLocalPath = null;
197 if (((XDebugStackFrame) object).getThread() == null) {
198 IPath sPath = new Path(stackFrame.getFullName().getPath());
199 List pathMap = getDirector().getLaunchConfiguration()
200 .getAttribute(IXDebugConstants.ATTR_PHP_PATHMAP, (List) null);
202 PathMapItem pmi = null;
203 for (int k = 0; k < pathMap.size(); k++) {
204 pmi = new PathMapItem((String) pathMap.get(k));
206 IPath local = new Path(pmi.getLocalPath().toString());
207 IPath remote = new Path(pmi.getRemotePath().toString());
209 if (remote.matchingFirstSegments(sPath) == remote.segmentCount()) {
217 String Type = stackFrame.getType();
219 if (Type.equals("eval")) {
220 results.add("pippo");
221 return results.toArray();
224 ISourceContainer[] containers = getSourceContainers();
225 for (int i = 0; i < containers.length; i++) {
226 ISourceContainer container = getDelegateContainer(containers[i]);
227 if (container == null) {
232 Object[] objects = container.findSourceElements(name);
233 if (objects.length > 0) {
234 if (isFindDuplicates()) {
235 if (((XDebugStackFrame) object).getThread() == null) {
236 addMatching(results, sLocalPath, objects);
241 if (objects.length == 1) {
244 return new Object[] { objects[0] };
247 } catch (CoreException e) {
248 if (single == null) {
250 } else if (multiStatus == null) {
251 multiStatus = new MultiStatus(DebugPlugin
252 .getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR,
253 new IStatus[] { single.getStatus() },
254 SourceLookupMessages.DefaultSourceContainer_0,
256 multiStatus.add(e.getStatus());
258 multiStatus.add(e.getStatus());
262 if (results == null) {
263 if (multiStatus != null) {
264 throw new CoreException(multiStatus);
265 } else if (single != null) {
271 return results.toArray();
274 static void addMatching(List results, IPath localPath, Object[] objects) {
275 if (results == null || localPath == null || objects == null) {
278 for (int j = 0; j < objects.length; j++) {
279 if (objects[j] == null || !(objects[j] instanceof IFile)) {
282 IFile file = (IFile) objects[j];
284 IPath path = new Path(file.getLocation().toString());
285 if (localPath.matchingFirstSegments(path) == localPath
287 results.add(objects[j]);