|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 package org.chromium.debug.core.util; |
|
6 |
|
7 import java.io.ByteArrayInputStream; |
|
8 import java.io.File; |
|
9 import java.net.URI; |
|
10 |
|
11 import org.chromium.debug.core.ChromiumDebugPlugin; |
|
12 import org.chromium.debug.core.efs.ChromiumScriptFileSystem; |
|
13 import org.eclipse.core.filesystem.EFS; |
|
14 import org.eclipse.core.filesystem.IFileStore; |
|
15 import org.eclipse.core.resources.IContainer; |
|
16 import org.eclipse.core.resources.IFile; |
|
17 import org.eclipse.core.resources.IProject; |
|
18 import org.eclipse.core.resources.IProjectDescription; |
|
19 import org.eclipse.core.resources.IWorkspace; |
|
20 import org.eclipse.core.resources.ResourceAttributes; |
|
21 import org.eclipse.core.resources.ResourcesPlugin; |
|
22 import org.eclipse.core.runtime.CoreException; |
|
23 import org.eclipse.core.runtime.IProgressMonitor; |
|
24 import org.eclipse.core.runtime.IStatus; |
|
25 import org.eclipse.core.runtime.Path; |
|
26 import org.eclipse.core.runtime.Status; |
|
27 import org.eclipse.core.runtime.jobs.Job; |
|
28 import org.eclipse.swt.widgets.Display; |
|
29 import org.eclipse.ui.IWorkbench; |
|
30 import org.eclipse.ui.IWorkbenchWindow; |
|
31 import org.eclipse.ui.PartInitException; |
|
32 import org.eclipse.ui.PlatformUI; |
|
33 |
|
34 /** |
|
35 * A utility for interaction with the Eclipse workspace. |
|
36 */ |
|
37 public class ChromiumDebugPluginUtil { |
|
38 |
|
39 public static final String CHROMIUM_EXTENSION = "chromium"; //$NON-NLS-1$ |
|
40 |
|
41 public static final String JS_DEBUG_PROJECT_NATURE = "org.chromium.debug.core.jsnature"; //$NON-NLS-1$ |
|
42 |
|
43 public static final String CHROMIUM_EXTENSION_SUFFIX = "." + CHROMIUM_EXTENSION; //$NON-NLS-1$ |
|
44 |
|
45 private static final String PROJECT_EXPLORER_ID = "org.eclipse.ui.navigator.ProjectExplorer"; //$NON-NLS-1$ |
|
46 |
|
47 /** |
|
48 * Brings up the "Project Explorer" view in the active workbench window. |
|
49 */ |
|
50 public static void openProjectExplorerView() { |
|
51 Display.getDefault().asyncExec(new Runnable() { |
|
52 public void run() { |
|
53 IWorkbench workbench = PlatformUI.getWorkbench(); |
|
54 IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); |
|
55 if (window == null) { |
|
56 if (workbench.getWorkbenchWindowCount() == 1) { |
|
57 window = workbench.getWorkbenchWindows()[0]; |
|
58 } |
|
59 } |
|
60 if (window != null) { |
|
61 try { |
|
62 window.getActivePage().showView(PROJECT_EXPLORER_ID); |
|
63 } catch (PartInitException e) { |
|
64 // ignore |
|
65 } |
|
66 } |
|
67 } |
|
68 }); |
|
69 } |
|
70 |
|
71 /** |
|
72 * Creates an empty workspace project with the name starting with the given projectNameBase. |
|
73 * Created project is guaranteed to be new in EFS, but workspace may happen to |
|
74 * alreay have project with such url (left uncleaned from previous runs). Such project |
|
75 * silently gets deleted. |
|
76 * @param projectNameBase project name template |
|
77 * @return the newly created project, or {@code null} if the creation failed |
|
78 */ |
|
79 public static IProject createEmptyProject(String projectNameBase) { |
|
80 URI projectUri; |
|
81 String projectName; |
|
82 try { |
|
83 for (int uniqueNumber = 0; ; uniqueNumber++) { |
|
84 String projectNameTry; |
|
85 if (uniqueNumber == 0) { |
|
86 projectNameTry = projectNameBase; |
|
87 } else { |
|
88 projectNameTry = projectNameBase + " (" + uniqueNumber + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
|
89 } |
|
90 URI projectUriTry = ChromiumScriptFileSystem.getFileStoreUri( |
|
91 new Path(null, "/" + projectNameTry)); //$NON-NLS-1$ |
|
92 IFileStore projectStore = EFS.getStore(projectUriTry); |
|
93 if (projectStore.fetchInfo().exists()) { |
|
94 continue; |
|
95 } else { |
|
96 projectUri = projectUriTry; |
|
97 projectName = projectNameTry; |
|
98 break; |
|
99 } |
|
100 } |
|
101 } catch (CoreException e) { |
|
102 ChromiumDebugPlugin.log(e); |
|
103 return null; |
|
104 } |
|
105 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); |
|
106 IProjectDescription description = |
|
107 ResourcesPlugin.getWorkspace().newProjectDescription(projectName); |
|
108 description.setLocationURI(projectUri); |
|
109 description.setNatureIds(new String[] { JS_DEBUG_PROJECT_NATURE }); |
|
110 try { |
|
111 if (project.exists()) { |
|
112 project.delete(true, null); |
|
113 } |
|
114 |
|
115 project.create(description, null); |
|
116 project.open(null); |
|
117 |
|
118 return project; |
|
119 } catch (CoreException e) { |
|
120 ChromiumDebugPlugin.log(e); |
|
121 } |
|
122 |
|
123 return null; |
|
124 } |
|
125 |
|
126 |
|
127 /** |
|
128 * Removes virtual project which was created for debug session. Does its job |
|
129 * asynchronously. |
|
130 */ |
|
131 public static void deleteVirtualProjectAsync(final IProject debugProject) { |
|
132 Job job = new Job("Remove virtual project") { |
|
133 @Override |
|
134 protected IStatus run(IProgressMonitor monitor) { |
|
135 URI projectUri = debugProject.getLocationURI(); |
|
136 try { |
|
137 IFileStore projectStore = EFS.getStore(projectUri); |
|
138 if (projectStore.fetchInfo().exists()) { |
|
139 projectStore.delete(EFS.NONE, null); |
|
140 } |
|
141 debugProject.delete(true, null); |
|
142 } catch (CoreException e) { |
|
143 ChromiumDebugPlugin.log(e); |
|
144 return new Status(IStatus.ERROR, ChromiumDebugPlugin.PLUGIN_ID, |
|
145 "Failed to delete virtual project"); |
|
146 } |
|
147 return Status.OK_STATUS; |
|
148 } |
|
149 }; |
|
150 |
|
151 job.schedule(); |
|
152 } |
|
153 |
|
154 /** |
|
155 * @param projectName to check for existence |
|
156 * @return whether the project named projectName exists. |
|
157 */ |
|
158 public static boolean projectExists(String projectName) { |
|
159 IWorkspace ws = ResourcesPlugin.getWorkspace(); |
|
160 IProject proj = ws.getRoot().getProject(projectName); |
|
161 return proj.exists(); |
|
162 } |
|
163 |
|
164 /** |
|
165 * Creates an empty file with the given filename in the given project. |
|
166 * |
|
167 * @param project to create the file in |
|
168 * @param filename the base file name to create (will be sanitized for |
|
169 * illegal chars and, in the case of a name clash, suffixed with "(N)") |
|
170 * @return the result of IFile.getName(), or {@code null} if the creation |
|
171 * has failed |
|
172 */ |
|
173 public static IFile createFile(IProject project, String filename) { |
|
174 String patchedName = new File(filename).getName().replace('?', '_'); // simple name |
|
175 String uniqueName = patchedName; |
|
176 |
|
177 // TODO(apavlov): refactor this? |
|
178 for (int i = 1; i < 1000; ++i) { |
|
179 String filePathname = uniqueName + CHROMIUM_EXTENSION_SUFFIX; |
|
180 IFile file = project.getFile(filePathname); |
|
181 |
|
182 if (file.exists()) { |
|
183 uniqueName = new StringBuilder(patchedName) |
|
184 .append(" (") //$NON-NLS-1$ |
|
185 .append(i) |
|
186 .append(')') |
|
187 .toString(); |
|
188 } else { |
|
189 try { |
|
190 file.create(new ByteArrayInputStream("".getBytes()), false, null); //$NON-NLS-1$ |
|
191 } catch (CoreException e) { |
|
192 ChromiumDebugPlugin.log(e); |
|
193 return null; |
|
194 } |
|
195 return file; |
|
196 } |
|
197 } |
|
198 |
|
199 // Can we have 1000 same-named files? |
|
200 return null; |
|
201 } |
|
202 |
|
203 /** |
|
204 * Writes data into a resource with the given resourceName residing in the |
|
205 * source folder of the given project. The previous file content is lost. |
|
206 * Temporarily resets the "read-only" file attribute if one is present. |
|
207 * |
|
208 * @param file to set contents for |
|
209 * @param data to write into the file |
|
210 * @throws CoreException |
|
211 */ |
|
212 public static void writeFile(IFile file, String data) throws CoreException { |
|
213 if (file != null && file.exists()) { |
|
214 ResourceAttributes resourceAttributes = file.getResourceAttributes(); |
|
215 if (resourceAttributes.isReadOnly()) { |
|
216 resourceAttributes.setReadOnly(false); |
|
217 file.setResourceAttributes(resourceAttributes); |
|
218 } |
|
219 file.setContents(new ByteArrayInputStream(data.getBytes()), IFile.FORCE, null); |
|
220 resourceAttributes.setReadOnly(true); |
|
221 file.setResourceAttributes(resourceAttributes); |
|
222 } |
|
223 } |
|
224 |
|
225 public static boolean isInteger(String value) { |
|
226 try { |
|
227 Integer.parseInt(value); |
|
228 return true; |
|
229 } catch (NumberFormatException e) { |
|
230 return false; |
|
231 } |
|
232 } |
|
233 |
|
234 /** |
|
235 * The container where the script sources should be put. |
|
236 * |
|
237 * @param project where the launch configuration stores the scripts |
|
238 * @return the script source container |
|
239 */ |
|
240 public static IContainer getSourceContainer(IProject project) { |
|
241 return project; |
|
242 } |
|
243 |
|
244 private ChromiumDebugPluginUtil() { |
|
245 // not instantiable |
|
246 } |
|
247 } |