Lines 80-86
Link Here
|
80 |
import java.util.regex.Pattern; |
80 |
import java.util.regex.Pattern; |
81 |
import javax.lang.model.element.TypeElement; |
81 |
import javax.lang.model.element.TypeElement; |
82 |
import javax.swing.JButton; |
82 |
import javax.swing.JButton; |
83 |
import javax.swing.SwingUtilities; |
|
|
84 |
import javax.swing.event.ChangeEvent; |
83 |
import javax.swing.event.ChangeEvent; |
85 |
import javax.swing.event.ChangeListener; |
84 |
import javax.swing.event.ChangeListener; |
86 |
import org.apache.tools.ant.module.api.support.ActionUtils; |
85 |
import org.apache.tools.ant.module.api.support.ActionUtils; |
Lines 123-129
Link Here
|
123 |
import org.netbeans.spi.project.SingleMethod; |
122 |
import org.netbeans.spi.project.SingleMethod; |
124 |
import org.netbeans.spi.project.support.ant.AntProjectHelper; |
123 |
import org.netbeans.spi.project.support.ant.AntProjectHelper; |
125 |
import org.netbeans.spi.project.support.ant.EditableProperties; |
124 |
import org.netbeans.spi.project.support.ant.EditableProperties; |
126 |
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper; |
|
|
127 |
import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
125 |
import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
128 |
import org.netbeans.spi.project.ui.support.DefaultProjectOperations; |
126 |
import org.netbeans.spi.project.ui.support.DefaultProjectOperations; |
129 |
import org.openide.DialogDescriptor; |
127 |
import org.openide.DialogDescriptor; |
Lines 172-183
Link Here
|
172 |
}))); |
170 |
}))); |
173 |
|
171 |
|
174 |
// Project |
172 |
// Project |
175 |
final private Project project; |
173 |
private final Project project; |
176 |
|
174 |
|
177 |
final AntProjectHelper antProjectHelper; |
175 |
private final AntProjectHelper antProjectHelper; |
178 |
|
176 |
|
179 |
final private Callback callback; |
177 |
private final Callback callback; |
180 |
|
178 |
|
181 |
// Ant project helper of the project |
179 |
// Ant project helper of the project |
182 |
private UpdateHelper updateHelper; |
180 |
private UpdateHelper updateHelper; |
183 |
|
181 |
|
Lines 321-333
Link Here
|
321 |
} catch (FileStateInvalidException x) { |
319 |
} catch (FileStateInvalidException x) { |
322 |
Exceptions.printStackTrace(x); |
320 |
Exceptions.printStackTrace(x); |
323 |
} |
321 |
} |
324 |
} |
322 |
} |
325 |
|
|
|
326 |
private JavaPlatform getActivePlatform() { |
327 |
return callback instanceof CustomPlatformCallback ? |
328 |
((CustomPlatformCallback)callback).getActivePlatform() : |
329 |
CommonProjectUtils.getActivePlatform(evaluator.getProperty(ProjectProperties.PLATFORM_ACTIVE)); |
330 |
} |
331 |
|
323 |
|
332 |
private void modification(FileObject f) { |
324 |
private void modification(FileObject f) { |
333 |
if (!allowsFileChangesTracking()) { |
325 |
if (!allowsFileChangesTracking()) { |
Lines 494-500
Link Here
|
494 |
copyMultiValue(ProjectProperties.RUN_JVM_ARGS, execProperties); |
486 |
copyMultiValue(ProjectProperties.RUN_JVM_ARGS, execProperties); |
495 |
prepareWorkDir(execProperties); |
487 |
prepareWorkDir(execProperties); |
496 |
|
488 |
|
497 |
execProperties.put(JavaRunner.PROP_PLATFORM, getActivePlatform()); |
489 |
execProperties.put(JavaRunner.PROP_PLATFORM, getProjectPlatform()); |
498 |
execProperties.put(JavaRunner.PROP_PROJECT_NAME, ProjectUtils.getInformation(project).getDisplayName()); |
490 |
execProperties.put(JavaRunner.PROP_PROJECT_NAME, ProjectUtils.getInformation(project).getDisplayName()); |
499 |
String runtimeEnc = evaluator.getProperty(ProjectProperties.RUNTIME_ENCODING); |
491 |
String runtimeEnc = evaluator.getProperty(ProjectProperties.RUNTIME_ENCODING); |
500 |
if (runtimeEnc != null) { |
492 |
if (runtimeEnc != null) { |
Lines 769-775
Link Here
|
769 |
@org.netbeans.api.annotations.common.SuppressWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS") |
761 |
@org.netbeans.api.annotations.common.SuppressWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS") |
770 |
public @CheckForNull String[] getTargetNames(String command, Lookup context, Properties p, boolean doJavaChecks) throws IllegalArgumentException { |
762 |
public @CheckForNull String[] getTargetNames(String command, Lookup context, Properties p, boolean doJavaChecks) throws IllegalArgumentException { |
771 |
if (Arrays.asList(getPlatformSensitiveActions()).contains(command)) { |
763 |
if (Arrays.asList(getPlatformSensitiveActions()).contains(command)) { |
772 |
if (getActivePlatform() == null) { |
764 |
if (getProjectPlatform() == null) { |
773 |
showPlatformWarning (); |
765 |
showPlatformWarning (); |
774 |
return null; |
766 |
return null; |
775 |
} |
767 |
} |
Lines 850-904
Link Here
|
850 |
p.setProperty("fix.includes", path); // NOI18N |
842 |
p.setProperty("fix.includes", path); // NOI18N |
851 |
p.setProperty("fix.classes", classes); // NOI18N |
843 |
p.setProperty("fix.classes", classes); // NOI18N |
852 |
} else if (!isServerExecution() && (command.equals (COMMAND_RUN) || command.equals(COMMAND_DEBUG) || command.equals(COMMAND_DEBUG_STEP_INTO) || command.equals(COMMAND_PROFILE))) { |
844 |
} else if (!isServerExecution() && (command.equals (COMMAND_RUN) || command.equals(COMMAND_DEBUG) || command.equals(COMMAND_DEBUG_STEP_INTO) || command.equals(COMMAND_PROFILE))) { |
853 |
String config = evaluator.getProperty(ProjectProperties.PROP_PROJECT_CONFIGURATION_CONFIG); |
|
|
854 |
String path; |
855 |
if (config == null || config.length() == 0) { |
856 |
path = AntProjectHelper.PROJECT_PROPERTIES_PATH; |
857 |
} else { |
858 |
// Set main class for a particular config only. |
859 |
path = "nbproject/configs/" + config + ".properties"; // NOI18N |
860 |
} |
861 |
EditableProperties ep = updateHelper.getProperties(path); |
862 |
|
863 |
// check project's main class |
845 |
// check project's main class |
864 |
// Check whether main class is defined in this config. Note that we use the evaluator, |
846 |
// Check whether main class is defined in this config. Note that we use the evaluator, |
865 |
// not ep.getProperty(MAIN_CLASS), since it is permissible for the default pseudoconfig |
847 |
// not ep.getProperty(MAIN_CLASS), since it is permissible for the default pseudoconfig |
866 |
// to define a main class - in this case an active config need not override it. |
848 |
// to define a main class - in this case an active config need not override it. |
867 |
String mainClass = evaluator.getProperty(ProjectProperties.MAIN_CLASS); |
849 |
|
868 |
MainClassStatus result; |
850 |
// If a specific config was selected, just skip this check for now. |
869 |
if (doJavaChecks) { |
851 |
// XXX would ideally check that that config in fact had a main class. |
870 |
result = isSetMainClass (projectSourceRoots, mainClass); |
852 |
// But then evaluator.getProperty(MAIN_CLASS) would be inaccurate. |
871 |
} else { |
853 |
// Solvable but punt on it for now. |
872 |
result = MainClassStatus.SET_AND_VALID; |
854 |
boolean hasCfg = context.lookup(ProjectConfiguration.class) != null; |
873 |
} |
855 |
String mainClass = getProjectMainClass(doJavaChecks && !hasCfg); |
874 |
if (context.lookup(ProjectConfiguration.class) != null) { |
856 |
if (mainClass == null) { |
875 |
// If a specific config was selected, just skip this check for now. |
|
|
876 |
// XXX would ideally check that that config in fact had a main class. |
877 |
// But then evaluator.getProperty(MAIN_CLASS) would be inaccurate. |
878 |
// Solvable but punt on it for now. |
879 |
result = MainClassStatus.SET_AND_VALID; |
880 |
} |
881 |
if (result != MainClassStatus.SET_AND_VALID) { |
882 |
do { |
857 |
do { |
883 |
// show warning, if cancel then return |
858 |
// show warning, if cancel then return |
884 |
if (showMainClassWarning (mainClass, ProjectUtils.getInformation(project).getDisplayName(), ep,result)) { |
859 |
if (!showMainClassSelector()) { |
885 |
return null; |
860 |
return null; |
886 |
} |
861 |
} |
887 |
// No longer use the evaluator: have not called putProperties yet so it would not work. |
862 |
// No longer use the evaluator: have not called putProperties yet so it would not work. |
888 |
mainClass = ep.get(ProjectProperties.MAIN_CLASS); |
863 |
mainClass = evaluator.getProperty(ProjectProperties.MAIN_CLASS); |
889 |
result=isSetMainClass (projectSourceRoots, mainClass); |
864 |
mainClass = getProjectMainClass(doJavaChecks && !hasCfg); |
890 |
} while (result != MainClassStatus.SET_AND_VALID); |
865 |
} while (mainClass == null); |
891 |
try { |
|
|
892 |
if (updateHelper.requestUpdate()) { |
893 |
updateHelper.putProperties(path, ep); |
894 |
ProjectManager.getDefault().saveProject(project); |
895 |
} |
896 |
else { |
897 |
return null; |
898 |
} |
899 |
} catch (IOException ioe) { |
900 |
ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Error while saving project: " + ioe); |
901 |
} |
902 |
} |
866 |
} |
903 |
if (!command.equals(COMMAND_RUN) && /* XXX should ideally look up proper mainClass in evaluator x config */ mainClass != null) { |
867 |
if (!command.equals(COMMAND_RUN) && /* XXX should ideally look up proper mainClass in evaluator x config */ mainClass != null) { |
904 |
if (command.equals(COMMAND_PROFILE)) { |
868 |
if (command.equals(COMMAND_PROFILE)) { |
Lines 1090-1095
Link Here
|
1090 |
} |
1054 |
} |
1091 |
|
1055 |
|
1092 |
/** |
1056 |
/** |
|
|
1057 |
* Returns the project's {@link JavaPlatform}. |
1058 |
* @return the project's {@link JavaPlatform} or null when project's |
1059 |
* {@link JavaPlatform} is broken. |
1060 |
* @since 1.66 |
1061 |
*/ |
1062 |
@CheckForNull |
1063 |
protected JavaPlatform getProjectPlatform() { |
1064 |
return CommonProjectUtils.getActivePlatform(evaluator.getProperty(ProjectProperties.PLATFORM_ACTIVE)); |
1065 |
} |
1066 |
|
1067 |
/** |
1093 |
* @param targetNames caller of this method must set this parameter to empty |
1068 |
* @param targetNames caller of this method must set this parameter to empty |
1094 |
* modifiable array; implementor of this method can return alternative target |
1069 |
* modifiable array; implementor of this method can return alternative target |
1095 |
* names to be used to handle this Java class |
1070 |
* names to be used to handle this Java class |
Lines 1098-1103
Link Here
|
1098 |
return false; |
1073 |
return false; |
1099 |
} |
1074 |
} |
1100 |
|
1075 |
|
|
|
1076 |
/** |
1077 |
* Gets the project main class to be executed. |
1078 |
* @param verify if true the java checks should be performed |
1079 |
* and the main class should be returned only if it's valid |
1080 |
* @return the main class |
1081 |
* @since 1.66 |
1082 |
*/ |
1083 |
@CheckForNull |
1084 |
protected String getProjectMainClass(final boolean verify) { |
1085 |
final String mainClass = evaluator.getProperty(ProjectProperties.MAIN_CLASS); |
1086 |
// support for unit testing |
1087 |
if (MainClassChooser.unitTestingSupport_hasMainMethodResult != null) { |
1088 |
return MainClassChooser.unitTestingSupport_hasMainMethodResult ? |
1089 |
mainClass : |
1090 |
null; |
1091 |
} |
1092 |
if (mainClass == null || mainClass.length () == 0) { |
1093 |
LOG.fine("Main class is not set"); //NOI18N |
1094 |
return null; |
1095 |
} |
1096 |
if (!verify) { |
1097 |
return mainClass; |
1098 |
} |
1099 |
final FileObject[] sourcesRoots = projectSourceRoots.getRoots(); |
1100 |
if (sourcesRoots.length > 0) { |
1101 |
LOG.log(Level.FINE, "Searching main class {0} for root: {1}", //NOI18N |
1102 |
new Object[] { |
1103 |
mainClass, |
1104 |
FileUtil.getFileDisplayName(sourcesRoots[0]) |
1105 |
}); |
1106 |
ClassPath bootPath = null, compilePath = null; |
1107 |
try { |
1108 |
bootPath = ClassPath.getClassPath (sourcesRoots[0], ClassPath.BOOT); //Single compilation unit |
1109 |
assert bootPath != null : assertPath ( |
1110 |
sourcesRoots[0], |
1111 |
sourcesRoots, |
1112 |
projectSourceRoots, |
1113 |
ClassPath.BOOT); |
1114 |
} catch (AssertionError e) { |
1115 |
//Log the assertion when -ea |
1116 |
Exceptions.printStackTrace(e); |
1117 |
} |
1118 |
try { |
1119 |
compilePath = ClassPath.getClassPath (sourcesRoots[0], ClassPath.EXECUTE); |
1120 |
assert compilePath != null : assertPath ( |
1121 |
sourcesRoots[0], |
1122 |
sourcesRoots, |
1123 |
projectSourceRoots, |
1124 |
ClassPath.EXECUTE); |
1125 |
} catch (AssertionError e) { |
1126 |
//Log the assertion when -ea |
1127 |
Exceptions.printStackTrace(e); |
1128 |
} |
1129 |
//todo: The J2SEActionProvider does not require the sourceRoots, it can take the classpath |
1130 |
//from ClassPathProvider everytime. But the assertions above are important, it seems that |
1131 |
//the SimpleFileOwnerQueryImplementation is broken in some cases. When assertions are enabled |
1132 |
//log the data. |
1133 |
if (bootPath == null) { |
1134 |
LOG.fine("Source root has no boot classpath, using project boot classpath."); //NOI18N |
1135 |
bootPath = callback.getProjectSourcesClassPath(ClassPath.BOOT); |
1136 |
} |
1137 |
if (compilePath == null) { |
1138 |
LOG.fine("Source root has no execute classpath, using project execute classpath."); //NOI18N |
1139 |
compilePath = callback.getProjectSourcesClassPath(ClassPath.EXECUTE); |
1140 |
} |
1141 |
|
1142 |
ClassPath sourcePath = ClassPath.getClassPath(sourcesRoots[0], ClassPath.SOURCE); |
1143 |
LOG.log(Level.FINE, "Classpaths used to resolve main boot: {0}, exec: {1}, src: {2}", //NOI18N |
1144 |
new Object[]{ |
1145 |
bootPath, |
1146 |
compilePath, |
1147 |
sourcePath |
1148 |
}); |
1149 |
if (CommonProjectUtils.isMainClass (mainClass, bootPath, compilePath, sourcePath)) { |
1150 |
return mainClass; |
1151 |
} |
1152 |
} else { |
1153 |
LOG.log(Level.FINE, "Searching main class {0} without source root", mainClass); //NOI18N |
1154 |
ClassPath bootPath = callback.getProjectSourcesClassPath(ClassPath.BOOT); |
1155 |
ClassPath compilePath = callback.getProjectSourcesClassPath(ClassPath.EXECUTE); |
1156 |
ClassPath sourcePath = callback.getProjectSourcesClassPath(ClassPath.SOURCE); //Empty ClassPath |
1157 |
LOG.log(Level.FINE, "Classpaths used to resolve main boot: {0}, exec: {1}, src: {2}", //NOI18N |
1158 |
new Object[]{ |
1159 |
bootPath, |
1160 |
compilePath, |
1161 |
sourcePath |
1162 |
}); |
1163 |
if (CommonProjectUtils.isMainClass (mainClass, bootPath, compilePath, sourcePath)) { |
1164 |
return mainClass; |
1165 |
} |
1166 |
} |
1167 |
LOG.log(Level.FINE, "Main class {0} is invalid.", mainClass); //NOI18N |
1168 |
return null; |
1169 |
} |
1170 |
|
1171 |
private String assertPath ( |
1172 |
FileObject fileObject, |
1173 |
FileObject[] expectedRoots, |
1174 |
SourceRoots roots, |
1175 |
String pathType) { |
1176 |
final StringBuilder sb = new StringBuilder (); |
1177 |
sb.append ("File: ").append (fileObject); //NOI18N |
1178 |
sb.append ("\nPath Type: ").append (pathType); //NOI18N |
1179 |
final Project owner = FileOwnerQuery.getOwner(fileObject); |
1180 |
sb.append ("\nOwner: ").append (owner == null ? "" : ProjectUtils.getInformation(owner).getDisplayName()); //NOI18N |
1181 |
sb.append ("\nClassPathProviders: "); //NOI18N |
1182 |
for (ClassPathProvider impl : Lookup.getDefault ().lookupResult (ClassPathProvider.class).allInstances ()) |
1183 |
sb.append ("\n ").append (impl); //NOI18N |
1184 |
sb.append ("\nProject SourceGroups:"); //NOI18N |
1185 |
final SourceGroup[] sgs = ProjectUtils.getSources(this.project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); |
1186 |
for (SourceGroup sg : sgs) { |
1187 |
sb.append("\n ").append(FileUtil.getFileDisplayName(sg.getRootFolder())); //NOI18N |
1188 |
} |
1189 |
sb.append ("\nProject Source Roots("); //NOI18N |
1190 |
sb.append(System.identityHashCode(roots)); |
1191 |
sb.append("):"); //NOI18N |
1192 |
for (FileObject expectedRoot : expectedRoots) { |
1193 |
sb.append("\n ").append(FileUtil.getFileDisplayName(expectedRoot)); //NOI18N |
1194 |
} |
1195 |
return sb.toString (); |
1196 |
} |
1197 |
|
1198 |
/** |
1199 |
* Shows a selector of project main class. |
1200 |
* @return true if main class was selected, false when project execution was canceled. |
1201 |
* @since 1.66 |
1202 |
*/ |
1203 |
@Messages({ |
1204 |
"LBL_MainClassWarning_ChooseMainClass_OK=OK", |
1205 |
"AD_MainClassWarning_ChooseMainClass_OK=N/A", |
1206 |
"# {0} - project name", "LBL_MainClassNotFound=Project {0} does not have a main class set.", |
1207 |
"# {0} - name of class", "# {1} - project name", "LBL_MainClassWrong={0} class wasn''t found in {1} project.", |
1208 |
"CTL_MainClassWarning_Title=Run Project" |
1209 |
}) |
1210 |
protected boolean showMainClassSelector() { |
1211 |
boolean result = false; |
1212 |
final JButton okButton = new JButton(LBL_MainClassWarning_ChooseMainClass_OK()); |
1213 |
okButton.getAccessibleContext().setAccessibleDescription(AD_MainClassWarning_ChooseMainClass_OK()); |
1214 |
// main class goes wrong => warning |
1215 |
String mainClass = getProjectMainClass(false); |
1216 |
String message; |
1217 |
if (mainClass == null) { |
1218 |
message = LBL_MainClassNotFound(ProjectUtils.getInformation(project).getDisplayName()); |
1219 |
} else { |
1220 |
message = LBL_MainClassWrong( |
1221 |
mainClass, |
1222 |
ProjectUtils.getInformation(project).getDisplayName()); |
1223 |
} |
1224 |
final MainClassWarning panel = new MainClassWarning (message, projectSourceRoots.getRoots()); |
1225 |
Object[] options = new Object[] { |
1226 |
okButton, |
1227 |
DialogDescriptor.CANCEL_OPTION |
1228 |
}; |
1229 |
panel.addChangeListener (new ChangeListener () { |
1230 |
@Override |
1231 |
public void stateChanged (ChangeEvent e) { |
1232 |
if (e.getSource () instanceof MouseEvent && MouseUtils.isDoubleClick (((MouseEvent)e.getSource ()))) { |
1233 |
// click button and the finish dialog with selected class |
1234 |
okButton.doClick (); |
1235 |
} else { |
1236 |
okButton.setEnabled (panel.getSelectedMainClass () != null); |
1237 |
} |
1238 |
} |
1239 |
}); |
1240 |
okButton.setEnabled (false); |
1241 |
DialogDescriptor desc = new DialogDescriptor (panel, |
1242 |
CTL_MainClassWarning_Title(), |
1243 |
true, options, options[0], DialogDescriptor.BOTTOM_ALIGN, null, null); |
1244 |
desc.setMessageType (DialogDescriptor.INFORMATION_MESSAGE); |
1245 |
Dialog dlg = DialogDisplayer.getDefault ().createDialog (desc); |
1246 |
dlg.setVisible (true); |
1247 |
if (desc.getValue() == options[0]) { |
1248 |
mainClass = panel.getSelectedMainClass (); |
1249 |
String config = evaluator.getProperty(ProjectProperties.PROP_PROJECT_CONFIGURATION_CONFIG); |
1250 |
String path; |
1251 |
if (config == null || config.length() == 0) { |
1252 |
path = AntProjectHelper.PROJECT_PROPERTIES_PATH; |
1253 |
} else { |
1254 |
// Set main class for a particular config only. |
1255 |
path = "nbproject/configs/" + config + ".properties"; // NOI18N |
1256 |
} |
1257 |
final EditableProperties ep = updateHelper.getProperties(path); |
1258 |
ep.put(ProjectProperties.MAIN_CLASS, mainClass == null ? "" : mainClass); |
1259 |
try { |
1260 |
if (updateHelper.requestUpdate()) { |
1261 |
updateHelper.putProperties(path, ep); |
1262 |
ProjectManager.getDefault().saveProject(project); |
1263 |
result = true; |
1264 |
} |
1265 |
} catch (IOException ioe) { |
1266 |
ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, "Error while saving project: " + ioe); |
1267 |
} |
1268 |
} |
1269 |
dlg.dispose(); |
1270 |
return result; |
1271 |
} |
1272 |
|
1101 |
private void prepareDirtyList(Properties p, boolean isExplicitBuildTarget) { |
1273 |
private void prepareDirtyList(Properties p, boolean isExplicitBuildTarget) { |
1102 |
String doDepend = evaluator.getProperty(ProjectProperties.DO_DEPEND); |
1274 |
String doDepend = evaluator.getProperty(ProjectProperties.DO_DEPEND); |
1103 |
String buildClassesDirValue = evaluator.getProperty(ProjectProperties.BUILD_CLASSES_DIR); |
1275 |
String buildClassesDirValue = evaluator.getProperty(ProjectProperties.BUILD_CLASSES_DIR); |
Lines 1594-1600
Link Here
|
1594 |
return Collections.emptyList(); |
1766 |
return Collections.emptyList(); |
1595 |
} |
1767 |
} |
1596 |
List<String> args = new ArrayList<String>(); |
1768 |
List<String> args = new ArrayList<String>(); |
1597 |
JavaPlatform p = getActivePlatform(); |
1769 |
JavaPlatform p = getProjectPlatform(); |
1598 |
for (StartupExtender group : StartupExtender.getExtenders(Lookups.fixed(project, p != null ? p : JavaPlatformManager.getDefault().getDefaultPlatform()), mode)) { |
1770 |
for (StartupExtender group : StartupExtender.getExtenders(Lookups.fixed(project, p != null ? p : JavaPlatformManager.getDefault().getDefaultPlatform()), mode)) { |
1599 |
args.addAll(group.getArguments()); |
1771 |
args.addAll(group.getArguments()); |
1600 |
} |
1772 |
} |
Lines 1641-1839
Link Here
|
1641 |
return collectAdditionalProperties(properties, command, context); |
1813 |
return collectAdditionalProperties(properties, command, context); |
1642 |
} |
1814 |
} |
1643 |
|
1815 |
|
1644 |
private static enum MainClassStatus { |
|
|
1645 |
SET_AND_VALID, |
1646 |
SET_BUT_INVALID, |
1647 |
UNSET |
1648 |
} |
1649 |
|
1650 |
/** |
1651 |
* Tests if the main class is set |
1652 |
* @param sourcesRoots source roots |
1653 |
* @param mainClass main class name |
1654 |
* @return status code |
1655 |
*/ |
1656 |
private MainClassStatus isSetMainClass(SourceRoots roots, String mainClass) { |
1657 |
|
1658 |
// support for unit testing |
1659 |
if (MainClassChooser.unitTestingSupport_hasMainMethodResult != null) { |
1660 |
return MainClassChooser.unitTestingSupport_hasMainMethodResult ? MainClassStatus.SET_AND_VALID : MainClassStatus.SET_BUT_INVALID; |
1661 |
} |
1662 |
|
1663 |
if (mainClass == null || mainClass.length () == 0) { |
1664 |
LOG.fine("Main class is not set"); //NOI18N |
1665 |
return MainClassStatus.UNSET; |
1666 |
} |
1667 |
final FileObject[] sourcesRoots = roots.getRoots(); |
1668 |
if (sourcesRoots.length > 0) { |
1669 |
LOG.log(Level.FINE, "Searching main class {0} for root: {1}", //NOI18N |
1670 |
new Object[] { |
1671 |
mainClass, |
1672 |
FileUtil.getFileDisplayName(sourcesRoots[0]) |
1673 |
}); |
1674 |
ClassPath bootPath = null, compilePath = null; |
1675 |
try { |
1676 |
bootPath = ClassPath.getClassPath (sourcesRoots[0], ClassPath.BOOT); //Single compilation unit |
1677 |
assert bootPath != null : assertPath ( |
1678 |
sourcesRoots[0], |
1679 |
sourcesRoots, |
1680 |
roots, |
1681 |
ClassPath.BOOT); |
1682 |
} catch (AssertionError e) { |
1683 |
//Log the assertion when -ea |
1684 |
Exceptions.printStackTrace(e); |
1685 |
} |
1686 |
try { |
1687 |
compilePath = ClassPath.getClassPath (sourcesRoots[0], ClassPath.EXECUTE); |
1688 |
assert compilePath != null : assertPath ( |
1689 |
sourcesRoots[0], |
1690 |
sourcesRoots, |
1691 |
roots, |
1692 |
ClassPath.EXECUTE); |
1693 |
} catch (AssertionError e) { |
1694 |
//Log the assertion when -ea |
1695 |
Exceptions.printStackTrace(e); |
1696 |
} |
1697 |
//todo: The J2SEActionProvider does not require the sourceRoots, it can take the classpath |
1698 |
//from ClassPathProvider everytime. But the assertions above are important, it seems that |
1699 |
//the SimpleFileOwnerQueryImplementation is broken in some cases. When assertions are enabled |
1700 |
//log the data. |
1701 |
if (bootPath == null) { |
1702 |
LOG.fine("Source root has no boot classpath, using project boot classpath."); //NOI18N |
1703 |
bootPath = callback.getProjectSourcesClassPath(ClassPath.BOOT); |
1704 |
} |
1705 |
if (compilePath == null) { |
1706 |
LOG.fine("Source root has no execute classpath, using project execute classpath."); //NOI18N |
1707 |
compilePath = callback.getProjectSourcesClassPath(ClassPath.EXECUTE); |
1708 |
} |
1709 |
|
1710 |
ClassPath sourcePath = ClassPath.getClassPath(sourcesRoots[0], ClassPath.SOURCE); |
1711 |
LOG.log(Level.FINE, "Classpaths used to resolve main boot: {0}, exec: {1}, src: {2}", //NOI18N |
1712 |
new Object[]{ |
1713 |
bootPath, |
1714 |
compilePath, |
1715 |
sourcePath |
1716 |
}); |
1717 |
if (CommonProjectUtils.isMainClass (mainClass, bootPath, compilePath, sourcePath)) { |
1718 |
return MainClassStatus.SET_AND_VALID; |
1719 |
} |
1720 |
} |
1721 |
else { |
1722 |
LOG.log(Level.FINE, "Searching main class {0} without source root", mainClass); //NOI18N |
1723 |
ClassPath bootPath = callback.getProjectSourcesClassPath(ClassPath.BOOT); |
1724 |
ClassPath compilePath = callback.getProjectSourcesClassPath(ClassPath.EXECUTE); |
1725 |
ClassPath sourcePath = callback.getProjectSourcesClassPath(ClassPath.SOURCE); //Empty ClassPath |
1726 |
LOG.log(Level.FINE, "Classpaths used to resolve main boot: {0}, exec: {1}, src: {2}", //NOI18N |
1727 |
new Object[]{ |
1728 |
bootPath, |
1729 |
compilePath, |
1730 |
sourcePath |
1731 |
}); |
1732 |
if (CommonProjectUtils.isMainClass (mainClass, bootPath, compilePath, sourcePath)) { |
1733 |
return MainClassStatus.SET_AND_VALID; |
1734 |
} |
1735 |
} |
1736 |
LOG.log(Level.FINE, "Main class {0} is invalid.", mainClass); //NOI18N |
1737 |
return MainClassStatus.SET_BUT_INVALID; |
1738 |
} |
1739 |
|
1740 |
private String assertPath ( |
1741 |
FileObject fileObject, |
1742 |
FileObject[] expectedRoots, |
1743 |
SourceRoots roots, |
1744 |
String pathType |
1745 |
) { |
1746 |
StringBuilder sb = new StringBuilder (); |
1747 |
sb.append ("File: ").append (fileObject); //NOI18N |
1748 |
sb.append ("\nPath Type: ").append (pathType); //NOI18N |
1749 |
final Project owner = FileOwnerQuery.getOwner(fileObject); |
1750 |
sb.append ("\nOwner: ").append (owner == null ? "" : ProjectUtils.getInformation(owner).getDisplayName()); //NOI18N |
1751 |
sb.append ("\nClassPathProviders: "); //NOI18N |
1752 |
for (ClassPathProvider impl : Lookup.getDefault ().lookupResult (ClassPathProvider.class).allInstances ()) |
1753 |
sb.append ("\n ").append (impl); //NOI18N |
1754 |
sb.append ("\nProject SourceGroups:"); //NOI18N |
1755 |
final SourceGroup[] sgs = ProjectUtils.getSources(this.project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); |
1756 |
for (SourceGroup sg : sgs) { |
1757 |
sb.append("\n ").append(FileUtil.getFileDisplayName(sg.getRootFolder())); //NOI18N |
1758 |
} |
1759 |
sb.append ("\nProject Source Roots("); //NOI18N |
1760 |
sb.append(System.identityHashCode(roots)); |
1761 |
sb.append("):"); //NOI18N |
1762 |
for (FileObject expectedRoot : expectedRoots) { |
1763 |
sb.append("\n ").append(FileUtil.getFileDisplayName(expectedRoot)); //NOI18N |
1764 |
} |
1765 |
return sb.toString (); |
1766 |
} |
1767 |
|
1768 |
/** |
1769 |
* Asks user for name of main class |
1770 |
* @param mainClass current main class |
1771 |
* @param projectName the name of project |
1772 |
* @param ep project.properties to possibly edit |
1773 |
* @param messgeType type of dialog |
1774 |
* @return true if user selected main class |
1775 |
*/ |
1776 |
@Messages({ |
1777 |
"LBL_MainClassWarning_ChooseMainClass_OK=OK", |
1778 |
"AD_MainClassWarning_ChooseMainClass_OK=N/A", |
1779 |
"# {0} - project name", "LBL_MainClassNotFound=Project {0} does not have a main class set.", |
1780 |
"# {0} - name of class", "# {1} - project name", "LBL_MainClassWrong={0} class wasn''t found in {1} project.", |
1781 |
"CTL_MainClassWarning_Title=Run Project" |
1782 |
}) |
1783 |
private boolean showMainClassWarning(String mainClass, String projectName, EditableProperties ep, MainClassStatus messageType) { |
1784 |
boolean canceled; |
1785 |
final JButton okButton = new JButton(LBL_MainClassWarning_ChooseMainClass_OK()); |
1786 |
okButton.getAccessibleContext().setAccessibleDescription(AD_MainClassWarning_ChooseMainClass_OK()); |
1787 |
|
1788 |
// main class goes wrong => warning |
1789 |
String message; |
1790 |
switch (messageType) { |
1791 |
case UNSET: |
1792 |
message = LBL_MainClassNotFound(projectName); |
1793 |
break; |
1794 |
case SET_BUT_INVALID: |
1795 |
message = LBL_MainClassWrong(mainClass, projectName); |
1796 |
break; |
1797 |
default: |
1798 |
throw new IllegalArgumentException (); |
1799 |
} |
1800 |
final MainClassWarning panel = new MainClassWarning (message,projectSourceRoots.getRoots()); |
1801 |
Object[] options = new Object[] { |
1802 |
okButton, |
1803 |
DialogDescriptor.CANCEL_OPTION |
1804 |
}; |
1805 |
|
1806 |
panel.addChangeListener (new ChangeListener () { |
1807 |
@Override |
1808 |
public void stateChanged (ChangeEvent e) { |
1809 |
if (e.getSource () instanceof MouseEvent && MouseUtils.isDoubleClick (((MouseEvent)e.getSource ()))) { |
1810 |
// click button and the finish dialog with selected class |
1811 |
okButton.doClick (); |
1812 |
} else { |
1813 |
okButton.setEnabled (panel.getSelectedMainClass () != null); |
1814 |
} |
1815 |
} |
1816 |
}); |
1817 |
|
1818 |
okButton.setEnabled (false); |
1819 |
DialogDescriptor desc = new DialogDescriptor (panel, |
1820 |
CTL_MainClassWarning_Title(), |
1821 |
true, options, options[0], DialogDescriptor.BOTTOM_ALIGN, null, null); |
1822 |
desc.setMessageType (DialogDescriptor.INFORMATION_MESSAGE); |
1823 |
Dialog dlg = DialogDisplayer.getDefault ().createDialog (desc); |
1824 |
dlg.setVisible (true); |
1825 |
if (desc.getValue() != options[0]) { |
1826 |
canceled = true; |
1827 |
} else { |
1828 |
mainClass = panel.getSelectedMainClass (); |
1829 |
canceled = false; |
1830 |
ep.put(ProjectProperties.MAIN_CLASS, mainClass == null ? "" : mainClass); |
1831 |
} |
1832 |
dlg.dispose(); |
1833 |
|
1834 |
return canceled; |
1835 |
} |
1836 |
|
1837 |
@Messages({ |
1816 |
@Messages({ |
1838 |
"# {0} - file name", "CTL_FileMultipleMain=The file {0} has more main classes.", |
1817 |
"# {0} - file name", "CTL_FileMultipleMain=The file {0} has more main classes.", |
1839 |
"CTL_FileMainClass_Title=Run File" |
1818 |
"CTL_FileMainClass_Title=Run File" |
Lines 2077-2100
Link Here
|
2077 |
Set<String> createConcealedProperties(@NonNull String command, @NonNull Lookup context); |
2056 |
Set<String> createConcealedProperties(@NonNull String command, @NonNull Lookup context); |
2078 |
} |
2057 |
} |
2079 |
|
2058 |
|
2080 |
/** |
|
|
2081 |
* Callback to find an active project platform. |
2082 |
* By default the {@link BaseActionProvider} finds an active project |
2083 |
* platform using the {@link ProjectProperties#PLATFORM_ACTIVE} property |
2084 |
* among J2SE platforms. When a project type needs to change such a behavior |
2085 |
* the {@link CustomPlatformCallback} provides a possibility for custom |
2086 |
* {@link JavaPlatform} lookup. |
2087 |
* @since 1.61 |
2088 |
*/ |
2089 |
public interface CustomPlatformCallback extends Callback { |
2090 |
/** |
2091 |
* Returns the active project platform. |
2092 |
* @return the active {@link JavaPlatform} or null in case of broken platform. |
2093 |
*/ |
2094 |
@CheckForNull |
2095 |
JavaPlatform getActivePlatform(); |
2096 |
} |
2097 |
|
2098 |
public static final class CallbackImpl implements Callback { |
2059 |
public static final class CallbackImpl implements Callback { |
2099 |
|
2060 |
|
2100 |
private ClassPathProviderImpl cp; |
2061 |
private ClassPathProviderImpl cp; |