1) Made breakpoint working for direct script debugging (php cli) on Win systems.
[phpeclipse.git] / net.sourceforge.phpeclipse.xdebug.core / src / net / sourceforge / phpeclipse / xdebug / php / launching / PHPSourceLookupParticipant.java
1 package net.sourceforge.phpeclipse.xdebug.php.launching;
2
3 import java.net.URI;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Map;
8
9 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
10 import net.sourceforge.phpeclipse.xdebug.core.PathMapItem;
11 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
12
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;
28
29 public class PHPSourceLookupParticipant extends AbstractSourceLookupParticipant {
30
31         private Map             pathMap         = null;
32         private boolean         remoteDebug = true;
33         private IPath           remoteSourcePath;
34         private String          projectName;
35
36         /* (non-Javadoc)
37          * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#getSourceName(Object)
38          */
39         public String getSourceName(Object object) throws CoreException {
40                 if (object instanceof XDebugStackFrame) {
41                         return ((XDebugStackFrame) object).getFullSourceName();
42                 }
43                 return null;
44         }
45
46           /**
47            * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
48            *
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)
52            *
53            *
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
56            */
57           public Object getSourceElement (IStackFrame stackFrame) throws CoreException {
58                 IPath           projectPath;
59                 IPath           remotePath;
60                 IPath           path;
61                 IPath           localPath;
62                 Iterator        iterator;
63                 String          fileName;
64                 //String   file;
65                 String          local;
66                 List            pathMap;
67                 PathMapItem pmi = null;
68                 Object      test;
69                 IProject    project;
70
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);
74                 
75                 if (getDirector ().getLaunchConfiguration ().getType ().getName ().equals ("PHP XDebug Script")) {
76                     remoteDebug = false;
77                 }
78                 else {
79                     remoteDebug = true;
80                 }
81                 
82                 fileName = ((XDebugStackFrame) stackFrame).getFullSourceName ();        // Get the filename as it is submitted by XDebug
83
84             if (remoteDebug) {                                                  // Is it a remote debugging session
85                         path = new Path (fileName);                                     // Create a IPath object for the server side filename
86 /*
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
92
93                                         return (projectPath.append (path)).toOSString ();       // Return the filename as absolute client side path
94                                 }
95                         }
96                         else {
97 */
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)
100                                 }
101
102                                 pmi = null;
103
104                                 for (int k = 0; k < pathMap.size(); k++) {
105                                         pmi = new PathMapItem ((String) pathMap.get(k));
106
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
110
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
113
114                                                 return path.toString ();
115 /*
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
118
119                                                 projectPath = (ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
120
121 //                                              return path;
122                                                 return (projectPath.append (path)).toString ();   // Return the filename as absolute client side path
123 */
124                                         }
125                                 }
126 //                      }
127
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)
130                         }
131
132                         pmi = null;
133
134                         for (int k = 0; k < pathMap.size(); k++) {
135                                 pmi = new PathMapItem((String) pathMap.get(k));
136
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
140
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
144
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.
147                                 }
148                         }
149
150                         return fileName;
151
152             } else { // no remote debug
153                 IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
154                 IPath filePath = new Path(fileName);
155                 
156                 if (root.getFileForLocation(filePath) == null) {
157                                 IProject proj = root.getProject (projectName);
158                                 IFile[] files = root.findFilesForLocation (filePath);
159                                 
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();
163                                                 break;
164                                         }
165                                 }
166                         }
167                 else {
168                     projectPath = (ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getLocation());
169                     filePath    = filePath.removeFirstSegments (projectPath.matchingFirstSegments (filePath));
170                     
171                     return filePath.toString ();
172                 }
173                 
174                         return fileName;
175             }
176           }
177
178         /* (non-Javadoc)
179          * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant#findSourceElements(java.lang.Object)
180          */
181         public Object[] findSourceElements (Object object) throws CoreException {
182                 String name = null;
183
184                 if (object == null) {
185                         return new Object[] {};
186                 }
187                 XDebugStackFrame stackFrame = null;
188                 if (object instanceof XDebugStackFrame) {
189                         stackFrame = (XDebugStackFrame) object;
190                 } else {
191                         return new Object[] {};
192                 }
193
194                 List results = null;
195                 CoreException single = null;
196                 MultiStatus multiStatus = null;
197
198                 if (isFindDuplicates()) {
199                         results = new ArrayList();
200                 }
201
202                 try {
203                     name = (String) getSourceElement (stackFrame);
204                 }
205                 catch (CoreException e) {
206                 }
207
208                 if (name == null || name.length() == 0) {
209                         return new Object[] {};
210                 }
211
212                 // here our stackframe is guaranteed not to be null
213                 IPath sLocalPath = null;
214
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);
219
220                         PathMapItem pmi = null;
221                         for (int k = 0; k < pathMap.size(); k++) {
222                                 pmi = new PathMapItem((String) pathMap.get(k));
223
224                                 IPath local = new Path(pmi.getLocalPath().toString());
225                                 IPath remote = new Path(pmi.getRemotePath().toString());
226
227                                 if (remote.matchingFirstSegments(sPath) == remote.segmentCount()) {
228                                         sLocalPath = local;
229                                 }
230                         }
231                 } else {
232
233                 }
234
235                 String Type = stackFrame.getType();
236
237                 if (Type.equals("eval")) {
238                         results.add("pippo");
239                         return results.toArray();
240                 }
241
242                 ISourceContainer[] containers = getSourceContainers();
243                 for (int i = 0; i < containers.length; i++) {
244                         ISourceContainer container = getDelegateContainer(containers[i]);
245                         if (container == null) {
246                                 continue;
247                         }
248
249                         try {
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);
255                                                 } else {
256                                                         return objects;
257                                                 }
258                                         } else {
259                                                 if (objects.length == 1) {
260                                                         return objects;
261                                                 }
262                                                 return new Object[] { objects[0] };
263                                         }
264                                 }
265                         } catch (CoreException e) {
266                                 if (single == null) {
267                                         single = e;
268                                 } else if (multiStatus == null) {
269                                         multiStatus = new MultiStatus(DebugPlugin
270                                                         .getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR,
271                                                         new IStatus[] { single.getStatus() },
272                                                         SourceLookupMessages.DefaultSourceContainer_0,
273                                                         null);
274                                         multiStatus.add(e.getStatus());
275                                 } else {
276                                         multiStatus.add(e.getStatus());
277                                 }
278                         }
279                 }
280                 if (results == null) {
281                         if (multiStatus != null) {
282                                 throw new CoreException(multiStatus);
283                         } else if (single != null) {
284                                 throw single;
285                         }
286                         return EMPTY;
287                 }
288
289                 return results.toArray();
290         }
291
292         static void addMatching(List results, IPath localPath, Object[] objects) {
293                 if (results == null || localPath == null || objects == null) {
294                         return;
295                 }
296                 for (int j = 0; j < objects.length; j++) {
297                         if (objects[j] == null || !(objects[j] instanceof IFile)) {
298                                 continue;
299                         }
300                         IFile file = (IFile) objects[j];
301
302                         IPath path = new Path(file.getLocation().toString());
303                         if (localPath.matchingFirstSegments(path) == localPath
304                                         .segmentCount()) {
305                                 results.add(objects[j]);
306                         }
307                 }
308         }
309 }