2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.j2ee.clientproject;
44
import java.beans.PropertyChangeEvent;
45
import java.beans.PropertyChangeListener;
46
import java.beans.PropertyChangeSupport;
48
import java.io.IOException;
49
import java.lang.ref.WeakReference;
51
import java.util.Arrays;
52
import java.util.LinkedList;
53
import java.util.List;
54
import java.util.logging.Level;
55
import java.util.logging.Logger;
56
import javax.swing.Icon;
57
import javax.swing.ImageIcon;
58
import javax.swing.JButton;
59
import org.netbeans.api.java.classpath.ClassPath;
60
import org.netbeans.api.java.classpath.GlobalPathRegistry;
61
import org.netbeans.api.java.project.JavaProjectConstants;
62
import org.netbeans.api.project.FileOwnerQuery;
63
import org.netbeans.api.project.Project;
64
import org.netbeans.api.project.ProjectInformation;
65
import org.netbeans.api.project.ProjectManager;
66
import org.netbeans.api.project.ant.AntArtifact;
67
import org.netbeans.api.project.ant.AntBuildExtender;
68
import org.netbeans.modules.j2ee.api.ejbjar.Car;
69
import org.netbeans.modules.j2ee.clientproject.classpath.AppClientProjectClassPathExtender;
70
import org.netbeans.modules.j2ee.clientproject.classpath.ClassPathProviderImpl;
71
import org.netbeans.modules.j2ee.clientproject.classpath.ClassPathSupport;
72
import org.netbeans.modules.j2ee.clientproject.queries.AppClientProjectEncodingQueryImpl;
73
import org.netbeans.modules.j2ee.clientproject.queries.CompiledSourceForBinaryQuery;
74
import org.netbeans.modules.j2ee.clientproject.queries.JavadocForBinaryQueryImpl;
75
import org.netbeans.modules.j2ee.clientproject.queries.SourceLevelQueryImpl;
76
import org.netbeans.modules.j2ee.clientproject.queries.UnitTestForSourceQueryImpl;
77
import org.netbeans.modules.j2ee.clientproject.ui.AppClientLogicalViewProvider;
78
import org.netbeans.modules.j2ee.clientproject.ui.customizer.AppClientProjectProperties;
79
import org.netbeans.modules.j2ee.clientproject.ui.customizer.CustomizerProviderImpl;
80
import org.netbeans.modules.j2ee.clientproject.wsclient.AppClientProjectJAXWSClientSupport;
81
import org.netbeans.modules.j2ee.clientproject.wsclient.AppClientProjectJAXWSVersionProvider;
82
import org.netbeans.modules.j2ee.clientproject.wsclient.AppClientProjectWebServicesClientSupport;
83
import org.netbeans.modules.j2ee.clientproject.wsclient.AppClientProjectWebServicesSupportProvider;
84
import org.netbeans.modules.j2ee.common.ui.BrokenServerSupport;
85
import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment;
86
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eePlatform;
87
import org.netbeans.modules.j2ee.spi.ejbjar.CarFactory;
88
import org.netbeans.modules.websvc.api.client.WebServicesClientSupport;
89
import org.netbeans.modules.websvc.api.jaxws.client.JAXWSClientSupport;
90
import org.netbeans.modules.websvc.api.jaxws.project.WSUtils;
91
import org.netbeans.modules.websvc.spi.client.WebServicesClientSupportFactory;
92
import org.netbeans.modules.websvc.spi.jaxws.client.JAXWSClientSupportFactory;
93
import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport;
94
import org.netbeans.spi.project.AuxiliaryConfiguration;
95
import org.netbeans.spi.project.SubprojectProvider;
96
import org.netbeans.spi.project.ant.AntArtifactProvider;
97
import org.netbeans.spi.project.ant.AntBuildExtenderFactory;
98
import org.netbeans.spi.project.ant.AntBuildExtenderImplementation;
99
import org.netbeans.spi.project.support.LookupProviderSupport;
100
import org.netbeans.spi.project.support.ant.AntProjectEvent;
101
import org.netbeans.spi.project.support.ant.AntProjectHelper;
102
import org.netbeans.spi.project.support.ant.AntProjectListener;
103
import org.netbeans.spi.project.support.ant.EditableProperties;
104
import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
105
import org.netbeans.spi.project.support.ant.ProjectXmlSavedHook;
106
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
107
import org.netbeans.spi.project.support.ant.PropertyUtils;
108
import org.netbeans.spi.project.support.ant.ReferenceHelper;
109
import org.netbeans.spi.project.support.ant.SourcesHelper;
110
import org.netbeans.spi.project.ui.PrivilegedTemplates;
111
import org.netbeans.spi.project.ui.ProjectOpenedHook;
112
import org.netbeans.spi.project.ui.RecommendedTemplates;
113
import org.netbeans.spi.project.ui.support.UILookupMergerSupport;
114
import org.openide.DialogDisplayer;
115
import org.openide.NotifyDescriptor;
116
import org.openide.filesystems.FileAttributeEvent;
117
import org.openide.filesystems.FileChangeListener;
118
import org.openide.filesystems.FileEvent;
119
import org.openide.filesystems.FileObject;
120
import org.openide.filesystems.FileRenameEvent;
121
import org.openide.filesystems.FileSystem.AtomicAction;
122
import org.openide.filesystems.FileUtil;
123
import org.openide.loaders.DataObject;
124
import org.openide.loaders.DataObjectNotFoundException;
125
import org.openide.util.Exceptions;
126
import org.openide.util.Lookup;
127
import org.openide.util.Mutex;
128
import org.openide.util.NbBundle;
129
import org.openide.util.RequestProcessor;
130
import org.openide.util.Utilities;
131
import org.openide.util.lookup.Lookups;
132
import org.w3c.dom.Element;
133
import org.w3c.dom.Node;
134
import org.w3c.dom.NodeList;
135
import org.w3c.dom.Text;
138
* Represents one plain Application Client project.
139
* @author Jesse Glick, et al.
141
public final class AppClientProject implements Project, AntProjectListener, FileChangeListener {
143
private static final Icon CAR_PROJECT_ICON = new ImageIcon(Utilities.loadImage("org/netbeans/modules/j2ee/clientproject/ui/resources/appclient.gif")); // NOI18N
145
private final AuxiliaryConfiguration aux;
146
private final AntProjectHelper helper;
147
private final PropertyEvaluator eval;
148
private final ReferenceHelper refHelper;
149
private final GeneratedFilesHelper genFilesHelper;
150
private final Lookup lookup;
151
private final UpdateHelper updateHelper;
152
private MainClassUpdater mainClassUpdater;
153
private SourceRoots sourceRoots;
154
private SourceRoots testRoots;
157
private AppClientProjectWebServicesClientSupport carProjectWebServicesClientSupport;
158
private AppClientProjectJAXWSClientSupport jaxWsClientSupport;
159
private WebServicesClientSupport apiWebServicesClientSupport;
160
private JAXWSClientSupport apiJAXWSClientSupport;
162
private PropertyChangeListener j2eePlatformListener;
163
private final AppClientProvider appClient;
164
private final Car apiJar;
165
private JarContainerImpl enterpriseResourceSupport;
166
private FileObject libFolder;
167
private final AppClientProjectClassPathExtender classpathExtender;
168
private final ClassPathProviderImpl cpProvider;
170
// use AntBuildExtender to enable Ant Extensibility
171
private AntBuildExtender buildExtender;
173
AppClientProject(AntProjectHelper helper) throws IOException {
174
this.helper = helper;
175
eval = createEvaluator();
176
aux = helper.createAuxiliaryConfiguration();
177
refHelper = new ReferenceHelper(helper, aux, eval);
178
buildExtender = AntBuildExtenderFactory.createAntExtender(new AppClientExtenderImplementation());
179
genFilesHelper = new GeneratedFilesHelper(helper, buildExtender);
180
this.updateHelper = new UpdateHelper(this, this.helper, this.aux, this.genFilesHelper,
181
UpdateHelper.createDefaultNotifier());
182
carProjectWebServicesClientSupport = new AppClientProjectWebServicesClientSupport(this, helper, refHelper);
183
jaxWsClientSupport = new AppClientProjectJAXWSClientSupport(this, helper);
184
apiWebServicesClientSupport = WebServicesClientSupportFactory.createWebServicesClientSupport(carProjectWebServicesClientSupport);
185
apiJAXWSClientSupport = JAXWSClientSupportFactory.createJAXWSClientSupport(jaxWsClientSupport);
186
cpProvider = new ClassPathProviderImpl(this.helper, evaluator(), getSourceRoots(),getTestSourceRoots());
187
appClient = new AppClientProvider(this, helper, cpProvider);
188
apiJar = CarFactory.createCar(appClient);
189
enterpriseResourceSupport = new JarContainerImpl(this, refHelper, helper);
190
classpathExtender = new AppClientProjectClassPathExtender(this, updateHelper, evaluator(), refHelper);
191
lookup = createLookup(aux, cpProvider);
192
helper.addAntProjectListener(this);
196
* Returns the project directory
197
* @return the directory the project is located in
199
public FileObject getProjectDirectory() {
200
return helper.getProjectDirectory();
204
public String toString() {
205
return "CarProject[" + getProjectDirectory() + "]"; // NOI18N
208
private PropertyEvaluator createEvaluator() {
209
// XXX might need to use a custom evaluator to handle active platform substitutions... TBD
210
// It is currently safe to not use the UpdateHelper for PropertyEvaluator; UH.getProperties() delegates to APH
211
return helper.getStandardPropertyEvaluator();
214
public PropertyEvaluator evaluator() {
218
public ReferenceHelper getReferenceHelper() {
219
return this.refHelper;
222
public UpdateHelper getUpdateHelper() {
223
return this.updateHelper;
226
public Lookup getLookup() {
230
public AntProjectHelper getAntProjectHelper() {
234
private Lookup createLookup(AuxiliaryConfiguration aux, ClassPathProviderImpl cpProvider) {
235
SubprojectProvider spp = refHelper.createSubprojectProvider();
237
final SourcesHelper sourcesHelper = new SourcesHelper(helper, evaluator());
238
String configFilesLabel = NbBundle.getMessage(AppClientLogicalViewProvider.class, "LBL_Node_ConfFiles"); //NOI18N
240
//sourcesHelper.addPrincipalSourceRoot("${"+AppClientProjectProperties.SOURCE_ROOT+"}", ejbModuleLabel, /*XXX*/null, null);
241
sourcesHelper.addPrincipalSourceRoot("${"+AppClientProjectProperties.META_INF+"}", configFilesLabel, /*XXX*/null, null); // NOI18N
243
ProjectManager.mutex().postWriteRequest(new Runnable() {
245
sourcesHelper.registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
248
Lookup base = Lookups.fixed(new Object[] {
251
helper.createCacheDirectoryProvider(),
253
new AppClientActionProvider( this, helper, this.updateHelper ),
254
new AppClientLogicalViewProvider(this, this.updateHelper, evaluator(), refHelper),
255
// new J2SECustomizerProvider(this, this.updateHelper, evaluator(), refHelper),
256
new CustomizerProviderImpl(this, this.updateHelper, evaluator(), refHelper, this.genFilesHelper),
257
new ClassPathProviderMerger(cpProvider),
258
new CompiledSourceForBinaryQuery(this.helper, evaluator(),getSourceRoots(),getTestSourceRoots()), //Does not use APH to get/put properties/cfgdata
259
new JavadocForBinaryQueryImpl(this.helper, evaluator()), //Does not use APH to get/put properties/cfgdata
260
new AntArtifactProviderImpl(),
261
new ProjectXmlSavedHookImpl(),
262
UILookupMergerSupport.createProjectOpenHookMerger(new ProjectOpenedHookImpl()),
263
new UnitTestForSourceQueryImpl(getSourceRoots(),getTestSourceRoots()),
264
new SourceLevelQueryImpl(evaluator()),
265
new AppClientSources(this.helper, evaluator(), getSourceRoots(), getTestSourceRoots()),
266
new AppClientSharabilityQuery(this.helper, evaluator(), getSourceRoots(), getTestSourceRoots()), //Does not use APH to get/put properties/cfgdata
267
new AppClientFileBuiltQuery(this.helper, evaluator(),getSourceRoots(),getTestSourceRoots()), //Does not use APH to get/put properties/cfgdata
268
new AppClientProjectEncodingQueryImpl(evaluator()),
269
new RecommendedTemplatesImpl(this.updateHelper),
272
AppClientProject.this, // never cast an externally obtained Project to AppClientProject - use lookup instead
273
new AppClientProjectOperations(this),
274
new AppClientProjectWebServicesSupportProvider(),
276
new ProjectAppClientProvider(this),
278
new AppClientPersistenceProvider(this, evaluator(), cpProvider),
279
new AppClientProjectJAXWSVersionProvider(helper),
280
enterpriseResourceSupport,
281
UILookupMergerSupport.createPrivilegedTemplatesMerger(),
282
UILookupMergerSupport.createRecommendedTemplatesMerger(),
283
LookupProviderSupport.createSourcesMerger()
285
return LookupProviderSupport.createCompositeLookup(base, "Projects/org-netbeans-modules-j2ee-clientproject/Lookup"); //NOI18N
288
public ClassPathProviderImpl getClassPathProvider () {
289
return this.cpProvider;
292
public void configurationXmlChanged(AntProjectEvent ev) {
293
if (ev.getPath().equals(AntProjectHelper.PROJECT_XML_PATH)) {
294
// Could be various kinds of changes, but name & displayName might have changed.
295
Info info = (Info)getLookup().lookup(ProjectInformation.class);
296
info.firePropertyChange(ProjectInformation.PROP_NAME);
297
info.firePropertyChange(ProjectInformation.PROP_DISPLAY_NAME);
301
public void propertiesChanged(AntProjectEvent ev) {
302
// currently ignored (probably better to listen to evaluator() if you need to)
305
// Package private methods -------------------------------------------------
308
* Returns the source roots of this project
309
* @return project's source roots
311
public synchronized SourceRoots getSourceRoots() {
312
if (this.sourceRoots == null) { //Local caching, no project metadata access
313
this.sourceRoots = new SourceRoots(this.updateHelper, evaluator(), getReferenceHelper(), "source-roots", false, "src.{0}{1}.dir"); //NOI18N
315
return this.sourceRoots;
318
public synchronized SourceRoots getTestSourceRoots() {
319
if (this.testRoots == null) { //Local caching, no project metadata access
320
this.testRoots = new SourceRoots(this.updateHelper, evaluator(), getReferenceHelper(), "test-roots", true, "test.{0}{1}.dir"); //NOI18N
322
return this.testRoots;
325
File getTestClassesDirectory() {
326
String testClassesDir = evaluator().getProperty(AppClientProjectProperties.BUILD_TEST_CLASSES_DIR);
327
if (testClassesDir == null) {
330
return helper.resolveFile(testClassesDir);
333
// Currently unused (but see #47230):
334
/** Store configured project name. */
335
public void setName(final String name) {
336
ProjectManager.mutex().writeAccess(new Runnable() {
338
Element data = helper.getPrimaryConfigurationData(true);
339
// XXX replace by XMLUtil when that has findElement, findText, etc.
340
NodeList nl = data.getElementsByTagNameNS(AppClientProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); // NOI18N
342
if (nl.getLength() == 1) {
343
nameEl = (Element) nl.item(0);
344
NodeList deadKids = nameEl.getChildNodes();
345
while (deadKids.getLength() > 0) {
346
nameEl.removeChild(deadKids.item(0));
349
nameEl = data.getOwnerDocument().createElementNS(AppClientProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); // NOI18N
350
data.insertBefore(nameEl, /* OK if null */data.getChildNodes().item(0));
352
nameEl.appendChild(data.getOwnerDocument().createTextNode(name));
353
helper.putPrimaryConfigurationData(data, true);
358
/** Return configured project name. */
359
public String getName() {
360
return ProjectManager.mutex().readAccess(new Mutex.Action<String>() {
361
public String run() {
362
Element data = updateHelper.getPrimaryConfigurationData(true);
363
// XXX replace by XMLUtil when that has findElement, findText, etc.
364
NodeList nl = data.getElementsByTagNameNS(AppClientProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); // NOI18N
365
if (nl.getLength() == 1) {
366
nl = nl.item(0).getChildNodes();
367
if (nl.getLength() == 1 && nl.item(0).getNodeType() == Node.TEXT_NODE) {
368
return ((Text) nl.item(0)).getNodeValue();
371
return "CAR???"; // NOI18N
376
public void fileAttributeChanged (FileAttributeEvent fe) {
379
public void fileChanged (FileEvent fe) {
382
public void fileDataCreated (FileEvent fe) {
383
FileObject fo = fe.getFile ();
384
checkLibraryFolder (fo);
387
public void fileDeleted (FileEvent fe) {
390
public void fileFolderCreated (FileEvent fe) {
393
public void fileRenamed (FileRenameEvent fe) {
394
FileObject fo = fe.getFile ();
395
checkLibraryFolder (fo);
398
private void checkLibraryFolder (FileObject fo) {
399
if (!FileUtil.isArchiveFile(fo)) {
403
if (fo.getParent ().equals (libFolder)) {
405
classpathExtender.addArchiveFile(fo);
406
} catch (IOException e) {
407
Exceptions.printStackTrace(e);
412
public void registerJ2eePlatformListener(final J2eePlatform platform) {
413
// listen to classpath changes
414
j2eePlatformListener = new PropertyChangeListener() {
415
public void propertyChange(PropertyChangeEvent evt) {
416
if (evt.getPropertyName().equals(J2eePlatform.PROP_CLASSPATH)) {
417
ProjectManager.mutex().writeAccess(new Runnable() {
419
EditableProperties ep = helper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
420
String classpath = Utils.toClasspathString(platform.getClasspathEntries());
421
ep.setProperty(AppClientProjectProperties.J2EE_PLATFORM_CLASSPATH, classpath);
422
helper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
424
ProjectManager.getDefault().saveProject(AppClientProject.this);
425
} catch (IOException e) {
426
Exceptions.printStackTrace(e);
433
platform.addPropertyChangeListener(j2eePlatformListener);
436
public void unregisterJ2eePlatformListener(J2eePlatform platform) {
437
if (j2eePlatformListener != null) {
438
platform.removePropertyChangeListener(j2eePlatformListener);
442
public Car getAPICar() {
446
public AppClientProvider getCarModule() {
451
private String getProperty(String path, String name) {
452
return helper.getProperties(path).getProperty(name);
455
String getBuildXmlName() {
456
String storedName = helper.getStandardPropertyEvaluator().getProperty(AppClientProjectProperties.BUILD_FILE);
457
return storedName == null ? GeneratedFilesHelper.BUILD_XML_PATH : storedName;
461
* Refreshes the build-impl.xml script. If it was modified by the user, it
462
* displays a confirmation dialog.
464
* @param askUserIfFlags only display the dialog if the state of the build script
465
* contains these flags (along with {@link GeneratedFilesHelper#FLAG_MODIFIED},
466
* which is always checked)
467
* @param askInCurrentThread if false, asks in another thread
469
private void refreshBuildImplXml(int askUserIfFlags, boolean askInCurrentThread) {
470
askUserIfFlags |= GeneratedFilesHelper.FLAG_MODIFIED;
471
int flags = genFilesHelper.getBuildScriptState(
472
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
473
AppClientProject.class.getResource("resources/build-impl.xsl")); // NOI18N
474
if ((flags & askUserIfFlags) == askUserIfFlags) {
475
Runnable run = new Runnable () {
477
JButton updateOption = new JButton (NbBundle.getMessage(AppClientProject.class, "CTL_Regenerate"));
478
if (DialogDisplayer.getDefault().notify(
479
new NotifyDescriptor (NbBundle.getMessage(AppClientProject.class,"TXT_BuildImplRegenerate"),
480
NbBundle.getMessage(AppClientProject.class,"TXT_BuildImplRegenerateTitle"),
481
NotifyDescriptor.DEFAULT_OPTION,
482
NotifyDescriptor.WARNING_MESSAGE,
485
NotifyDescriptor.CANCEL_OPTION
487
updateOption)) == updateOption) {
489
genFilesHelper.generateBuildScriptFromStylesheet(
490
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
491
AppClientProject.class.getResource("resources/build-impl.xsl")); // NOI18N
492
} catch (IOException e) {
493
Exceptions.printStackTrace(e);
494
} catch (IllegalStateException e) {
495
Exceptions.printStackTrace(e);
500
if (askInCurrentThread) {
503
RequestProcessor.getDefault().post(run);
507
genFilesHelper.refreshBuildScript(
508
GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
509
AppClientProject.class.getResource("resources/build-impl.xsl"), // NOI18N
511
} catch (IOException e) {
512
Exceptions.printStackTrace(e);
517
// Private innerclasses ----------------------------------------------------
518
//when #110886 gets implemented, this class is obsolete
519
private final class Info implements ProjectInformation {
521
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
523
private WeakReference<String> cachedName = null;
527
void firePropertyChange(String prop) {
528
pcs.firePropertyChange(prop, null, null);
534
public String getName() {
535
return PropertyUtils.getUsablePropertyName(getDisplayName());
538
public String getDisplayName() {
540
if (cachedName != null) {
541
String dn = cachedName.get();
547
String dn = ProjectManager.mutex().readAccess(new Mutex.Action<String>() {
548
public String run() {
549
Element data = updateHelper.getPrimaryConfigurationData(true);
550
// XXX replace by XMLUtil when that has findElement, findText, etc.
551
NodeList nl = data.getElementsByTagNameNS(AppClientProjectType.PROJECT_CONFIGURATION_NAMESPACE, "name"); // NOI18N
552
if (nl.getLength() == 1) {
553
nl = nl.item(0).getChildNodes();
554
if (nl.getLength() == 1 && nl.item(0).getNodeType() == Node.TEXT_NODE) {
555
return ((Text) nl.item(0)).getNodeValue();
558
return "???"; // NOI18N
562
cachedName = new WeakReference<String>(dn);
567
public Icon getIcon() {
568
return CAR_PROJECT_ICON;
571
public Project getProject() {
572
return AppClientProject.this;
575
public void addPropertyChangeListener(PropertyChangeListener listener) {
576
pcs.addPropertyChangeListener(listener);
579
public void removePropertyChangeListener(PropertyChangeListener listener) {
580
pcs.removePropertyChangeListener(listener);
585
private final class ProjectXmlSavedHookImpl extends ProjectXmlSavedHook {
587
ProjectXmlSavedHookImpl() {}
589
protected void projectXmlSaved() throws IOException {
590
refreshBuildImplXml(0, false);
592
genFilesHelper.refreshBuildScript(
594
AppClientProject.class.getResource("resources/build.xsl"), //NOI18N
600
/** Package-private for unit tests only. */
601
final class ProjectOpenedHookImpl extends ProjectOpenedHook {
603
ProjectOpenedHookImpl() {}
605
protected void projectOpened() {
606
// Check up on build scripts.
608
//Check libraries and add them to classpath automatically
609
String libFolderName = helper.getStandardPropertyEvaluator ().getProperty (AppClientProjectProperties.LIBRARIES_DIR);
611
//DDDataObject initialization to be ready to listen on changes (#49656)
613
FileObject ddFO = appClient.getDeploymentDescriptor();
615
DataObject.find(ddFO);
617
} catch (DataObjectNotFoundException ex) {}
619
if (libFolderName != null && helper.resolveFile (libFolderName).isDirectory ()) {
620
libFolder = helper.resolveFileObject(libFolderName);
621
FileObject children [] = libFolder.getChildren ();
622
List<FileObject> libs = new LinkedList<FileObject>();
623
for (int i = 0; i < children.length; i++) {
624
if (FileUtil.isArchiveFile(children[i])) {
625
libs.add(children[i]);
628
FileObject[] libsArray = new FileObject[libs.size()];
629
libs.toArray(libsArray);
630
classpathExtender.addArchiveFiles(AppClientProjectProperties.JAVAC_CLASSPATH, libsArray, ClassPathSupport.ELEMENT_INCLUDED_LIBRARIES);
631
libFolder.addFileChangeListener (AppClientProject.this);
634
// Check up on build scripts.
636
refreshBuildImplXml( GeneratedFilesHelper.FLAG_OLD_PROJECT_XML, true);
638
genFilesHelper.refreshBuildScript(
640
AppClientProject.class.getResource("resources/build.xsl"), //NOI18N
643
String servInstID = getProperty(AntProjectHelper.PRIVATE_PROPERTIES_PATH, AppClientProjectProperties.J2EE_SERVER_INSTANCE);
644
J2eePlatform platform = Deployment.getDefault().getJ2eePlatform(servInstID);
645
if (platform != null) {
646
// updates j2ee.platform.cp & wscompile.cp & reg. j2ee platform listener
647
AppClientProjectProperties.setServerInstance(AppClientProject.this, AppClientProject.this.helper, servInstID);
649
// if there is some server instance of the type which was used
650
// previously do not ask and use it
651
String serverType = getProperty(AntProjectHelper.PROJECT_PROPERTIES_PATH, AppClientProjectProperties.J2EE_SERVER_TYPE);
652
if (serverType != null) {
653
String[] servInstIDs = Deployment.getDefault().getInstancesOfServer(serverType);
654
if (servInstIDs.length > 0) {
655
AppClientProjectProperties.setServerInstance(AppClientProject.this, AppClientProject.this.helper, servInstIDs[0]);
656
platform = Deployment.getDefault().getJ2eePlatform(servInstIDs[0]);
659
if (platform == null) {
660
BrokenServerSupport.showAlert();
663
} catch (IOException e) {
664
Logger.getLogger("global").log(Level.INFO, null, e);
668
// register project's classpaths to GlobalPathRegistry
669
GlobalPathRegistry.getDefault().register(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
670
GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
671
GlobalPathRegistry.getDefault().register(ClassPath.COMPILE, cpProvider.getProjectClassPaths(ClassPath.COMPILE));
673
// initialize the server configuration
674
// it MUST BE called AFTER classpaths are registered to GlobalPathRegistry!
675
// AppClient DDProvider (used here) needs classpath set correctly when resolving Java Extents for annotations
676
appClient.getConfigSupport().ensureConfigurationReady();
678
//register updater of main.class
679
//the updater is active only on the opened projects
680
mainClassUpdater = new MainClassUpdater(AppClientProject.this, eval, updateHelper,
681
cpProvider.getProjectClassPaths(ClassPath.SOURCE)[0], AppClientProjectProperties.MAIN_CLASS);
684
getProjectDirectory().getFileSystem().runAtomicAction(new AtomicAction() {
685
public void run() throws IOException {
686
ProjectManager.mutex().writeAccess(new Runnable() {
694
} catch (IOException e) {
695
Exceptions.printStackTrace(e);
698
AppClientLogicalViewProvider physicalViewProvider = AppClientProject.this.getLookup().lookup(AppClientLogicalViewProvider.class);
699
if (physicalViewProvider != null && physicalViewProvider.hasBrokenLinks()) {
700
BrokenReferencesSupport.showAlert();
704
private void updateProject() {
705
// Make it easier to run headless builds on the same machine at least.
706
EditableProperties ep = updateHelper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
707
File buildProperties = new File(System.getProperty("netbeans.user"), "build.properties"); // NOI18N
708
ep.setProperty("user.properties.file", buildProperties.getAbsolutePath()); //NOI18N
710
// set jaxws.endorsed.dir property (for endorsed mechanism to be used with wsimport, wsgen)
711
WSUtils.setJaxWsEndorsedDirProperty(ep);
713
updateHelper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep);
715
// update a dual build directory project to use a single build directory
716
ep = updateHelper.getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
717
String earBuildDir = ep.getProperty(AppClientProjectProperties.BUILD_EAR_CLASSES_DIR);
718
if (null != earBuildDir) {
719
// there is an BUILD_EAR_CLASSES_DIR property... we may
720
// need to change its value
721
String buildDir = ep.getProperty(AppClientProjectProperties.BUILD_CLASSES_DIR);
722
if (null != buildDir) {
723
// there is a value that we may need to change the
724
// BUILD_EAR_CLASSES_DIR property value to match.
725
if (!buildDir.equals(earBuildDir)) {
726
// the values do not match... update the property and save it
727
ep.setProperty(AppClientProjectProperties.BUILD_EAR_CLASSES_DIR,
729
updateHelper.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH,
733
// the values match and we don't need to do anything
737
// the project doesn't have a BUILD_CLASSES_DIR property
738
// ** This is not an expected state, but if the project
739
// properties evolve, this property may go away...
743
// there isn't a BUILD_EAR_CLASSES_DIR in this project...
744
// so we should not create one, by setting it.
748
ProjectManager.getDefault().saveProject(AppClientProject.this);
749
} catch (IOException e) {
750
Exceptions.printStackTrace(e);
754
protected void projectClosed() {
756
// unregister j2ee platform classpath change listener
757
String servInstID = getProperty(AntProjectHelper.PRIVATE_PROPERTIES_PATH, AppClientProjectProperties.J2EE_SERVER_INSTANCE);
758
J2eePlatform platform = Deployment.getDefault().getJ2eePlatform(servInstID);
759
if (platform != null) {
760
unregisterJ2eePlatformListener(platform);
763
// Probably unnecessary, but just in case:
765
ProjectManager.getDefault().saveProject(AppClientProject.this);
766
} catch (IOException e) {
767
Exceptions.printStackTrace(e);
770
// unregister project's classpaths to GlobalPathRegistry
771
GlobalPathRegistry.getDefault().unregister(ClassPath.BOOT, cpProvider.getProjectClassPaths(ClassPath.BOOT));
772
GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, cpProvider.getProjectClassPaths(ClassPath.SOURCE));
773
GlobalPathRegistry.getDefault().unregister(ClassPath.COMPILE, cpProvider.getProjectClassPaths(ClassPath.COMPILE));
774
if (mainClassUpdater != null) {
775
mainClassUpdater.unregister();
776
mainClassUpdater = null;
782
public WebServicesClientSupport getAPIWebServicesClientSupport() {
783
return apiWebServicesClientSupport;
786
public JAXWSClientSupport getAPIJAXWSClientSupport() {
787
return apiJAXWSClientSupport;
791
* Exports the main JAR as an official build product for use from other scripts.
792
* The type of the artifact will be {@link AntArtifact#TYPE_JAR}.
794
private final class AntArtifactProviderImpl implements AntArtifactProvider {
796
public AntArtifact[] getBuildArtifacts() {
797
return new AntArtifact[] {
798
helper.createSimpleAntArtifact(JavaProjectConstants.ARTIFACT_TYPE_JAR, "dist.jar", helper.getStandardPropertyEvaluator(), "dist", "clean"), // NOI18N
799
//new CarAntArtifact(helper.createSimpleAntArtifact(AppClientProjectConstants.ARTIFACT_TYPE_CAR, "dist.jar", helper.getStandardPropertyEvaluator(), "dist", "clean")), // NOI18N
800
new CarAntArtifact(helper.createSimpleAntArtifact(AppClientProjectConstants.ARTIFACT_TYPE_J2EE_MODULE_IN_EAR_ARCHIVE, "dist.ear.jar", helper.getStandardPropertyEvaluator(), "dist-ear", "clean-ear")) // NOI18N
806
private static final class RecommendedTemplatesImpl implements RecommendedTemplates, PrivilegedTemplates {
808
RecommendedTemplatesImpl(UpdateHelper helper) {
809
this.helper = helper;
812
transient private final UpdateHelper helper;
813
transient private boolean isArchive = false;
815
// List of primarily supported templates
817
private static final String[] APPLICATION_TYPES = new String[] {
818
"java-classes", // NOI18N
819
"java-main-class", // NOI18N
820
"j2ee-types", // NOI18N
821
"java-forms", // NOI18N
822
"gui-java-application", // NOI18N
823
"java-beans", // NOI18N
824
"persistence", // NOI18N
825
"oasis-XML-catalogs", // NOI18N
827
"ant-script", // NOI18N
828
"ant-task", // NOI18N
829
"web-service-clients", // NOI18N
831
"sunresource-types", // NOI18N
832
// "web-types", // NOI18N
835
"simple-files" // NOI18N
838
private static final String[] PRIVILEGED_NAMES = new String[] {
839
"Templates/Classes/Class.java", // NOI18N
840
"Templates/Classes/Package", // NOI18N
841
"Templates/Classes/Interface.java", // NOI18N
842
"Templates/GUIForms/JPanel.java", // NOI18N
843
"Templates/GUIForms/JFrame.java", // NOI18N
844
"Templates/J2EE/CachingServiceLocator.java", //NOI18N
845
"Templates/WebServices/WebServiceClient" // NOI18N
848
private static final String[] APPLICATION_TYPES_ARCHIVE = new String[] {
849
"deployment-descriptor", // NOI18N
853
private static final String[] PRIVILEGED_NAMES_ARCHIVE = new String[] {
854
"Templates/J2EE/applicationClientXml," // NOI18N
857
public String[] getRecommendedTypes() {
858
String[] retVal = null;
861
retVal = APPLICATION_TYPES_ARCHIVE.clone();
863
retVal = APPLICATION_TYPES.clone();
868
public String[] getPrivilegedTemplates() {
869
String[] retVal = null;
872
retVal = PRIVILEGED_NAMES_ARCHIVE.clone();
874
retVal = PRIVILEGED_NAMES.clone();
879
transient private boolean checked = false;
881
private void checkEnvironment() {
883
final Object srcType = helper.getAntProjectHelper().
884
getStandardPropertyEvaluator().getProperty(AppClientProjectProperties.JAVA_SOURCE_BASED);
885
if ("false".equals(srcType)) {
894
private final class CarAntArtifact extends AntArtifact {
896
private final AntArtifact impl;
898
CarAntArtifact(AntArtifact aa) {
903
public String getID() {
904
if (AppClientProjectConstants.ARTIFACT_TYPE_J2EE_MODULE_IN_EAR_ARCHIVE.equals(getType())) {
905
return AppClientProjectConstants.CAR_ANT_ARTIFACT_ID;
910
public String getType() {
911
return impl.getType();
914
public String getTargetName() {
915
return impl.getTargetName();
918
public File getScriptLocation() {
919
return impl.getScriptLocation();
922
public String getCleanTargetName() {
923
return impl.getCleanTargetName();
927
public URI[] getArtifactLocations() {
928
return impl.getArtifactLocations();
932
public Project getProject() {
933
return impl.getProject();
938
private class AppClientExtenderImplementation implements AntBuildExtenderImplementation {
939
//add targets here as required by the external plugins..
940
public List<String> getExtensibleTargets() {
941
String[] targets = new String[] {
942
"-do-init", "-init-check", "-post-clean", "jar", "-pre-pre-compile","-do-compile","-do-compile-single", "-pre-dist" //NOI18N
944
return Arrays.asList(targets);
947
public Project getOwningProject() {
948
return AppClientProject.this;