001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.j2ee.jboss4.config;
043:
044: import java.beans.PropertyChangeEvent;
045: import java.beans.PropertyChangeListener;
046: import java.io.ByteArrayInputStream;
047: import java.io.File;
048: import java.io.IOException;
049: import java.io.OutputStream;
050: import javax.swing.text.BadLocationException;
051: import javax.swing.text.StyledDocument;
052: import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
053: import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eeModule;
054: import org.netbeans.modules.j2ee.deployment.plugins.spi.config.DatasourceConfiguration;
055: import org.netbeans.modules.j2ee.deployment.plugins.spi.config.DeploymentPlanConfiguration;
056: import org.netbeans.modules.j2ee.deployment.plugins.spi.config.ModuleConfiguration;
057: import org.netbeans.modules.j2ee.jboss4.config.gen.EjbRef;
058: import org.netbeans.modules.j2ee.jboss4.config.gen.JbossClient;
059: import org.netbeans.modules.j2ee.jboss4.config.gen.ResourceRef;
060: import org.netbeans.modules.j2ee.jboss4.config.gen.ServiceRef;
061: import org.netbeans.modules.j2ee.jboss4.config.mdb.MessageDestinationSupport;
062: import org.openide.DialogDisplayer;
063: import org.openide.NotifyDescriptor;
064: import org.openide.cookies.EditorCookie;
065: import org.openide.cookies.SaveCookie;
066: import org.openide.filesystems.FileUtil;
067: import org.openide.loaders.DataObject;
068: import org.openide.loaders.DataObjectNotFoundException;
069: import org.openide.util.Exceptions;
070: import org.openide.util.Lookup;
071: import org.openide.util.NbBundle;
072: import org.openide.util.lookup.Lookups;
073:
074: /**
075: *
076: * @author jungi
077: */
078: public class CarDeploymentConfiguration extends
079: JBDeploymentConfiguration implements ModuleConfiguration,
080: DatasourceConfiguration, DeploymentPlanConfiguration,
081: PropertyChangeListener {
082:
083: private File jbossClientFile;
084: private JbossClient jbossClient;
085:
086: /** Creates a new instance of CarDeploymentConfiguration */
087: public CarDeploymentConfiguration(J2eeModule j2eeModule) {
088: super (j2eeModule);
089: jbossClientFile = j2eeModule
090: .getDeploymentConfigurationFile("META-INF/jboss-client.xml"); // NOI18N
091: getJbossClient();
092: if (deploymentDescriptorDO == null) {
093: try {
094: deploymentDescriptorDO = deploymentDescriptorDO
095: .find(FileUtil.toFileObject(jbossClientFile));
096: deploymentDescriptorDO.addPropertyChangeListener(this );
097: } catch (DataObjectNotFoundException donfe) {
098: Exceptions.printStackTrace(donfe);
099: }
100: }
101: // TODO: rewrite
102: // AppClient appClient = (AppClient) j2eeModule.getMetadataModel(J2eeModule.CLIENT_XML);
103: // if (appClient != null) {
104: // appClient.addPropertyChangeListener(this);
105: // }
106: }
107:
108: public void dispose() {
109: // TODO: rewrite
110: // AppClient appClient = (AppClient) j2eeModule.getMetadataModel(J2eeModule.CLIENT_XML);
111: // if (appClient != null) {
112: // appClient.removePropertyChangeListener(this);
113: // }
114: }
115:
116: public Lookup getLookup() {
117: return Lookups.fixed(this );
118: }
119:
120: /**
121: * Return JbossClient graph. If it was not created yet, load it from the file
122: * and cache it. If the file does not exist, generate it.
123: *
124: * @return JbossWeb graph or null if the jboss-web.xml file is not parseable.
125: */
126: public synchronized JbossClient getJbossClient() {
127: if (jbossClient == null) {
128: try {
129: if (jbossClientFile.exists()) {
130: // load configuration if already exists
131: try {
132: jbossClient = JbossClient
133: .createGraph(jbossClientFile);
134: } catch (IOException ioe) {
135: Exceptions.printStackTrace(ioe);
136: } catch (RuntimeException re) {
137: // jboss-web.xml is not parseable, do nothing
138: }
139: } else {
140: // create jboss-web.xml if it does not exist yet
141: jbossClient = generateJbossClient();
142: ResourceConfigurationHelper.writeFile(
143: jbossClientFile, jbossClient);
144: }
145: } catch (ConfigurationException ce) {
146: Exceptions.printStackTrace(ce);
147: }
148: }
149: return jbossClient;
150: }
151:
152: /**
153: * Listen to jboss-web.xml document changes.
154: */
155: public void propertyChange(PropertyChangeEvent evt) {
156: Object newValue = evt.getNewValue();
157: if (evt.getPropertyName() == DataObject.PROP_MODIFIED
158: && evt.getNewValue() == Boolean.FALSE) {
159: if (evt.getSource() == deploymentDescriptorDO) { // dataobject has been modified, jbossWeb graph is out of sync
160: synchronized (this ) {
161: jbossClient = null;
162: }
163: } else {
164: // super.propertyChange(evt);
165: }
166: } else if (evt.getOldValue() == null) {
167: // TODO do we also want to check changes in the application client display name?
168: if (newValue instanceof org.netbeans.modules.j2ee.dd.api.common.ResourceRef) {
169: //a new resource reference added
170: org.netbeans.modules.j2ee.dd.api.common.ResourceRef resourceRef = (org.netbeans.modules.j2ee.dd.api.common.ResourceRef) newValue;
171: try {
172: String resType = resourceRef.getResType();
173: if ("javax.sql.DataSource".equals(resType)) { // NOI18N
174: addResReference(resourceRef.getResRefName());
175: } else if ("javax.mail.Session".equals(resType)) { // NOI18N
176: addMailReference(resourceRef.getResRefName());
177: } else if ("javax.jms.ConnectionFactory"
178: .equals(resType)) { // NOI18N
179: addConnectionFactoryReference(resourceRef
180: .getResRefName());
181: }
182: } catch (ConfigurationException ce) {
183: Exceptions.printStackTrace(ce);
184: }
185: } else if (newValue instanceof org.netbeans.modules.j2ee.dd.api.common.EjbRef) {
186: // a new ejb reference added
187: org.netbeans.modules.j2ee.dd.api.common.EjbRef ejbRef = (org.netbeans.modules.j2ee.dd.api.common.EjbRef) newValue;
188: try {
189: String ejbRefType = ejbRef.getEjbRefType();
190: if ("Session".equals(ejbRefType)
191: || "Entity".equals(ejbRefType)) { // NOI18N
192: addEjbReference(ejbRef.getEjbRefName());
193: }
194: } catch (ConfigurationException ce) {
195: Exceptions.printStackTrace(ce);
196: }
197: } else if (newValue instanceof org.netbeans.modules.j2ee.dd.api.common.ServiceRef) {
198: // a new message destination reference added
199: org.netbeans.modules.j2ee.dd.api.common.ServiceRef serviceRef = (org.netbeans.modules.j2ee.dd.api.common.ServiceRef) newValue;
200: try {
201: addServiceReference(serviceRef.getServiceRefName());
202: } catch (ConfigurationException ce) {
203: Exceptions.printStackTrace(ce);
204: }
205: }
206: }
207: }
208:
209: public void save(OutputStream os) throws ConfigurationException {
210: JbossClient jbossClientDD = getJbossClient();
211: if (jbossClientDD == null) {
212: String msg = NbBundle.getMessage(
213: CarDeploymentConfiguration.class,
214: "MSG_cannotSaveNotParseableConfFile",
215: jbossClientFile.getAbsolutePath());
216: throw new ConfigurationException(msg);
217: }
218: try {
219: jbossClientDD.write(os);
220: } catch (IOException ioe) {
221: String msg = NbBundle.getMessage(
222: CarDeploymentConfiguration.class,
223: "MSG_CannotUpdateFile", jbossClientFile
224: .getAbsolutePath());
225: throw new ConfigurationException(msg, ioe);
226: }
227: }
228:
229: // private helper methods -------------------------------------------------
230:
231: /**
232: * Generate JbossWeb graph.
233: */
234: private JbossClient generateJbossClient() {
235: JbossClient jbossClientDD = new JbossClient();
236: //jbossClientDD.setContextRoot(""); // NOI18N
237: return jbossClientDD;
238: }
239:
240: /**
241: * Add a new resource reference.
242: *
243: * @param name resource reference name
244: */
245: private void addResReference(final String name)
246: throws ConfigurationException {
247: modifyJbossClient(new JbossClientModifier() {
248: public void modify(JbossClient modifiedJbossClient) {
249:
250: // check whether resource not already defined
251: ResourceRef resourceRefs[] = modifiedJbossClient
252: .getResourceRef();
253: for (int i = 0; i < resourceRefs.length; i++) {
254: String rrn = resourceRefs[i].getResRefName();
255: if (name.equals(rrn)) {
256: // already exists
257: return;
258: }
259: }
260:
261: //if it doesn't exist yet, create a new one
262: ResourceRef newRR = new ResourceRef();
263: newRR.setResRefName(name);
264: newRR.setJndiName(JBossDatasource.PREFIX + name);
265: modifiedJbossClient.addResourceRef(newRR);
266: }
267: });
268: }
269:
270: /**
271: * Add a new mail service reference.
272: *
273: * @param name mail service name
274: */
275: private void addMailReference(final String name)
276: throws ConfigurationException {
277: modifyJbossClient(new JbossClientModifier() {
278: public void modify(JbossClient modifiedJbossClient) {
279:
280: // check whether mail service not already defined
281: ResourceRef resourceRefs[] = modifiedJbossClient
282: .getResourceRef();
283: for (int i = 0; i < resourceRefs.length; i++) {
284: String rrn = resourceRefs[i].getResRefName();
285: if (name.equals(rrn)) {
286: // already exists
287: return;
288: }
289: }
290:
291: //if it doesn't exist yet, create a new one
292: ResourceRef newRR = new ResourceRef();
293: newRR.setResRefName(name);
294: newRR.setJndiName(MAIL_SERVICE_JNDI_NAME_JB4);
295: modifiedJbossClient.addResourceRef(newRR);
296: }
297: });
298: }
299:
300: /**
301: * Add a new connection factory reference.
302: *
303: * @param name connection factory name
304: */
305: private void addConnectionFactoryReference(final String name)
306: throws ConfigurationException {
307: modifyJbossClient(new JbossClientModifier() {
308: public void modify(JbossClient modifiedJbossClient) {
309:
310: // check whether connection factory not already defined
311: ResourceRef resourceRefs[] = modifiedJbossClient
312: .getResourceRef();
313: for (int i = 0; i < resourceRefs.length; i++) {
314: String rrn = resourceRefs[i].getResRefName();
315: if (name.equals(rrn)) {
316: // already exists
317: return;
318: }
319: }
320:
321: //if it doesn't exist yet, create a new one
322: ResourceRef newRR = new ResourceRef();
323: newRR.setResRefName(name);
324: newRR
325: .setJndiName(MessageDestinationSupport.CONN_FACTORY_JNDI_NAME_JB4);
326: modifiedJbossClient.addResourceRef(newRR);
327: }
328: });
329: }
330:
331: /**
332: * Add a new ejb reference.
333: *
334: * @param name ejb reference name
335: */
336: private void addEjbReference(final String name)
337: throws ConfigurationException {
338: modifyJbossClient(new JbossClientModifier() {
339: public void modify(JbossClient modifiedJbossClient) {
340:
341: // check whether resource not already defined
342: EjbRef ejbRefs[] = modifiedJbossClient.getEjbRef();
343: for (int i = 0; i < ejbRefs.length; i++) {
344: String ern = ejbRefs[i].getEjbRefName();
345: if (name.equals(ern)) {
346: // already exists
347: return;
348: }
349: }
350:
351: //if it doesn't exist yet, create a new one
352: EjbRef newER = new EjbRef();
353: newER.setEjbRefName(name);
354: newER.setJndiName(/*JBOSS4_EJB_JNDI_PREFIX + */name);
355: modifiedJbossClient.addEjbRef(newER);
356: }
357: });
358: }
359:
360: /**
361: * Add a new jndi-name.
362: *
363: * @param name jndi-name name
364: */
365: private void setJndiName(final String jndiName)
366: throws ConfigurationException {
367: modifyJbossClient(new JbossClientModifier() {
368: public void modify(JbossClient modifiedJbossClient) {
369: modifiedJbossClient.setJndiName(jndiName);
370: }
371: });
372: }
373:
374: /**
375: * Add a new service reference.
376: *
377: * @param name service reference name
378: */
379: private void addServiceReference(final String name)
380: throws ConfigurationException {
381: modifyJbossClient(new JbossClientModifier() {
382: public void modify(JbossClient modifiedJbossClient) {
383:
384: // check whether resource not already defined
385: ServiceRef serviceRefs[] = modifiedJbossClient
386: .getServiceRef();
387: for (int i = 0; i < serviceRefs.length; i++) {
388: String srn = serviceRefs[i].getServiceRefName();
389: if (name.equals(srn)) {
390: // already exists
391: return;
392: }
393: }
394:
395: //if it doesn't exist yet, create a new one
396: ServiceRef newSR = new ServiceRef();
397: newSR.setServiceRefName(name);
398: modifiedJbossClient.addServiceRef(newSR);
399: }
400: });
401: }
402:
403: /**
404: * Perform jbossWeb changes defined by the jbossWeb modifier. Update editor
405: * content and save changes, if appropriate.
406: *
407: * @param modifier
408: */
409: private void modifyJbossClient(JbossClientModifier modifier)
410: throws ConfigurationException {
411: assert deploymentDescriptorDO != null : "DataObject has not been initialized yet"; // NIO18N
412: try {
413: // get the document
414: EditorCookie editor = (EditorCookie) deploymentDescriptorDO
415: .getCookie(EditorCookie.class);
416: StyledDocument doc = editor.getDocument();
417: if (doc == null) {
418: doc = editor.openDocument();
419: }
420:
421: // get the up-to-date model
422: JbossClient newJbossClient = null;
423: try {
424: // try to create a graph from the editor content
425: byte[] docString = doc.getText(0, doc.getLength())
426: .getBytes();
427: newJbossClient = JbossClient
428: .createGraph(new ByteArrayInputStream(docString));
429: } catch (RuntimeException e) {
430: JbossClient oldJbossClient = getJbossClient();
431: if (oldJbossClient == null) {
432: // neither the old graph is parseable, there is not much we can do here
433: // TODO: should we notify the user?
434: String msg = NbBundle.getMessage(
435: CarDeploymentConfiguration.class,
436: "MSG_jbossXmlCannotParse", jbossClientFile
437: .getAbsolutePath());
438: throw new ConfigurationException(msg);
439: }
440: // current editor content is not parseable, ask whether to override or not
441: NotifyDescriptor notDesc = new NotifyDescriptor.Confirmation(
442: NbBundle.getMessage(
443: CarDeploymentConfiguration.class,
444: "MSG_jbossClientXmlNotValid"),
445: NotifyDescriptor.OK_CANCEL_OPTION);
446: Object result = DialogDisplayer.getDefault().notify(
447: notDesc);
448: if (result == NotifyDescriptor.CANCEL_OPTION) {
449: // keep the old content
450: return;
451: }
452: // use the old graph
453: newJbossClient = oldJbossClient;
454: }
455:
456: // perform changes
457: modifier.modify(newJbossClient);
458:
459: // save, if appropriate
460: boolean modified = deploymentDescriptorDO.isModified();
461: ResourceConfigurationHelper.replaceDocument(doc,
462: newJbossClient);
463: if (!modified) {
464: SaveCookie cookie = (SaveCookie) deploymentDescriptorDO
465: .getCookie(SaveCookie.class);
466: if (cookie != null) {
467: cookie.save();
468: }
469: }
470: synchronized (this ) {
471: jbossClient = newJbossClient;
472: }
473: } catch (BadLocationException ble) {
474: // this should not occur, just log it if it happens
475: Exceptions.printStackTrace(ble);
476: } catch (IOException ioe) {
477: String msg = NbBundle.getMessage(
478: CarDeploymentConfiguration.class,
479: "MSG_CannotUpdateFile", jbossClientFile
480: .getAbsolutePath());
481: throw new ConfigurationException(msg, ioe);
482: }
483: }
484:
485: public boolean supportsCreateDatasource() {
486: return true;
487: }
488:
489: public boolean supportsCreateMessageDestination() {
490: return false;
491: }
492:
493: // private helper interface -----------------------------------------------
494:
495: private interface JbossClientModifier {
496: void modify(JbossClient modifiedJbossClient);
497: }
498: }
|