001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.etl.project;
020:
021: import java.beans.PropertyChangeListener;
022: import java.beans.PropertyChangeSupport;
023: import java.io.IOException;
024: import java.io.File;
025: import javax.swing.Icon;
026: import javax.swing.ImageIcon;
027: import net.java.hulp.i18n.Logger;
028: import org.netbeans.api.java.project.JavaProjectConstants;
029: import org.netbeans.api.project.FileOwnerQuery;
030: import org.netbeans.api.project.Project;
031: import org.netbeans.api.project.ProjectManager;
032: import org.netbeans.api.project.ant.AntArtifact;
033: import org.netbeans.modules.compapp.projects.base.ui.IcanproCustomizerProvider;
034: import org.netbeans.modules.compapp.projects.base.ui.IcanproLogicalViewProvider;
035: import org.netbeans.modules.compapp.projects.base.ui.customizer.IcanproProjectProperties;
036: import org.netbeans.api.project.ProjectInformation;
037: import org.netbeans.modules.compapp.projects.base.ProjectPropertyProvider;
038: import org.netbeans.spi.project.SubprojectProvider;
039: import org.netbeans.spi.project.support.ant.AntProjectEvent;
040: import org.netbeans.spi.project.support.ant.AntProjectHelper;
041: import org.netbeans.spi.project.support.ant.AntProjectListener;
042: import org.netbeans.spi.project.support.ant.GeneratedFilesHelper;
043: import org.netbeans.spi.project.support.ant.ProjectXmlSavedHook;
044: import org.netbeans.spi.project.ui.PrivilegedTemplates;
045: import org.netbeans.spi.project.ui.RecommendedTemplates;
046: import org.netbeans.spi.project.support.ant.ReferenceHelper;
047: import org.netbeans.spi.project.support.ant.PropertyEvaluator;
048: import org.netbeans.spi.project.support.ant.SourcesHelper;
049: import org.netbeans.spi.project.ui.ProjectOpenedHook;
050: import org.netbeans.spi.queries.FileBuiltQueryImplementation;
051: import org.openide.ErrorManager;
052: import org.openide.filesystems.FileObject;
053: import org.openide.util.Lookup;
054: import org.openide.util.Mutex;
055: import org.openide.util.Utilities;
056: import org.openide.util.lookup.Lookups;
057: import org.netbeans.modules.compapp.projects.base.spi.JbiArtifactProvider;
058: import org.netbeans.modules.etl.project.ui.EtlproLogicalViewProvider;
059: import org.netbeans.spi.java.project.support.ui.BrokenReferencesSupport;
060: import org.netbeans.spi.project.AuxiliaryConfiguration;
061: import org.netbeans.spi.project.support.ant.EditableProperties;
062: import org.openide.modules.InstalledFileLocator;
063: import org.w3c.dom.Element;
064: import org.w3c.dom.Node;
065: import org.w3c.dom.NodeList;
066: import org.w3c.dom.Text;
067:
068: /**
069: * Represents one ejb module project
070: * @author Chris Webster
071: */
072: public final class EtlproProject implements Project,
073: AntProjectListener, ProjectPropertyProvider {
074:
075: private static transient final Logger mLogger = LogUtil
076: .getLogger(EtlproProject.class.getName());
077: private static transient final Localizer mLoc = Localizer.get();
078: private static final Icon PROJECT_ICON = new ImageIcon(
079: Utilities
080: .loadImage("org/netbeans/modules/etl/project/ui/resources/etlproProjectIcon.gif")); // NOI18N
081: public static final String SOURCES_TYPE_ICANPRO = "BIZPRO";
082: public static final String MODULE_INSTALL_NAME = "modules/org-netbeans-modules-etl-project.jar";
083: public static final String MODULE_INSTALL_CBN = "org.netbeans.modules.etl.project";
084: public static final String MODULE_INSTALL_DIR = "module.install.dir";
085: public static final String COMMAND_GENWSDL = "gen-wsdl";
086: public static final String COMMAND_SCHEMA = "gen-schema";
087: public static final String COMMAND_BULK_LOADER = "bulk-loader";
088: private final AntProjectHelper helper;
089: private final PropertyEvaluator eval;
090: private final ReferenceHelper refHelper;
091: private final GeneratedFilesHelper genFilesHelper;
092: private final Lookup lookup;
093:
094: public EtlproProject(final AntProjectHelper helper)
095: throws IOException {
096: this .helper = helper;
097: eval = createEvaluator();
098: AuxiliaryConfiguration aux = helper
099: .createAuxiliaryConfiguration();
100: refHelper = new ReferenceHelper(helper, aux, helper
101: .getStandardPropertyEvaluator());
102: genFilesHelper = new GeneratedFilesHelper(helper);
103: lookup = createLookup(aux);
104: helper.addAntProjectListener(this );
105: }
106:
107: public FileObject getProjectDirectory() {
108: return helper.getProjectDirectory();
109: }
110:
111: public String toString() {
112: return "EtlproProject[" + getProjectDirectory() + "]"; // NOI18N
113: }
114:
115: private PropertyEvaluator createEvaluator() {
116: // XXX might need to use a custom evaluator to handle active platform substitutions... TBD
117: return helper.getStandardPropertyEvaluator();
118: }
119:
120: PropertyEvaluator evaluator() {
121: return eval;
122: }
123:
124: public AntProjectHelper getAntProjectHelper() {
125: return helper;
126: }
127:
128: public ReferenceHelper getReferenceHelper() {
129: return this .refHelper;
130: }
131:
132: public Lookup getLookup() {
133: return lookup;
134: }
135:
136: private Lookup createLookup(AuxiliaryConfiguration aux) {
137: SubprojectProvider spp = refHelper.createSubprojectProvider();
138: FileBuiltQueryImplementation fileBuilt = helper
139: .createGlobFileBuiltQuery(helper
140: .getStandardPropertyEvaluator(),
141: new String[] { "${src.dir}/*.java" }, // NOI18N
142: new String[] { "${build.classes.dir}/*.class" } // NOI18N
143: );
144: final SourcesHelper sourcesHelper = new SourcesHelper(helper,
145: evaluator());
146: String nbBundle1 = mLoc.t("PRSR001: EJB Module");
147: String nbBundle2 = mLoc.t("PRSR001: Source Packages");
148: String webModuleLabel = Localizer.parse(nbBundle1); //NOI18N
149: String srcJavaLabel = Localizer.parse(nbBundle2); //NOI18N
150:
151: sourcesHelper.addPrincipalSourceRoot("${"
152: + IcanproProjectProperties.SOURCE_ROOT + "}",
153: webModuleLabel, /*XXX*/null, null);
154: sourcesHelper.addPrincipalSourceRoot("${"
155: + IcanproProjectProperties.SRC_DIR + "}", srcJavaLabel, /*XXX*/
156: null, null);
157:
158: sourcesHelper.addTypedSourceRoot("${"
159: + IcanproProjectProperties.SRC_DIR + "}",
160: SOURCES_TYPE_ICANPRO, srcJavaLabel, /*XXX*/null, null);
161: sourcesHelper.addTypedSourceRoot("${"
162: + IcanproProjectProperties.SRC_DIR + "}",
163: JavaProjectConstants.SOURCES_TYPE_JAVA, srcJavaLabel, /*XXX*/
164: null, null);
165: ProjectManager.mutex().postWriteRequest(new Runnable() {
166:
167: public void run() {
168: sourcesHelper
169: .registerExternalRoots(FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT);
170: }
171: });
172: return Lookups
173: .fixed(new Object[] {
174: new Info(),
175: aux,
176: helper.createCacheDirectoryProvider(),
177: helper,
178: spp,
179: new EtlproActionProvider(this , helper,
180: refHelper),
181: new EtlproLogicalViewProvider(this , helper,
182: evaluator(), spp, refHelper),
183: new IcanproCustomizerProvider(this , helper,
184: refHelper),
185: new JbiArtifactProviderImpl(),
186: new ProjectXmlSavedHookImpl(),
187: new ProjectOpenedHookImpl(),
188: new EtlProjectOperations(this ),
189: fileBuilt,
190: new RecommendedTemplatesImpl(),
191: refHelper,
192: sourcesHelper.createSources(),
193: helper
194: .createSharabilityQuery(
195: evaluator(),
196: new String[] { "${"
197: + IcanproProjectProperties.SOURCE_ROOT
198: + "}" },
199: new String[] {
200: "${"
201: + IcanproProjectProperties.BUILD_DIR
202: + "}",
203: "${"
204: + IcanproProjectProperties.DIST_DIR
205: + "}" }) });
206: }
207:
208: public void configurationXmlChanged(AntProjectEvent ev) {
209: if (ev.getPath().equals(AntProjectHelper.PROJECT_XML_PATH)) {
210: // Could be various kinds of changes, but name & displayName might have changed.
211: Info info = (Info) getLookup().lookup(
212: ProjectInformation.class);
213: info.firePropertyChange(ProjectInformation.PROP_NAME);
214: info
215: .firePropertyChange(ProjectInformation.PROP_DISPLAY_NAME);
216: }
217: }
218:
219: public void propertiesChanged(AntProjectEvent ev) {
220: // currently ignored
221: //TODO: should not be ignored!
222: }
223:
224: String getBuildXmlName() {
225: String storedName = helper.getStandardPropertyEvaluator()
226: .getProperty(IcanproProjectProperties.BUILD_FILE);
227: return storedName == null ? GeneratedFilesHelper.BUILD_XML_PATH
228: : storedName;
229: }
230:
231: // Package private methods -------------------------------------------------
232: FileObject getSourceDirectory() {
233: String srcDir = helper.getStandardPropertyEvaluator()
234: .getProperty("src.dir"); // NOI18N
235: return helper.resolveFileObject(srcDir);
236: }
237:
238: /** Return configured project name. */
239: public String getName() {
240: return (String) ProjectManager.mutex().readAccess(
241: new Mutex.Action() {
242:
243: public Object run() {
244: Element data = helper
245: .getPrimaryConfigurationData(true);
246: // XXX replace by XMLUtil when that has findElement, findText, etc.
247: NodeList nl = data
248: .getElementsByTagNameNS(
249: EtlproProjectType.PROJECT_CONFIGURATION_NAMESPACE,
250: "name");
251: if (nl.getLength() == 1) {
252: nl = nl.item(0).getChildNodes();
253: if (nl.getLength() == 1
254: && nl.item(0).getNodeType() == Node.TEXT_NODE) {
255: return ((Text) nl.item(0))
256: .getNodeValue();
257: }
258: }
259: return "???"; // NOI18N
260: }
261: });
262: }
263:
264: // Private innerclasses ----------------------------------------------------
265: private final class Info implements ProjectInformation {
266:
267: private final PropertyChangeSupport pcs = new PropertyChangeSupport(
268: this );
269:
270: Info() {
271: }
272:
273: void firePropertyChange(String prop) {
274: pcs.firePropertyChange(prop, null, null);
275: }
276:
277: public String getName() {
278: return EtlproProject.this .getName();
279: }
280:
281: public String getDisplayName() {
282: return EtlproProject.this .getName();
283: }
284:
285: public Icon getIcon() {
286: return PROJECT_ICON;
287: }
288:
289: public Project getProject() {
290: return EtlproProject.this ;
291: }
292:
293: public void addPropertyChangeListener(
294: PropertyChangeListener listener) {
295: pcs.addPropertyChangeListener(listener);
296: }
297:
298: public void removePropertyChangeListener(
299: PropertyChangeListener listener) {
300: pcs.removePropertyChangeListener(listener);
301: }
302: }
303:
304: private final class ProjectXmlSavedHookImpl extends
305: ProjectXmlSavedHook {
306:
307: ProjectXmlSavedHookImpl() {
308: }
309:
310: protected void projectXmlSaved() throws IOException {
311: genFilesHelper.refreshBuildScript(
312: GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
313: EtlproProject.class
314: .getResource("resources/build-impl.xsl"),
315: false);
316: genFilesHelper.refreshBuildScript(getBuildXmlName(),
317: EtlproProject.class
318: .getResource("resources/build.xsl"), false);
319: }
320: }
321:
322: private final class ProjectOpenedHookImpl extends ProjectOpenedHook {
323:
324: ProjectOpenedHookImpl() {
325: }
326:
327: protected void projectOpened() {
328: try {
329: // Check up on build scripts.
330: genFilesHelper
331: .refreshBuildScript(
332: GeneratedFilesHelper.BUILD_IMPL_XML_PATH,
333: EtlproProject.class
334: .getResource("resources/build-impl.xsl"),
335: true);
336: genFilesHelper.refreshBuildScript(getBuildXmlName(),
337: EtlproProject.class
338: .getResource("resources/build.xsl"),
339: true);
340: } catch (IOException e) {
341: ErrorManager.getDefault().notify(
342: ErrorManager.INFORMATIONAL, e);
343: }
344:
345: // Make it easier to run headless builds on the same machine at least.
346: ProjectManager.mutex().writeAccess(new Mutex.Action() {
347:
348: public Object run() {
349: EditableProperties ep = helper
350: .getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH);
351: ep.setProperty("netbeans.user", System
352: .getProperty("netbeans.user"));
353: ep.setProperty("netbeans.home", System
354: .getProperty("netbeans.home"));
355: File f = InstalledFileLocator.getDefault().locate(
356: MODULE_INSTALL_NAME, MODULE_INSTALL_CBN,
357: false);
358: if (f != null) {
359: ep.setProperty(MODULE_INSTALL_DIR, f
360: .getParentFile().getPath());
361: }
362:
363: helper.putProperties(
364: AntProjectHelper.PRIVATE_PROPERTIES_PATH,
365: ep);
366: try {
367: ProjectManager.getDefault().saveProject(
368: EtlproProject.this );
369: } catch (IOException e) {
370: ErrorManager.getDefault().notify(e);
371: }
372: return null;
373: }
374: });
375:
376: if (IcanproLogicalViewProvider.hasBrokenLinks(helper,
377: refHelper)) {
378: BrokenReferencesSupport.showAlert();
379: }
380: }
381:
382: protected void projectClosed() {
383: // Probably unnecessary, but just in case:
384: try {
385: ProjectManager.getDefault().saveProject(
386: EtlproProject.this );
387: } catch (IOException e) {
388: ErrorManager.getDefault().notify(e);
389: }
390: }
391: }
392:
393: public void setName(final String name) {
394: ProjectManager.mutex().writeAccess(new Mutex.Action() {
395: public Object run() {
396: Element data = helper.getPrimaryConfigurationData(true);
397: NodeList nl = data
398: .getElementsByTagNameNS(
399: EtlproProjectType.PROJECT_CONFIGURATION_NAMESPACE,
400: "name");
401: Element nameEl;
402: if (nl.getLength() == 1) {
403: nameEl = (Element) nl.item(0);
404: NodeList deadKids = nameEl.getChildNodes();
405: while (deadKids.getLength() > 0) {
406: nameEl.removeChild(deadKids.item(0));
407: }
408: } else {
409: nameEl = data
410: .getOwnerDocument()
411: .createElementNS(
412: EtlproProjectType.PROJECT_CONFIGURATION_NAMESPACE,
413: "name");
414: data.insertBefore(nameEl, data.getChildNodes()
415: .item(0));
416: }
417: nameEl.appendChild(data.getOwnerDocument()
418: .createTextNode(name));
419: helper.putPrimaryConfigurationData(data, true);
420: return null;
421: }
422: });
423: }
424:
425: /**
426: * Exports the main JAR as an official build product for use from other scripts.
427: * The type of the artifact will be {@link AntArtifact}.
428: */
429: private final class JbiArtifactProviderImpl implements
430: JbiArtifactProvider {
431:
432: public AntArtifact[] getBuildArtifacts() {
433: return new AntArtifact[] { helper
434: .createSimpleAntArtifact(
435: JbiArtifactProvider.ARTIFACT_TYPE_JBI_ASA
436: + ":"
437: + helper
438: .getStandardPropertyEvaluator()
439: .getProperty(
440: IcanproProjectProperties.JBI_SETYPE_PREFIX),
441: IcanproProjectProperties.SE_DEPLOYMENT_JAR,
442: helper.getStandardPropertyEvaluator(),
443: "dist_se", "clean"), // NOI18N
444: };
445: }
446:
447: public String getJbiServiceAssemblyType() {
448: return helper.getStandardPropertyEvaluator().getProperty(
449: IcanproProjectProperties.JBI_SETYPE_PREFIX);
450: }
451: }
452:
453: public IcanproProjectProperties getProjectProperties() {
454: return new IcanproProjectProperties(this , helper, refHelper,
455: EtlproProjectType.PROJECT_CONFIGURATION_NAMESPACE);
456: }
457:
458: private static final class RecommendedTemplatesImpl implements
459: RecommendedTemplates, PrivilegedTemplates {
460:
461: // List of primarily supported templates
462:
463: private static final String[] TYPES = new String[] { "SOA_ETL", // NOI18N
464: "XML", // NOI18N
465: "simple-files" // NOI18N
466: };
467: private static final String[] PRIVILEGED_NAMES = new String[] { "Templates/CAPS/ETL.etl", };
468:
469: public String[] getRecommendedTypes() {
470: return TYPES;
471: }
472:
473: public String[] getPrivilegedTemplates() {
474: return PRIVILEGED_NAMES;
475: }
476:
477: }
478: }
|