Lines 1-7
Link Here
|
1 |
/* |
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
3 |
* |
4 |
* Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. |
4 |
* Copyright 2011 Oracle and/or its affiliates. All rights reserved. |
5 |
* |
5 |
* |
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates. |
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates. |
7 |
* Other names may be trademarks of their respective owners. |
7 |
* Other names may be trademarks of their respective owners. |
Lines 24-34
Link Here
|
24 |
* your own identifying information: |
24 |
* your own identifying information: |
25 |
* "Portions Copyrighted [year] [name of copyright owner]" |
25 |
* "Portions Copyrighted [year] [name of copyright owner]" |
26 |
* |
26 |
* |
27 |
* Contributor(s): |
|
|
28 |
* The Original Software is NetBeans. The Initial Developer of the Original |
29 |
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun |
30 |
* Microsystems, Inc. All Rights Reserved. |
31 |
* |
32 |
* If you wish your version of this file to be governed by only the CDDL |
27 |
* If you wish your version of this file to be governed by only the CDDL |
33 |
* or only the GPL Version 2, indicate your decision by adding |
28 |
* or only the GPL Version 2, indicate your decision by adding |
34 |
* "[Contributor] elects to include this software in this distribution |
29 |
* "[Contributor] elects to include this software in this distribution |
Lines 39-810
Link Here
|
39 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
34 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
40 |
* Version 2 license, then the option applies only if the new code is |
35 |
* Version 2 license, then the option applies only if the new code is |
41 |
* made subject to such option by the copyright holder. |
36 |
* made subject to such option by the copyright holder. |
|
|
37 |
* |
38 |
* Contributor(s): |
39 |
* |
40 |
* Portions Copyrighted 2011 Sun Microsystems, Inc. |
42 |
*/ |
41 |
*/ |
43 |
|
|
|
44 |
package org.netbeans.modules.profiler.nbimpl.actions; |
42 |
package org.netbeans.modules.profiler.nbimpl.actions; |
45 |
|
43 |
|
|
|
44 |
import javax.swing.Action; |
46 |
import org.netbeans.api.project.Project; |
45 |
import org.netbeans.api.project.Project; |
47 |
import org.netbeans.api.project.ProjectUtils; |
|
|
48 |
import org.netbeans.api.project.ui.OpenProjects; |
49 |
import org.netbeans.lib.profiler.ProfilerLogger; |
46 |
import org.netbeans.lib.profiler.ProfilerLogger; |
50 |
import org.netbeans.lib.profiler.common.Profiler; |
|
|
51 |
import org.netbeans.lib.profiler.common.ProfilingSettings; |
52 |
import org.netbeans.lib.profiler.common.SessionSettings; |
53 |
import org.netbeans.lib.profiler.global.CommonConstants; |
54 |
import org.netbeans.lib.profiler.utils.MiscUtils; |
55 |
import org.netbeans.modules.profiler.NetBeansProfiler; |
47 |
import org.netbeans.modules.profiler.NetBeansProfiler; |
56 |
import org.netbeans.modules.profiler.api.ProfilerIDESettings; |
48 |
|
57 |
import org.netbeans.modules.profiler.utils.IDEUtils; |
49 |
import org.netbeans.modules.profiler.api.icons.Icons; |
|
|
50 |
import org.netbeans.modules.profiler.api.icons.ProfilerIcons; |
51 |
import org.netbeans.modules.profiler.api.project.ProjectProfilingSupport; |
52 |
import org.netbeans.spi.project.ActionProvider; |
53 |
import org.netbeans.spi.project.ui.support.FileSensitiveActions; |
58 |
import org.netbeans.spi.project.ui.support.MainProjectSensitiveActions; |
54 |
import org.netbeans.spi.project.ui.support.MainProjectSensitiveActions; |
59 |
import org.netbeans.spi.project.ui.support.ProjectActionPerformer; |
55 |
import org.netbeans.spi.project.ui.support.ProjectActionPerformer; |
60 |
import org.openide.ErrorManager; |
56 |
import org.netbeans.spi.project.ui.support.ProjectSensitiveActions; |
61 |
import org.openide.filesystems.FileObject; |
57 |
import org.openide.awt.ActionID; |
62 |
import org.openide.filesystems.FileUtil; |
58 |
import org.openide.awt.ActionReference; |
63 |
import org.openide.util.Lookup; |
59 |
import org.openide.awt.ActionReferences; |
|
|
60 |
import org.openide.awt.ActionRegistration; |
64 |
import org.openide.util.NbBundle; |
61 |
import org.openide.util.NbBundle; |
65 |
import org.openide.util.RequestProcessor; |
62 |
import org.openide.util.NbBundle.Messages; |
66 |
import java.io.IOException; |
|
|
67 |
import java.text.MessageFormat; |
68 |
import java.util.Properties; |
69 |
import javax.swing.Action; |
70 |
import org.netbeans.api.java.source.ui.ScanDialog; |
71 |
import org.netbeans.lib.profiler.common.CommonUtils; |
72 |
import org.netbeans.lib.profiler.global.Platform; |
73 |
import org.netbeans.modules.profiler.HeapDumpWatch; |
74 |
import org.netbeans.modules.profiler.actions.JavaPlatformSelector; |
75 |
import org.netbeans.modules.profiler.actions.ProfilingSupport; |
76 |
import org.netbeans.modules.profiler.api.icons.Icons; |
77 |
import org.netbeans.modules.profiler.api.JavaPlatform; |
78 |
import org.netbeans.modules.profiler.api.java.JavaProfilerSource; |
79 |
import org.netbeans.modules.profiler.api.ProfilerDialogs; |
80 |
import org.netbeans.modules.profiler.api.icons.ProfilerIcons; |
81 |
import org.netbeans.modules.profiler.api.project.ProjectStorage; |
82 |
import org.netbeans.modules.profiler.api.project.AntProjectSupport; |
83 |
import org.netbeans.modules.profiler.api.project.ProjectProfilingSupport; |
84 |
import org.netbeans.modules.profiler.projectsupport.utilities.ProjectUtilities; |
85 |
|
86 |
|
63 |
|
87 |
/** |
64 |
/** |
88 |
* 4.0 Ant-style actions |
|
|
89 |
* |
65 |
* |
90 |
* @author Tomas Hurka |
66 |
* @author Jaroslav Bachorik <jaroslav.bachorik@oracle.com> |
91 |
* @author Ian Formanek |
|
|
92 |
*/ |
67 |
*/ |
93 |
@NbBundle.Messages({ |
68 |
public class AntActions { |
94 |
"AntActions_FileTestNotFoundMsg=Test for the file does not exist.", |
69 |
@ActionID(category="Profile", id="org.netbeans.modules.profiler.actions.ProfileMainProject") |
95 |
"AntActions_FailedDetermineJavaPlatformMsg=Failed to determine version of Java platform: {0}", |
70 |
@ActionRegistration(displayName="Profile Main Project", lazy=false) |
96 |
"AntActions_FailedDetermineProjectBuildScriptMsg=Cannot determine build script for project {0}", |
71 |
@ActionReferences({ |
97 |
"AntActions_IncorrectJavaSpecVersionDialogCaption=Warning", |
72 |
@ActionReference(path="Menu/Profile", position=100), |
98 |
"AntActions_IncorrectJavaSpecVersionDialogMsg=The specification version of project Java Platform is greater than specification version of the\nplatform that will be used for profiling. You may experience problems unless you set the compiler\nparameter to generate bytecode compatible with the platform that will be used.\n\nDo you want to continue with the current settings?", |
73 |
@ActionReference(path="Shortcuts", name="A-F2") |
99 |
"AntActions_UnsupportedProjectTypeMsg=Profiling this project type is not supported.", |
74 |
}) |
100 |
"AntActions_InvalidJavaplatformMsg=Failed to determine overridden platform: {0}", |
75 |
public static Action profileMainProjectAction() { |
101 |
"AntActions_InvalidPlatformProjectMsg=The Java platform defined for the project is invalid. Right-click the project\nand choose a different platform using Properties | Libraries | Java Platform.\n\nInvalid platform: {0}", |
76 |
final Action delegate = MainProjectSensitiveActions.mainProjectSensitiveAction( |
102 |
"AntActions_InvalidPlatformProfilerMsg=The Java platform defined for profiling is invalid. Choose a different platform\nin Tools | Options | Miscellaneous | Profiler | Profiler Java Platform.\n\nInvalid platform: {0}", |
77 |
new ProjectSensitivePerformer(ActionProvider.COMMAND_PROFILE), |
103 |
"AntActions_LazyEnablementFailure=<html><b>Unable to start profiling.</b><br><br>Please, make sure the project type is supported</p><p>and/or the selected file can be executed.", |
78 |
NbBundle.getMessage(AntActions.class, "LBL_ProfileMainProjectAction"), // NOI18N |
104 |
"AntActions_LazyEnablementProgressMessage=Validating profiler action" |
79 |
Icons.getIcon(ProfilerIcons.PROFILE) |
105 |
}) |
80 |
); |
106 |
public final class AntActions { |
81 |
delegate.putValue(Action.SHORT_DESCRIPTION, NbBundle.getMessage(AntActions.class, "HINT_ProfileMainProjectAction")); // NOI18N |
107 |
private static final String LINUX_THREAD_TIMER_KEY = "-XX:+UseLinuxPosixThreadCPUClocks"; // NOI18N |
82 |
|
108 |
//~ Constructors ------------------------------------------------------------------------------------------------------------- |
83 |
return delegate; |
109 |
|
|
|
110 |
/** Default constructor to avoid creating instances */ |
111 |
private AntActions() { |
112 |
} |
84 |
} |
113 |
|
85 |
|
114 |
//~ Methods ------------------------------------------------------------------------------------------------------------------ |
86 |
@ActionID(category="Profile", id="org.netbeans.modules.profiler.actions.ProfileProjectPopup") |
115 |
|
87 |
@ActionRegistration(displayName="Profile", lazy=false, asynchronous=true) |
116 |
/** |
88 |
@ActionReferences({ |
117 |
* @return An Action to invoke profiling of the main project in the IDE |
89 |
@ActionReference(path="Projects/org-netbeans-modules-java-j2seproject/Actions", position=1000), |
118 |
*/ |
90 |
@ActionReference(path="Projects/org-netbeans-modules-apisupport-project/Actions", position=900), |
119 |
public static Action profileMainProject() { |
91 |
@ActionReference(path="Projects/org-netbeans-modules-apisupport-project-suite/Actions", position=1000), |
120 |
final Action a = MainProjectSensitiveActions.mainProjectSensitiveAction(new ProjectActionPerformer() { |
92 |
@ActionReference(path="Projects/org-netbeans-modules-web-project/Actions", position=1000) |
121 |
public boolean enable(final Project project) { |
93 |
}) |
122 |
// Check if the Profiler is initialized correctly |
94 |
public static Action profileProjectPopup() { |
123 |
if (!NetBeansProfiler.isInitialized()) { |
95 |
Action delegate = ProjectSensitiveActions.projectSensitiveAction( |
124 |
return false; |
96 |
new ProjectSensitivePerformer(ActionProvider.COMMAND_PROFILE), |
125 |
} |
97 |
NbBundle.getMessage(AntActions.class, "LBL_ProfileProject"), // NOI18N |
126 |
|
98 |
null |
127 |
// No projects opened => disable action |
99 |
); |
128 |
if (OpenProjects.getDefault().getOpenProjects().length == 0) { |
100 |
|
129 |
return false; |
101 |
return delegate; |
130 |
} |
102 |
} |
131 |
|
103 |
|
132 |
// No main project set => enable action (see Issue 116619) |
104 |
@ActionID(category="Project", id="org.netbeans.modules.apisupport.project.suite.ProfileOsgi") |
133 |
if (project == null) { |
105 |
@ActionRegistration(displayName="#SUITE_ACTION_profile_osgi", asynchronous=true) |
134 |
return true; |
106 |
@ActionReference(path="Projects/org-netbeans-modules-apisupport-project-suite-osgi/Actions", position=500) |
135 |
} |
107 |
@NbBundle.Messages("SUITE_ACTION_profile_osgi=Profile in Felix") |
136 |
|
108 |
public static Action profileOsgi() { |
137 |
// Check if project type is supported, eventually return null |
109 |
Action delegate = ProjectSensitiveActions.projectSensitiveAction( |
138 |
return org.netbeans.modules.profiler.nbimpl.project.ProjectUtilities.isProjectTypeSupported(project); |
110 |
new ProjectSensitivePerformer("profile-osgi"), |
|
|
111 |
Bundle.SUITE_ACTION_profile_osgi(), |
112 |
null |
113 |
); |
114 |
|
115 |
return delegate; |
116 |
} |
117 |
|
118 |
@Messages("LBL_ProfileFile=Profile File") |
119 |
@ActionID(category="Profile", id="org.netbeans.modules.profiler.actions.ProfileSingle") |
120 |
@ActionRegistration(displayName="#LBL_ProfileFile", lazy=false) |
121 |
@ActionReferences({ |
122 |
@ActionReference(path="Loaders/text/x-java/Actions", position=1200), |
123 |
@ActionReference(path="Loaders/text/x-jsp/Actions", position=800), |
124 |
@ActionReference(path="Menu/Profile", position=110) |
125 |
}) |
126 |
public static Action profileSingle() { |
127 |
Action delegate = FileSensitiveActions.fileSensitiveAction( |
128 |
new FileSensitivePerformer(ActionProvider.COMMAND_PROFILE_SINGLE), |
129 |
Bundle.LBL_ProfileFile(), |
130 |
null); |
131 |
|
132 |
return delegate; |
133 |
} |
134 |
|
135 |
@Messages("LBL_ProfileTest=Profile Test File") |
136 |
@ActionID(category = "Profile", id = "org.netbeans.modules.profiler.actions.ProfileTest") |
137 |
@ActionRegistration(displayName = "#LBL_ProfileTest", lazy=false) |
138 |
@ActionReferences(value = { |
139 |
@ActionReference(path = "Loaders/text/x-java/Actions", position = 1280), |
140 |
@ActionReference(path = "Menu/Profile", position = 120)}) |
141 |
public static Action profileTest() { |
142 |
return FileSensitiveActions.fileSensitiveAction( |
143 |
new FileSensitivePerformer(ActionProvider.COMMAND_PROFILE_TEST_SINGLE), |
144 |
Bundle.LBL_ProfileTest(), |
145 |
null); |
146 |
} |
147 |
|
148 |
@ActionID(id = "org.netbeans.modules.profiler.nbimpl.actions.UnintegrateProfilerAction", category = "Profile") |
149 |
@ActionRegistration(displayName = "#LBL_UnintegrateProfilerAction", lazy=false) |
150 |
@ActionReference(path = "Menu/Profile/Advanced", position = 500) |
151 |
public static Action unintegrateProfiler() { |
152 |
final Action a = ProjectSensitiveActions.projectSensitiveAction(new ProjectActionPerformer() { |
153 |
@Override |
154 |
public boolean enable(Project project) { |
155 |
if (!NetBeansProfiler.isInitialized()) { |
156 |
return false; |
139 |
} |
157 |
} |
140 |
|
158 |
|
141 |
public void perform(final Project project) { |
159 |
if (project == null) { |
142 |
if (org.netbeans.modules.profiler.nbimpl.project.ProjectUtilities.isProjectTypeSupported(project)) { |
160 |
return false; |
143 |
doProfileProject(project, null, NbBundle.getMessage(AntActions.class, "LBL_ProfileProject")); |
|
|
144 |
} else { |
145 |
ProfilerDialogs.displayError(Bundle.AntActions_UnsupportedProjectTypeMsg()); |
146 |
} |
147 |
} |
148 |
}, NbBundle.getMessage(AntActions.class, "LBL_ProfileMainProjectAction"), // NOI18N |
149 |
null); |
150 |
a.putValue(Action.SHORT_DESCRIPTION, NbBundle.getMessage(AntActions.class, "HINT_ProfileMainProjectAction" // NOI18N |
151 |
)); |
152 |
a.putValue("iconBase", Icons.getResource(ProfilerIcons.PROFILE)); |
153 |
a.putValue(Action.SMALL_ICON, Icons.getIcon(ProfilerIcons.PROFILE)); |
154 |
|
155 |
return a; |
156 |
} |
157 |
|
158 |
/** |
159 |
* @return An Action to invoke profiling of a selected project in the IDE |
160 |
*/ |
161 |
public static Action profileProject() { |
162 |
final Action a = ProjectSensitiveAction.projectSensitiveAction(new ProjectSensitiveAction.ProfilerProjectActionPerformer() { |
163 |
public boolean enable(final Project project, final Lookup context, final boolean lightweightOnly) { |
164 |
if (!NetBeansProfiler.isInitialized()) { |
165 |
return false; |
166 |
} |
167 |
|
168 |
if (project == null) { |
169 |
return false; |
170 |
} |
171 |
|
172 |
return org.netbeans.modules.profiler.nbimpl.project.ProjectUtilities.isProjectTypeSupported(project); |
173 |
} |
161 |
} |
174 |
|
162 |
|
175 |
public void perform(final Project project, final Lookup context) { |
163 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
176 |
doProfileProject(project, null, NbBundle.getMessage(AntActions.class, "LBL_ProfileProject")); |
164 |
return support.supportsUnintegrate(); |
|
|
165 |
} |
166 |
|
167 |
@Override |
168 |
public void perform(Project project) { |
169 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
170 |
try { |
171 |
support.unintegrateProfiler(); |
172 |
} catch (Exception e) { |
173 |
ProfilerLogger.log(e); |
177 |
} |
174 |
} |
178 |
}, NbBundle.getMessage(AntActions.class, "LBL_ProfileProjectAction40_General"), // NOI18N |
175 |
} |
179 |
NbBundle.getMessage(AntActions.class, |
176 |
}, NbBundle.getMessage(AntActions.class, "LBL_UnintegrateProfilerAction"), null); // NOI18N |
180 |
"LBL_ProfileProjectAction40"), // NOI18N |
|
|
181 |
null); |
182 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
177 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
183 |
|
178 |
|
184 |
return a; |
179 |
return a; |
185 |
} |
180 |
} |
186 |
|
|
|
187 |
/** |
188 |
* @return An Action to invoke profiling of a selected project in the IDE, does not have project name in display name |
189 |
*/ |
190 |
public static Action profileProjectPopup() { |
191 |
final Action a = ProjectSensitiveAction.projectSensitiveAction(new ProjectSensitiveAction.ProfilerProjectActionPerformer() { |
192 |
public boolean enable(final Project project, final Lookup context, final boolean lightweightOnly) { |
193 |
if (!NetBeansProfiler.isInitialized()) { |
194 |
return false; |
195 |
} |
196 |
|
197 |
if (project == null) { |
198 |
return false; |
199 |
} |
200 |
|
201 |
return org.netbeans.modules.profiler.nbimpl.project.ProjectUtilities.isProjectTypeSupported(project); |
202 |
} |
203 |
|
204 |
public void perform(final Project project, final Lookup context) { |
205 |
doProfileProject(project, null, NbBundle.getMessage(AntActions.class, "LBL_ProfileProject")); |
206 |
} |
207 |
}, NbBundle.getMessage(AntActions.class, "LBL_ProfileProjectActionPopup"), // NOI18N |
208 |
NbBundle.getMessage(AntActions.class, |
209 |
"LBL_ProfileProjectActionPopup"), // NOI18N |
210 |
null); |
211 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
212 |
|
213 |
return a; |
214 |
} |
215 |
|
216 |
/** |
217 |
* @return An Action to invoke profiling of a single class in the IDE |
218 |
*/ |
219 |
public static Action profileSingle() { |
220 |
final Action a = FileSensitiveAction.fileSensitiveAction(new ProjectSensitiveAction.ProfilerProjectActionPerformer() { |
221 |
public boolean enable(final Project project, final Lookup context, final boolean lightweightOnly) { |
222 |
if (!NetBeansProfiler.isInitialized()) { |
223 |
return false; |
224 |
} |
225 |
|
226 |
if (project == null) { |
227 |
return false; |
228 |
} |
229 |
|
230 |
final FileObject[] fos = ProjectSensitiveAction.ActionsUtil.getFilesFromLookup(context, project); |
231 |
|
232 |
if (fos.length != 1) { |
233 |
return false; |
234 |
} |
235 |
|
236 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
237 |
// if (!lightweightOnly) { |
238 |
// if (!ptp.isFileObjectSupported(project, fos[0])) { |
239 |
// return ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
240 |
// } |
241 |
// } else { |
242 |
// return ptp.isProfilingSupported(project) || ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
243 |
// } |
244 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
245 |
if (!lightweightOnly) { |
246 |
if (!support.isFileObjectSupported(fos[0])) { |
247 |
return ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
248 |
} |
249 |
} else { |
250 |
return support.isProfilingSupported() || ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
251 |
} |
252 |
|
253 |
return true; |
254 |
} |
255 |
|
256 |
public void perform(final Project project, final Lookup context) { |
257 |
final FileObject[] fos = ProjectSensitiveAction.ActionsUtil.getFilesFromLookup(context, project); |
258 |
|
259 |
if (fos.length != 1) { |
260 |
throw new IllegalStateException(); |
261 |
} |
262 |
|
263 |
doProfileProject(project, JavaProfilerSource.createFrom(fos[0]), NbBundle.getMessage(AntActions.class, "LBL_ProfileFile")); |
264 |
} |
265 |
}, NbBundle.getMessage(AntActions.class, "LBL_ProfileSingleAction40_General"), // NOI18N |
266 |
NbBundle.getMessage(AntActions.class, "LBL_ProfileSingleAction40"), // NOI18N |
267 |
null); |
268 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
269 |
|
270 |
return a; |
271 |
} |
272 |
|
273 |
/** |
274 |
* @return An Action to invoke profiling of a single class in the IDE. Does not have file name in its display name |
275 |
*/ |
276 |
public static Action profileSinglePopup() { |
277 |
final Action a = FileSensitiveAction.fileSensitiveAction(new ProjectSensitiveAction.ProfilerProjectActionPerformer() { |
278 |
public boolean enable(final Project project, final Lookup context, final boolean lightweightOnly) { |
279 |
if (!NetBeansProfiler.isInitialized()) { |
280 |
return false; |
281 |
} |
282 |
|
283 |
if (project == null) { |
284 |
return false; |
285 |
} |
286 |
|
287 |
final FileObject[] fos = ProjectSensitiveAction.ActionsUtil.getFilesFromLookup(context, project); |
288 |
|
289 |
if (fos.length != 1) { |
290 |
return false; |
291 |
} |
292 |
|
293 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
294 |
// if (!lightweightOnly) { |
295 |
// if (!ptp.isFileObjectSupported(project, fos[0])) { |
296 |
// return ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
297 |
// } |
298 |
// } else { |
299 |
// return ptp.isProfilingSupported(project) || ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
300 |
// } |
301 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
302 |
if (!lightweightOnly) { |
303 |
if (!support.isFileObjectSupported( fos[0])) { |
304 |
return ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
305 |
} |
306 |
} else { |
307 |
return support.isProfilingSupported() || ProjectUtilities.hasAction(project, "profile-single"); //NOI18N |
308 |
} |
309 |
|
310 |
return true; |
311 |
} |
312 |
|
313 |
public void perform(final Project project, final Lookup context) { |
314 |
final FileObject[] fos = ProjectSensitiveAction.ActionsUtil.getFilesFromLookup(context, project); |
315 |
|
316 |
if (fos.length != 1) { |
317 |
throw new IllegalStateException(); |
318 |
} |
319 |
|
320 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
321 |
// if (!ptp.isFileObjectSupported(project, fos[0]) && !ProjectUtilities.hasAction(project, "profile-single")) { //NOI18N |
322 |
// throw new IllegalStateException(); |
323 |
// } |
324 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
325 |
if (!support.isFileObjectSupported( fos[0]) && !ProjectUtilities.hasAction(project, "profile-single")) { //NOI18N |
326 |
throw new IllegalStateException(); |
327 |
} |
328 |
|
329 |
doProfileProject(project, JavaProfilerSource.createFrom(fos[0]) ,NbBundle.getMessage(AntActions.class, "LBL_ProfileFile")); |
330 |
} |
331 |
}, NbBundle.getMessage(AntActions.class, "LBL_ProfileSingleActionPopup"), // NOI18N |
332 |
NbBundle.getMessage(AntActions.class, |
333 |
"LBL_ProfileSingleActionPopup"), // NOI18N |
334 |
null); |
335 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
336 |
|
337 |
return a; |
338 |
} |
339 |
|
340 |
/** |
341 |
* @return An Action to invoke profiling of a single class in the IDE |
342 |
*/ |
343 |
public static Action profileTest() { |
344 |
final Action a = FileSensitiveAction.fileSensitiveAction(new ProjectSensitiveAction.ProfilerProjectActionPerformer() { |
345 |
public boolean enable(final Project project, final Lookup context, final boolean lightweightOnly) { |
346 |
if (!NetBeansProfiler.isInitialized()) { |
347 |
return false; |
348 |
} |
349 |
|
350 |
if (project == null) { |
351 |
return false; |
352 |
} |
353 |
|
354 |
final FileObject[] fos = ProjectSensitiveAction.ActionsUtil.getFilesFromLookup(context, project); |
355 |
|
356 |
if (fos.length != 1) { |
357 |
return false; |
358 |
} |
359 |
|
360 |
final FileObject fo = ProjectUtilities.findTestForFile(fos[0]); |
361 |
|
362 |
if (fo == null) { |
363 |
return false; // not a test and test for it does not exist |
364 |
} |
365 |
|
366 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
367 |
// if (!lightweightOnly) { |
368 |
// return (ptp.isFileObjectSupported(project, fo)); |
369 |
// } else { |
370 |
// return ptp.isProfilingSupported(project); |
371 |
// } |
372 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
373 |
if (!lightweightOnly) { |
374 |
return (support.isFileObjectSupported(fo)); |
375 |
} else { |
376 |
return support.isProfilingSupported(); |
377 |
} |
378 |
} |
379 |
|
380 |
public void perform(final Project project, final Lookup context) { |
381 |
final FileObject[] fos = ProjectSensitiveAction.ActionsUtil.getFilesFromLookup(context, project); |
382 |
|
383 |
if (fos.length != 1) { |
384 |
throw new IllegalStateException(); |
385 |
} |
386 |
|
387 |
final FileObject fo = ProjectUtilities.findTestForFile(fos[0]); |
388 |
|
389 |
if (fo == null) { |
390 |
throw new IllegalStateException(Bundle.AntActions_FileTestNotFoundMsg()); |
391 |
} |
392 |
|
393 |
if (!ProjectProfilingSupport.get(project).isFileObjectSupported(fo)) { |
394 |
throw new IllegalStateException(); |
395 |
} |
396 |
|
397 |
doProfileProject(project, JavaProfilerSource.createFrom(fo), NbBundle.getMessage(AntActions.class, "LBL_ProfileTest")); |
398 |
} |
399 |
}, NbBundle.getMessage(AntActions.class, "LBL_ProfileTestAction_General"), // NI18N |
400 |
NbBundle.getMessage(AntActions.class, "LBL_ProfileTestAction"), // NOI18N |
401 |
null); |
402 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
403 |
|
404 |
return a; |
405 |
} |
406 |
|
407 |
public static Action unintegrateProfiler() { |
408 |
final Action a = ProjectSensitiveAction.projectSensitiveAction(new ProjectSensitiveAction.ProfilerProjectActionPerformer() { |
409 |
public boolean enable(final Project project, final Lookup context, final boolean lightweightOnly) { |
410 |
if (!NetBeansProfiler.isInitialized()) { |
411 |
return false; |
412 |
} |
413 |
|
414 |
if (project == null) { |
415 |
return false; |
416 |
} |
417 |
|
418 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
419 |
// |
420 |
// return ptp.supportsUnintegrate(project); |
421 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
422 |
return support.supportsUnintegrate(); |
423 |
} |
424 |
|
425 |
public void perform(final Project project, final Lookup context) { |
426 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
427 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
428 |
try { |
429 |
support.unintegrateProfiler(); |
430 |
} catch (Exception e) { |
431 |
ProfilerLogger.log(e); |
432 |
} |
433 |
} |
434 |
}, NbBundle.getMessage(AntActions.class, "LBL_UnintegrateProfilerAction"), // NOI18N |
435 |
NbBundle.getMessage(AntActions.class, |
436 |
"LBL_UnintegrateProfilerAction"), // NOI18N |
437 |
null); |
438 |
a.putValue("noIconInMenu", Boolean.TRUE); //NOI18N |
439 |
|
440 |
return a; |
441 |
} |
442 |
|
443 |
private static String getHeapDumpPath(ProfilerIDESettings gps, Project project) { |
444 |
int oomeDetectionMode = gps.getOOMDetectionMode(); |
445 |
|
446 |
switch (oomeDetectionMode) { |
447 |
case ProfilerIDESettings.OOME_DETECTION_TEMPDIR: |
448 |
return System.getProperty("java.io.tmpdir"); // NOI18N |
449 |
case ProfilerIDESettings.OOME_DETECTION_PROJECTDIR: |
450 |
|
451 |
try { |
452 |
return FileUtil.toFile(ProjectStorage.getSettingsFolder(project, true)).getAbsolutePath(); |
453 |
} catch (IOException e) { |
454 |
ErrorManager.getDefault().annotate(e, "Cannot resolve project settings directory:\n" + e.getMessage()); |
455 |
ErrorManager.getDefault().notify(ErrorManager.ERROR, e); |
456 |
|
457 |
return null; |
458 |
} |
459 |
case ProfilerIDESettings.OOME_DETECTION_CUSTOMDIR: |
460 |
return gps.getCustomHeapdumpPath(); |
461 |
} |
462 |
|
463 |
return null; |
464 |
} |
465 |
|
466 |
private static void activateLinuxPosixThreadTime(ProfilingSettings ps, Properties props, Project project) { |
467 |
if (ps.getThreadCPUTimerOn()) { |
468 |
props.setProperty("profiler.info.jvmargs", LINUX_THREAD_TIMER_KEY + " " + props.getProperty("profiler.info.jvmargs")); // NOI18N |
469 |
ProfilerLogger.log("Profiler.UseLinuxPosixThreadCPUClocks: Enabled"); // NOI18N |
470 |
} |
471 |
} |
472 |
|
473 |
private static void activateOOMProtection(ProfilerIDESettings gps, Properties props, Project project) { |
474 |
if (gps.isOOMDetectionEnabled()) { |
475 |
String oldArgs = props.getProperty("profiler.info.jvmargs"); |
476 |
oldArgs = (oldArgs != null) ? oldArgs : ""; |
477 |
|
478 |
StringBuilder oomArgsBuffer = new StringBuilder(oldArgs); |
479 |
String heapDumpPath = getHeapDumpPath(gps, project); |
480 |
|
481 |
if ((heapDumpPath != null) && (heapDumpPath.length() > 0)) { |
482 |
// used for filesystem listener |
483 |
props.setProperty(HeapDumpWatch.OOME_PROTECTION_ENABLED_KEY, "yes"); |
484 |
props.setProperty(HeapDumpWatch.OOME_PROTECTION_DUMPPATH_KEY, heapDumpPath); |
485 |
|
486 |
// used as an argument for starting java process |
487 |
if (heapDumpPath.contains(" ")) { |
488 |
heapDumpPath = "\"" + heapDumpPath + "\""; |
489 |
} |
490 |
|
491 |
oomArgsBuffer.append(" -XX:+HeapDumpOnOutOfMemoryError"); // NOI18N |
492 |
oomArgsBuffer.append(" -XX:HeapDumpPath=").append(heapDumpPath).append(" "); // NOI18N |
493 |
|
494 |
ProfilerLogger.log("Profiler.OutOfMemoryDetection: Enabled"); // NOI18N |
495 |
} |
496 |
|
497 |
props.setProperty("profiler.info.jvmargs", oomArgsBuffer.toString()); // NOI18N |
498 |
} |
499 |
} |
500 |
|
501 |
// -- Private implementation ----------------------------------------------------------------------------------------- |
502 |
|
503 |
/** |
504 |
* Performs profiling of the selected project using either the supplied class (in case of profile single) or the |
505 |
* project's main class. |
506 |
* |
507 |
* @param project The project to profile |
508 |
* @param profiledClassFile In case profiledClass is not null, this is the FileObject representing the specified class |
509 |
*/ |
510 |
private static void doProfileProject(final Project project, final JavaProfilerSource profiledClassFile, final String actionName) { |
511 |
final boolean isTest = profiledClassFile != null ? profiledClassFile.isTest() : false; |
512 |
final FileObject fo = profiledClassFile != null ? profiledClassFile.getFile() : null; |
513 |
|
514 |
if (ProfilingSupport.getDefault().isProfilingActionInvoked()) { |
515 |
return; |
516 |
} |
517 |
|
518 |
ProfilingSupport.getDefault().setProfilingActionInvoked(true); |
519 |
|
520 |
final Runnable actionPerform = new Runnable() { |
521 |
public void run() { |
522 |
try { |
523 |
// 1. if there is profiling in progress, ask the user and possibly cancel |
524 |
if (ProfilingSupport.getDefault().checkProfilingInProgress()) { |
525 |
return; |
526 |
} |
527 |
|
528 |
// final ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
529 |
ProjectProfilingSupport support = ProjectProfilingSupport.get(project); |
530 |
if (!support.isProfilingSupported()) { |
531 |
// Branch A: not supported project with profile action in the action provider |
532 |
|
533 |
// as of now, the profile-tests will neve be used |
534 |
ProjectUtilities.invokeAction(project, isTest ? "profile-tests" : "profile"); //NOI18N |
535 |
} else { |
536 |
// Branch B: project profiling directly supported via ProjectTypeProfiler |
537 |
// 2. check if the project has been modified for profiling |
538 |
if (!support.checkProjectIsModifiedForProfiler()) { |
539 |
return; // something failed - has already been reported to the user |
540 |
} |
541 |
|
542 |
// 3. determine Java platform to use |
543 |
final JavaPlatform platform = initPlatform(project, support); |
544 |
|
545 |
if (platform == null) { |
546 |
return; // user already notified |
547 |
} |
548 |
|
549 |
// 3. check if the project is properly setup to be profiled (e.g. main class has a main method) |
550 |
// FIXME - probably it would be better to pass around JavaProfilerSource instead of FileObject |
551 |
if (!support.checkProjectCanBeProfiled(fo)) { |
552 |
return; |
553 |
} |
554 |
|
555 |
// 5. get session settings from the project context |
556 |
final ProfilerIDESettings gps = ProfilerIDESettings.getInstance(); |
557 |
|
558 |
final String javaFile = platform.getPlatformJavaFile(); |
559 |
|
560 |
if (javaFile == null) { |
561 |
if (ProfilerIDESettings.getInstance().getJavaPlatformForProfiling() == null) { |
562 |
// used platform defined for project |
563 |
ProfilerDialogs.displayError(Bundle.AntActions_InvalidPlatformProjectMsg(platform.getDisplayName())); |
564 |
} else { |
565 |
// used platform defined in Options / Profiler |
566 |
ProfilerDialogs.displayError(Bundle.AntActions_InvalidPlatformProfilerMsg(platform.getDisplayName())); |
567 |
} |
568 |
return; |
569 |
} |
570 |
|
571 |
final String javaVersion = platform.getPlatformJDKVersion(); |
572 |
|
573 |
if (javaVersion == null) { |
574 |
ProfilerDialogs.displayError(Bundle.AntActions_FailedDetermineJavaPlatformMsg(platform.getDisplayName())); |
575 |
|
576 |
return; |
577 |
} |
578 |
|
579 |
final SessionSettings ss = new SessionSettings(); |
580 |
ss.setJavaExecutable(javaFile); |
581 |
ss.setJavaVersionString(javaVersion); |
582 |
ss.setSystemArchitecture(platform.getPlatformArchitecture()); |
583 |
ss.setPortNo(gps.getPortNo()); |
584 |
support.setupProjectSessionSettings(ss); |
585 |
|
586 |
boolean settingsAccepted = false; |
587 |
ProfilingSettings pSettings = null; |
588 |
|
589 |
while (!settingsAccepted) { |
590 |
// 6. show SelectTaskPanel and let the user choose the profiling type |
591 |
pSettings = ProfilingSupport.getDefault() |
592 |
.selectTaskForProfiling(project, ss, fo, |
593 |
support.supportsSettingsOverride()); |
594 |
|
595 |
if (pSettings == null) { |
596 |
return; // cancelled |
597 |
} |
598 |
|
599 |
// Here was a check for enormous profiling overhead when profiling Web Projects. |
600 |
// Generally, this is the right place to give ProjectTypeProfiler a chance to |
601 |
// accept/reject current profiling settings before starting new profiling session. |
602 |
settingsAccepted = true; |
603 |
} |
604 |
|
605 |
final ProfilingSettings profilingSettings = pSettings; |
606 |
final Properties props = new Properties(); |
607 |
|
608 |
// 7. store things into properties to be passed to Ant |
609 |
profilingSettings.store(props); // Profiling settings |
610 |
ss.store(props); // Session settings |
611 |
|
612 |
// Auxiliary internal profiler information: |
613 |
String projectDir = FileUtil.toFile(project.getProjectDirectory()).getAbsolutePath(); |
614 |
props.setProperty("profiler.info.project.dir", projectDir); // NOI18N // TODO: create constant |
615 |
|
616 |
if (fo != null) { |
617 |
String singleFile = FileUtil.toFile(fo).getAbsolutePath(); |
618 |
props.setProperty("profiler.info.single.file", singleFile); // NOI18N // TODO: create constant |
619 |
} |
620 |
|
621 |
String usedJavaExecutable = ss.getJavaExecutable(); |
622 |
String usedJvmArgs = ss.getJVMArgs(); |
623 |
|
624 |
if (profilingSettings.getOverrideGlobalSettings()) { |
625 |
String javaPlatformName = profilingSettings.getJavaPlatformName(); |
626 |
JavaPlatform jp; |
627 |
|
628 |
if (javaPlatformName != null) { |
629 |
usedJavaExecutable = Profiler.getDefault().getPlatformJavaFile(javaPlatformName); |
630 |
jp = JavaPlatform.getJavaPlatformById(javaPlatformName); |
631 |
|
632 |
if (jp == null) { |
633 |
// selected platform does not exist, use |
634 |
String text = Bundle.AntActions_InvalidJavaplatformMsg(javaPlatformName); |
635 |
ProfilerDialogs.displayWarning(text); |
636 |
jp = platform; |
637 |
} |
638 |
} else { |
639 |
// javaPlatformName == null -> do not override java platform, use platform from global settings |
640 |
jp = platform; |
641 |
} |
642 |
// added to support nbstartprofiledserver |
643 |
props.setProperty("profiler.info.javaPlatform", |
644 |
jp.getPlatformId()); |
645 |
usedJvmArgs = profilingSettings.getJVMArgs(); |
646 |
} else { |
647 |
// added to support nbstartprofiledserver |
648 |
props.setProperty("profiler.info.javaPlatform", |
649 |
platform.getPlatformId()); |
650 |
} |
651 |
|
652 |
props.setProperty("profiler.info.jvm", usedJavaExecutable); // NOI18N |
653 |
props.setProperty("profiler.info.jvmargs", usedJvmArgs); // NOI18N |
654 |
|
655 |
if (javaVersion.equals(CommonConstants.JDK_15_STRING)) { |
656 |
// JDK 1.5 used |
657 |
props.setProperty("profiler.info.jvmargs.agent", // NOI18N |
658 |
IDEUtils.getAntProfilerStartArgument15(ss.getPortNo(), |
659 |
ss.getSystemArchitecture()) |
660 |
); |
661 |
|
662 |
if (platform.getPlatformJDKMinor() >= 7) { |
663 |
activateOOMProtection(gps, props, project); |
664 |
} else { |
665 |
ProfilerLogger.log("Profiler.OutOfMemoryDetection: Disabled. Not supported JVM. Use at least 1.4.2_12 or 1.5.0_07"); // NOI18N |
666 |
} |
667 |
} else if (javaVersion.equals(CommonConstants.JDK_16_STRING)) { |
668 |
// JDK 1.6 used |
669 |
props.setProperty("profiler.info.jvmargs.agent", // NOI18N |
670 |
IDEUtils.getAntProfilerStartArgument16(ss.getPortNo(), |
671 |
ss.getSystemArchitecture()) |
672 |
); |
673 |
activateOOMProtection(gps, props, project); |
674 |
} else if (javaVersion.equals(CommonConstants.JDK_17_STRING)) { |
675 |
props.setProperty("profiler.info.jvmargs.agent", // NOI18N |
676 |
IDEUtils.getAntProfilerStartArgument17(ss.getPortNo(), |
677 |
ss.getSystemArchitecture()) |
678 |
); |
679 |
activateOOMProtection(gps, props, project); |
680 |
} else if (javaVersion.equals(CommonConstants.JDK_18_STRING)) { |
681 |
props.setProperty("profiler.info.jvmargs.agent", // NOI18N |
682 |
IDEUtils.getAntProfilerStartArgument18(ss.getPortNo(), |
683 |
ss.getSystemArchitecture()) |
684 |
); |
685 |
activateOOMProtection(gps, props, project); |
686 |
} else { |
687 |
throw new IllegalArgumentException("Unsupported JDK " + javaVersion); // NOI18N |
688 |
} |
689 |
|
690 |
if (Platform.isLinux() && javaVersion.equals(CommonConstants.JDK_16_STRING)) { |
691 |
activateLinuxPosixThreadTime(pSettings, props, project); |
692 |
} |
693 |
|
694 |
if (!support.startProfilingSession(fo, isTest, props)) { // Used for Maven - ProjectTypeProfiler itself controls starting profiling session |
695 |
|
696 |
// 8. determine the build script and target to run |
697 |
AntProjectSupport antSupport = AntProjectSupport.get(project); |
698 |
final FileObject buildScriptFO = antSupport.getProjectBuildScript(); |
699 |
|
700 |
if (buildScriptFO == null) { |
701 |
ProfilerDialogs.displayError(Bundle.AntActions_FailedDetermineProjectBuildScriptMsg(ProjectUtils.getInformation(project).getName())); |
702 |
|
703 |
return; |
704 |
} |
705 |
|
706 |
// determine which type fo target shoudl be called, and request its name |
707 |
int type; |
708 |
|
709 |
if (isTest) { |
710 |
type = (fo == null) ? AntProjectSupport.TARGET_PROFILE_TEST |
711 |
: AntProjectSupport.TARGET_PROFILE_TEST_SINGLE; |
712 |
} else { |
713 |
type = (fo == null) ? AntProjectSupport.TARGET_PROFILE |
714 |
: AntProjectSupport.TARGET_PROFILE_SINGLE; |
715 |
} |
716 |
|
717 |
final String profileTarget = antSupport.getProfilerTargetName(buildScriptFO, type, fo); |
718 |
|
719 |
if (profileTarget == null) { |
720 |
return; // already notified the user or user's choice |
721 |
} |
722 |
|
723 |
// 9. final ability of the ProjectTypeProfiler to influence the properties passed to Ant |
724 |
support.configurePropertiesForProfiling(props, fo); |
725 |
|
726 |
// 10. Run the target |
727 |
((org.netbeans.modules.profiler.nbimpl.NetBeansProfiler)Profiler.getDefault()).runTarget(buildScriptFO, profileTarget, props); |
728 |
|
729 |
} |
730 |
|
731 |
|
732 |
} |
733 |
} finally { |
734 |
ProfilingSupport.getDefault().setProfilingActionInvoked(false); |
735 |
} |
736 |
} |
737 |
}; |
738 |
|
739 |
CommonUtils.runInEventDispatchThread(new Runnable() { |
740 |
@Override |
741 |
public void run() { |
742 |
if (ScanDialog.runWhenScanFinished(new Runnable() { |
743 |
@Override |
744 |
public void run() { |
745 |
RequestProcessor.getDefault().post(actionPerform); |
746 |
} |
747 |
}, actionName)) { |
748 |
ProfilingSupport.getDefault().setProfilingActionInvoked(false); |
749 |
} |
750 |
} |
751 |
}); |
752 |
} |
753 |
|
754 |
private static JavaPlatform initPlatform(Project project, ProjectProfilingSupport pps) { |
755 |
// 1. check if we have a Java platform to use for profiling |
756 |
final ProfilerIDESettings gps = ProfilerIDESettings.getInstance(); |
757 |
JavaPlatform platform = JavaPlatform.getJavaPlatformById(gps.getJavaPlatformForProfiling()); |
758 |
JavaPlatform projectPlatform = pps.getProjectJavaPlatform(); |
759 |
|
760 |
if (platform == null) { // should use the one defined in project |
761 |
platform = projectPlatform; |
762 |
|
763 |
if ((platform == null) || !MiscUtils.isSupportedJVM(platform.getSystemProperties())) { |
764 |
platform = JavaPlatformSelector.getDefault().selectPlatformToUse(); |
765 |
|
766 |
if (platform == null) { |
767 |
return null; |
768 |
} |
769 |
} |
770 |
} |
771 |
|
772 |
if (projectPlatform != null) { // check that the project platform is not newer than platform to use |
773 |
|
774 |
while (true) { |
775 |
if (projectPlatform.getVersion().compareTo(platform.getVersion()) > 0) { |
776 |
Boolean ret = ProfilerDialogs.displayCancellableConfirmation( |
777 |
Bundle.AntActions_IncorrectJavaSpecVersionDialogMsg(), |
778 |
Bundle.AntActions_IncorrectJavaSpecVersionDialogCaption()); |
779 |
|
780 |
if (Boolean.TRUE.equals(ret)) { |
781 |
break; |
782 |
} else if (Boolean.FALSE.equals(ret)) { |
783 |
platform = JavaPlatformSelector.getDefault().selectPlatformToUse(); |
784 |
|
785 |
if (platform == null) { |
786 |
return null; // cancelled by the user |
787 |
} |
788 |
} else { // cancelled |
789 |
|
790 |
return null; |
791 |
} |
792 |
} else { |
793 |
break; // version comparison OK. |
794 |
} |
795 |
} |
796 |
} |
797 |
|
798 |
return platform; |
799 |
} |
800 |
|
801 |
// private static boolean isProjectTypeSupported(final Project project) { |
802 |
// ProjectTypeProfiler ptp = org.netbeans.modules.profiler.utils.ProjectUtilities.getProjectTypeProfiler(project); |
803 |
// |
804 |
// if (ptp.isProfilingSupported(project)) { |
805 |
// return true; |
806 |
// } |
807 |
// |
808 |
// return ProjectUtilities.hasAction(project, "profile"); //NOI18N |
809 |
// } |
810 |
} |
181 |
} |