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.xml.wsdl.ui.wizard;
043:
044: import java.awt.Component;
045: import java.beans.PropertyChangeEvent;
046: import java.beans.PropertyChangeListener;
047: import java.io.File;
048: import java.io.FileOutputStream;
049: import java.io.IOException;
050: import java.io.OutputStreamWriter;
051: import java.util.ArrayList;
052: import java.util.Iterator;
053: import java.util.List;
054:
055: import javax.swing.JTextField;
056: import javax.swing.event.ChangeEvent;
057: import javax.swing.event.ChangeListener;
058: import javax.swing.event.DocumentEvent;
059: import javax.swing.event.DocumentListener;
060: import javax.swing.text.BadLocationException;
061: import javax.swing.text.Document;
062:
063: import org.netbeans.api.project.Project;
064: import org.netbeans.modules.xml.wsdl.model.WSDLModel;
065: import org.netbeans.modules.xml.wsdl.model.WSDLModelFactory;
066: import org.netbeans.modules.xml.wsdl.ui.actions.ActionHelper;
067: import org.netbeans.modules.xml.wsdl.ui.view.treeeditor.newtype.OperationPanel;
068: import org.netbeans.modules.xml.xam.ModelSource;
069: import org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent;
070: import org.netbeans.spi.project.ui.templates.support.Templates;
071: import org.openide.ErrorManager;
072: import org.openide.NotifyDescriptor;
073: import org.openide.WizardDescriptor;
074: import org.openide.WizardValidationException;
075: import org.openide.cookies.EditorCookie;
076: import org.openide.filesystems.FileObject;
077: import org.openide.filesystems.FileUtil;
078: import org.openide.loaders.DataObject;
079: import org.openide.loaders.DataObjectNotFoundException;
080: import org.openide.loaders.TemplateWizard;
081: import org.openide.util.HelpCtx;
082: import org.openide.util.NbBundle;
083:
084: /**
085: *
086: * @author Milan Kuchtiak
087: */
088: final class WsdlPanel implements WizardDescriptor.FinishablePanel {
089:
090: public static final String FILE_NAME = "FILE_NAME";
091:
092: public static final String WSDL_TARGETNAMESPACE = "WSDL_TARGETNAMESPACE";
093:
094: public static final String WSDL_DEFINITION_NAME = "WSDL_DEFINITION_NAME";
095: public static final String ENCODING = "PROJECT_ENCODING";
096:
097: private static final String DEFAULT_TARGET_NAMESPACE = "urn:WS/wsdl"; //NOI18N
098:
099: private final List<ChangeListener> listeners = new ArrayList<ChangeListener>();
100: private WsdlUIPanel gui;
101:
102: private Project project;
103: private TemplateWizard templateWizard;
104:
105: private JTextField fileNameTextField;
106:
107: private File tempWSDLFile = null;
108:
109: private WSDLModel mTempWSDLModel = null;
110:
111: private String mErrorMessage;
112:
113: private TextChangeListener mListener = new TextChangeListener();
114:
115: WsdlPanel(Project project) {
116: this .project = project;
117: }
118:
119: TemplateWizard getTemplateWizard() {
120: return templateWizard;
121: }
122:
123: void setNameTF(JTextField nameTF) {
124: gui.attachFileNameListener(nameTF);
125: if (nameTF != null) {
126: nameTF.getDocument().removeDocumentListener(mListener);//remove existing one
127: nameTF.getDocument().addDocumentListener(mListener);
128: fileNameTextField = nameTF;
129: }
130: }
131:
132: public Component getComponent() {
133: if (gui == null) {
134: gui = new WsdlUIPanel(this );
135: gui.getSchemaFileTextField().addPropertyChangeListener(
136: new SchemaImportTextChangeListener());
137: gui.getSchemaFileTextField().getDocument()
138: .addDocumentListener(
139: new SchemaImportTextChangeListener());
140: // gui.setPreferredSize(new Dimension(450, 400));
141: }
142: return gui;
143: }
144:
145: public Project getProject() {
146: return project;
147: }
148:
149: public HelpCtx getHelp() {
150: return new HelpCtx(WsdlPanel.class);
151: }
152:
153: void cleanup() {
154: WSDLModel tempModel = (WSDLModel) templateWizard
155: .getProperty(WizardPortTypeConfigurationStep.TEMP_WSDLMODEL);
156: if (tempModel != null) {
157: DataObject dobj = ActionHelper.getDataObject(tempModel);
158: if (dobj != null) {
159: dobj.setModified(false);
160: try {
161: dobj.delete();
162: } catch (Exception e) {
163: //ignore
164: }
165: }
166: }
167: templateWizard.putProperty(
168: WizardPortTypeConfigurationStep.TEMP_WSDLMODEL, null);
169:
170: if (mTempWSDLModel != null) {
171: DataObject dobj = ActionHelper
172: .getDataObject(mTempWSDLModel);
173: if (dobj != null) {
174: dobj.setModified(false);
175: try {
176: dobj.delete();
177: } catch (Exception e) {
178: //ignore
179: }
180: }
181: mTempWSDLModel = null;
182: }
183: }
184:
185: public boolean isValid() {
186: if (templateWizard != null) {
187: /* String errorMessage = null;
188: //This should be good enough to disable html code.
189: // If not try to use the StringEscapeUtils.escapeHtml from common lang.
190: if (mErrorMessage != null) {
191: errorMessage = "<html>" + Utility.escapeHtml(mErrorMessage) + "</html>";
192: }*/
193:
194: templateWizard.putProperty("WizardPanel_errorMessage",
195: mErrorMessage); // NOI18N
196: }
197: return this .mErrorMessage == null;
198:
199: }
200:
201: public void addChangeListener(ChangeListener l) {
202: listeners.add(l);
203: }
204:
205: public void removeChangeListener(ChangeListener l) {
206: listeners.remove(l);
207: }
208:
209: protected void fireChange() {
210: ChangeEvent e = new ChangeEvent(this );
211: Iterator it = listeners.iterator();
212: while (it.hasNext()) {
213: ((ChangeListener) it.next()).stateChanged(e);
214: }
215: }
216:
217: public void readSettings(Object settings) {
218: templateWizard = (TemplateWizard) settings;
219:
220: //if user come to first panel we need to discard out temp wsdl model
221: cleanup();
222:
223: templateWizard.putProperty(
224: WizardPortTypeConfigurationStep.TEMP_WSDLFILE, null);
225: tempWSDLFile = null;
226:
227: }
228:
229: public void storeSettings(Object settings) {
230: TemplateWizard wiz = (TemplateWizard) settings;
231: Object option = wiz.getValue();
232: if (option == NotifyDescriptor.CANCEL_OPTION
233: || option == WizardDescriptor.PREVIOUS_OPTION) {
234: cleanup();
235: return;
236: }
237:
238: String fileName = Templates.getTargetName(wiz);
239: if (fileName == null)
240: return;
241: wiz.putProperty(FILE_NAME, fileName);
242: String targetNamespace = getNS();
243: wiz.putProperty(WSDL_TARGETNAMESPACE, targetNamespace);
244: String definitionName = fileName;
245: wiz.putProperty(WSDL_DEFINITION_NAME, definitionName);
246: try {
247: if (tempWSDLFile == null) {
248:
249: // Create a temporary file for storing our settings.
250: tempWSDLFile = File.createTempFile(fileName + "RIT",
251: ".wsdl"); // NOI18N
252: populateFileFromTemplate(tempWSDLFile);
253: tempWSDLFile.deleteOnExit();
254: templateWizard.putProperty(
255: WizardPortTypeConfigurationStep.TEMP_WSDLFILE,
256: tempWSDLFile);
257: mTempWSDLModel = prepareModelFromFile(tempWSDLFile,
258: definitionName);
259: wiz.putProperty(
260: WizardPortTypeConfigurationStep.TEMP_WSDLMODEL,
261: mTempWSDLModel);
262: } else {
263: wiz.putProperty(
264: WizardPortTypeConfigurationStep.TEMP_WSDLMODEL,
265: mTempWSDLModel);
266: wiz.putProperty(
267: WizardPortTypeConfigurationStep.TEMP_WSDLFILE,
268: tempWSDLFile);
269: mTempWSDLModel.startTransaction();
270: mTempWSDLModel.getDefinitions().setTargetNamespace(
271: targetNamespace);
272: mTempWSDLModel.getDefinitions().setName(definitionName);
273: if (mTempWSDLModel.getDefinitions().getTypes() == null) {
274: mTempWSDLModel.getDefinitions().setTypes(
275: mTempWSDLModel.getFactory().createTypes());
276: }
277: mTempWSDLModel.endTransaction();
278: }
279: } catch (Exception e) {
280: ErrorManager.getDefault().notify(e);
281: }
282: }
283:
284: /**
285: * Create a temporary WSDL file that is based on the wizard template.
286: *
287: * @param wizard the template wizard.
288: * @param file the WSDL file to be written.
289: * @throws DataObjectNotFoundException
290: * if the wizard template is missing.
291: * @throws IOException
292: * if unable to create the temporary file.
293: */
294: void populateFileFromTemplate(File file)
295: throws DataObjectNotFoundException, IOException {
296: if (templateWizard == null) {
297: throw new IOException("templateWizard not defined");
298: }
299:
300: String encoding = (String) templateWizard.getProperty(ENCODING);
301:
302: FileObject template = Templates.getTemplate(templateWizard);
303: DataObject dTemplate = DataObject.find(template);
304: if (dTemplate != null) {
305: EditorCookie editorCookie = DataObject.find(
306: dTemplate.getPrimaryFile()).getCookie(
307: EditorCookie.class);
308: editorCookie.openDocument();
309: Document doc = editorCookie.getDocument();
310: StringBuilder stringBuilder = new StringBuilder();
311: try {
312: stringBuilder.append(doc.getText(0, doc.getLength()));
313: } catch (BadLocationException ble) {
314: // This basically cannot happen.
315: ErrorManager.getDefault().notify(ble);
316: }
317: if (!encoding.equalsIgnoreCase("UTF-8")) {
318: stringBuilder.delete(30, 35);
319: stringBuilder.insert(30, encoding);
320: }
321: FileOutputStream stream = new FileOutputStream(file);
322: OutputStreamWriter writer = new OutputStreamWriter(stream,
323: encoding);
324: writer.write(stringBuilder.toString());
325: writer.close();
326: stream.close();
327: }
328: }
329:
330: /**
331: * Load and initialize the WSDL model from the given file, which should
332: * already have a minimal WSDL definition. The preparation includes
333: * setting the definition name, adding a namespace and prefix, and
334: * adding the types component.
335: *
336: * @param file the file with a minimal WSDL definition.
337: * @return the model.
338: */
339: WSDLModel prepareModelFromFile(File file, String definitionName) {
340: File f = FileUtil.normalizeFile(file);
341: FileObject fobj = FileUtil.toFileObject(f);
342: ModelSource modelSource = org.netbeans.modules.xml.retriever.catalog.Utilities
343: .getModelSource(fobj, fobj.canWrite());
344: WSDLModel model = WSDLModelFactory.getDefault().getModel(
345: modelSource);
346: model.startTransaction();
347: model.getDefinitions().setName(definitionName);
348: String ns = getNS();
349: model.getDefinitions().setTargetNamespace(ns);
350: ((AbstractDocumentComponent) model.getDefinitions()).addPrefix(
351: "tns", ns);
352: if (model.getDefinitions().getTypes() == null) {
353: model.getDefinitions().setTypes(
354: model.getFactory().createTypes());
355: }
356: model.endTransaction();
357: return model;
358: }
359:
360: String getNS() {
361: String targetNamespace = gui.getNS();
362: if (targetNamespace.length() == 0) {
363: targetNamespace = DEFAULT_TARGET_NAMESPACE;
364: }
365: return targetNamespace;
366: }
367:
368: WsdlUIPanel.SchemaInfo[] getSchemas() {
369: return gui.getSchemas();
370: }
371:
372: boolean isImport() {
373: return gui.isImport();
374: }
375:
376: public boolean isFinishPanel() {
377: return isValid();
378: }
379:
380: private void fireChangeEvent() {
381: Iterator<ChangeListener> it = this .listeners.iterator();
382: ChangeEvent e = new ChangeEvent(this );
383: while (it.hasNext()) {
384: ChangeListener l = it.next();
385: l.stateChanged(e);
386: }
387: }
388:
389: private boolean isValidName(Document doc) {
390: try {
391: String text = doc.getText(0, doc.getLength());
392: boolean isValid = org.netbeans.modules.xml.xam.dom.Utils
393: .isValidNCName(text);
394: if (!isValid) {
395: mErrorMessage = NbBundle.getMessage(
396: OperationPanel.class, "ERR_MSG_INVALID_NAME",
397: text);
398: } else {
399: mErrorMessage = null;
400: }
401:
402: } catch (Exception ex) {
403: ex.printStackTrace();
404: }
405:
406: return mErrorMessage == null;
407: }
408:
409: private void validateFileName() {
410: boolean validFileName = isValidName(this .fileNameTextField
411: .getDocument());
412: if (!validFileName) {
413: fireChangeEvent();
414: return;
415: }
416: }
417:
418: class TextChangeListener implements DocumentListener {
419:
420: public void changedUpdate(DocumentEvent e) {
421: validateFileName();
422: }
423:
424: public void insertUpdate(DocumentEvent e) {
425: validateFileName();
426: }
427:
428: public void removeUpdate(DocumentEvent e) {
429: validateFileName();
430: }
431:
432: }
433:
434: class SchemaImportTextChangeListener implements
435: PropertyChangeListener, DocumentListener {
436:
437: public void propertyChange(PropertyChangeEvent evt) {
438: if (evt.getPropertyName().equals("VALUE_SET")) {
439: validateSchemas();
440: }
441: }
442:
443: public void insertUpdate(DocumentEvent e) {
444: validateSchemas();
445: }
446:
447: public void removeUpdate(DocumentEvent e) {
448: validateSchemas();
449: }
450:
451: public void changedUpdate(DocumentEvent e) {
452: validateSchemas();
453: }
454:
455: }
456:
457: public void validateSchemas() {
458: try {
459: gui.validateSchemas();
460: } catch (WizardValidationException e) {
461: mErrorMessage = e.getLocalizedMessage();
462: fireChangeEvent();
463: return;
464: }
465: mErrorMessage = null;
466: fireChangeEvent();
467: }
468:
469: }
|