New Xdebug configuration manual. contributed by Ian MacLennan .
[phpeclipse.git] / net.sourceforge.phpeclipse.launching / src / net / sourceforge / phpdt / internal / launching / PHPSourceLocator.java
1 package net.sourceforge.phpdt.internal.launching;
2
3 import java.util.Iterator;
4 import java.util.Map;
5
6 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
7 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
8 import net.sourceforge.phpeclipse.builder.ExternalEditorInput;
9 import net.sourceforge.phpeclipse.builder.FileStorage;
10
11 import org.eclipse.core.resources.IFile;
12 import org.eclipse.core.resources.IProject;
13 import org.eclipse.core.resources.IWorkspaceRoot;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IPath;
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Path;
18 import org.eclipse.debug.core.ILaunchConfiguration;
19 import org.eclipse.debug.core.model.IPersistableSourceLocator;
20 import org.eclipse.debug.core.model.IStackFrame;
21 import org.eclipse.debug.ui.ISourcePresentation;
22 import org.eclipse.ui.IEditorInput;
23 import org.eclipse.ui.IWorkbench;
24 import org.eclipse.ui.IWorkbenchPage;
25 import org.eclipse.ui.IWorkbenchWindow;
26 import org.eclipse.ui.PlatformUI;
27 import org.eclipse.ui.part.FileEditorInput;
28
29 public class PHPSourceLocator implements IPersistableSourceLocator, ISourcePresentation {
30         private String          absoluteWorkingDirectory;
31         private Map             pathMap = null;
32         private boolean         remoteDebug;
33         private IPath           remoteSourcePath;
34         private String          projectName;
35
36   public PHPSourceLocator() {
37
38   }
39
40   public String getAbsoluteWorkingDirectory() {
41     return absoluteWorkingDirectory;
42   }
43
44   /**
45    * @see org.eclipse.debug.core.model.IPersistableSourceLocator#getMemento()
46    */
47   public String getMemento() throws CoreException {
48     return null;
49   }
50
51   /**
52    * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeFromMemento(String)
53    */
54   public void initializeFromMemento(String memento) throws CoreException {
55   }
56
57   /**
58    * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeDefaults(ILaunchConfiguration)
59    */
60   public void initializeDefaults (ILaunchConfiguration configuration) throws CoreException {
61     this.absoluteWorkingDirectory = configuration.getAttribute (PHPLaunchConfigurationAttribute.WORKING_DIRECTORY, "");
62         this.remoteDebug              = configuration.getAttribute (PHPLaunchConfigurationAttribute.REMOTE_DEBUG,false);
63         this.pathMap                  = configuration.getAttribute (PHPLaunchConfigurationAttribute.FILE_MAP, (Map)null);
64         this.projectName              = configuration.getAttribute (PHPLaunchConfigurationAttribute.PROJECT_NAME, "");
65
66         this.remoteSourcePath = new Path (configuration.getAttribute (PHPLaunchConfigurationAttribute.REMOTE_PATH, ""));
67   }
68
69   /**
70    * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
71    *
72    * Return the client side source filename for the server side source file.
73    * E.g. when cross debugging, the server side filename could be /var/www/index.php
74    * on the client side it is either a Eclipse_PHP_projectname\index.php (when it is a linked file)
75    *
76    *
77    * @param stackFrame    The stackframe for which we want the client side source file name
78    * @return              The filename as it appears on the client side
79    */
80   public Object getSourceElement (IStackFrame stackFrame) {
81         IPath    projectPath;
82         IPath    remotePath;
83         IPath    path;
84         IPath    localPath;
85         Iterator iterator;
86         String   fileName;
87         String   file;
88         String   local;
89
90         fileName = ((PHPStackFrame) stackFrame).getFileName ();                 // Get the filename as it is submitted by DBG
91         file     = "";
92
93     if (remoteDebug) {                                              // Is it a remote debugging session
94                 path = new Path (fileName);                                 // Create a IPath object for the server side filename
95
96                 if (!remoteSourcePath.isEmpty()) {
97                         if (remoteSourcePath.isPrefixOf (path)) {                   // Is the server side filename with the remote source path
98                                 path        = path.removeFirstSegments (remoteSourcePath.matchingFirstSegments (path)); // Remove the remote source path
99                                 file        = path.toString ();                         // The filename without the remote source path
100                                 projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
101
102                                 return (projectPath.append (path)).toOSString ();       // Return the filename as absolute client side path
103                         }
104                 }
105                 else {
106                         if (pathMap == null) {                                      // Do we have path mapping (e.g. for cross platform debugging)
107                                 return fileName;                                        // No, then return the filename as it given by DBG (the full server side path)
108                         }
109
110                         iterator = pathMap.keySet().iterator();
111
112                         while (iterator.hasNext ()) {
113                                 local      = (String) iterator.next ();                 // Get the local/client side path of the mapping
114                                 remotePath = new Path ((String) pathMap.get (local));   // Get the remote/server side path of the mapping
115
116                                 if (remotePath.isPrefixOf (path)) {                     // Starts the remote/server side file path with the remote/server side mapping path
117                                         path      = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
118                                         localPath = new Path (local);                       // Create new IPath object for the local/client side path
119                                         path      = localPath.append (path);                // Prepend the project relative path to filename
120
121                                         projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
122
123                                         return (projectPath.append (path)).toOSString ();       // Return the filename as absolute client side path
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                 iterator = pathMap.keySet().iterator();
133
134                 while (iterator.hasNext ()) {
135                         local      = (String) iterator.next ();                 // Get the local/client side path of the mapping
136                         remotePath = new Path ((String) pathMap.get (local));   // Get the remote/server side path of the mapping
137
138                         if (remotePath.isPrefixOf (path)) {                     // Starts the remote/server side file path with the remote/server side mapping path
139                                 path      = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
140                                 localPath = new Path (local);                       // Create new IPath object for the local/client side path
141
142                                 return localPath.append (path).toOSString ();       // Append the remote filename to the client side path (So we return the absolute path
143                                                                                                                                         // to the source file as the client side sees it.
144                         }
145                 }
146
147                 return fileName;
148
149     } else {
150
151         IWorkspaceRoot root = PHPLaunchingPlugin.getWorkspace().getRoot();
152         Path filePath = new Path(fileName);
153
154         if (root.getFileForLocation(filePath) == null) {
155                         IProject proj = root.getProject(projectName);
156                         IFile[] files = root.findFilesForLocation(filePath);
157                         for (int i = 0; i < files.length; i++) {
158                                 if (files[i].getProject().equals(proj)) {
159                                         fileName = proj.getLocation().append(files[i].getProjectRelativePath()).toOSString();
160                                         break;
161                                 }
162                         }
163                 }
164
165                 return fileName;
166     }
167   }
168
169   /**
170    * @see org.eclipse.debug.ui.ISourcePresentation#getEditorId(IEditorInput, Object)
171    */
172   public String getEditorId(IEditorInput input, Object element) {
173     return PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor((String) element).getId();
174   }
175
176   /**
177    * @see org.eclipse.debug.ui.ISourcePresentation#getEditorInput(Object)
178    *
179    * @param element The absolute local/client side file path
180    */
181   public IEditorInput getEditorInput (Object element) {
182         String           filename;
183         IWorkbench       workbench;
184         IWorkbenchWindow window;
185     IWorkbenchPage   page;
186         IPath            path;
187         IFile            eclipseFile;
188
189     filename  = (String) element;
190     workbench = PlatformUI.getWorkbench ();
191     window    = workbench.getWorkbenchWindows ()[0];
192     page      = window.getActivePage ();
193     path      = new Path (filename);                                // Create an IPath object of the absolute local/client side file name
194
195     // If the file exists in the workspace, open it
196     eclipseFile = PHPeclipsePlugin.getWorkspace().getRoot().getFileForLocation (path);
197
198     //    IFile eclipseFile = PHPeclipsePlugin.getWorkspace().getRoot().getFileForLocation(new Path(filename));
199 //    if (eclipseFile == null) {
200 //      filename = this.getAbsoluteWorkingDirectory() + "/" + filename;
201 //      eclipseFile = PHPeclipsePlugin.getWorkspace().getRoot().getFileForLocation(new Path(filename));
202 //      if (eclipseFile == null) {
203 //        PHPeclipsePlugin.log(IStatus.INFO, "Could not find file \"" + element + "\".");
204 //        return null;
205 //      }
206 //    } else
207
208     if (eclipseFile == null || !eclipseFile.exists ()) {
209       //                Otherwise open the stream directly
210           //
211       if (page == null) {
212         PHPeclipsePlugin.log(IStatus.INFO, "Could not find file \"" + element + "\".");
213         return null;
214       }
215
216       FileStorage storage = new FileStorage (path);
217       storage.setReadOnly ();
218
219       //      IEditorRegistry registry = workbench.getEditorRegistry();
220       //      IEditorDescriptor desc = registry.getDefaultEditor(filename);
221       //      if (desc == null) {
222       //        desc = registry.getDefaultEditor();
223       //      }
224       return new ExternalEditorInput(storage);
225     }
226
227     return new FileEditorInput (eclipseFile);
228   }
229 }