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-2006 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.compapp.projects.common;
043:
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.util.Collection;
047: import java.util.List;
048: import java.util.Map;
049: import java.util.logging.Level;
050: import java.util.logging.Logger;
051: import javax.swing.text.BadLocationException;
052: import javax.swing.text.Document;
053: import org.netbeans.editor.BaseDocument;
054: import org.netbeans.modules.compapp.projects.common.CatalogWSDL.CatalogWSDLSerializer;
055: import org.netbeans.modules.compapp.projects.common.CatalogWSDL.Entry;
056: import org.netbeans.modules.compapp.projects.common.CatalogWSDL.EntryType;
057: import org.netbeans.modules.xml.schema.model.Schema;
058: import org.netbeans.modules.xml.wsdl.model.Definitions;
059: import org.netbeans.modules.xml.wsdl.model.Import;
060: import org.netbeans.modules.xml.wsdl.model.Types;
061: import org.netbeans.modules.xml.wsdl.model.WSDLModel;
062: import org.netbeans.modules.xml.wsdl.model.WSDLModelFactory;
063: import org.netbeans.modules.xml.wsdl.model.extensions.xsd.WSDLSchema;
064: import org.netbeans.modules.xml.xam.ModelSource;
065: import org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent;
066: import org.netbeans.modules.xml.xam.locator.CatalogModelException;
067: import org.netbeans.modules.xml.xdm.xam.XDMAccessProvider;
068: import org.openide.cookies.EditorCookie;
069: import org.openide.cookies.SaveCookie;
070: import org.openide.filesystems.FileObject;
071: import org.openide.loaders.DataObject;
072: import org.openide.util.Lookup;
073: import org.openide.util.lookup.Lookups;
074:
075: /**
076: * This class is a concrete implemenation of the CatalogWSDLSerializer which uses
077: * WSDL XDM Model for reading/writing the catalog.wsdl file
078: * @see CatalogWSDLSerializer
079: * @author chikkala
080: */
081: public class XAMCatalogWSDLSerializer extends CatalogWSDLSerializer {
082: /** logger */
083: private static final Logger sLogger = Logger
084: .getLogger(XAMCatalogWSDLSerializer.class.getName());
085: /** defuult model source provider that is used to load/save xdm model */
086: private static ModelSourceProvider sModelSourceProvider = new ModelSourceProvider();
087:
088: /**
089: * setter for the static model source provider which will be used to
090: * create xdm model.
091: * The model source implemenation provided in the retriever package's Utility
092: * class is not suitable, a simple model source provider implemenation is
093: * provided with the default one. @see ModelSourceProvider for more details.
094: *
095: * @param msProvider ModelSourceProvider
096: */
097: static void setModelSourceProvider(ModelSourceProvider msProvider) {
098: sLogger.fine("new MessageSourceProvider set");
099: sModelSourceProvider = msProvider;
100: }
101:
102: /**
103: * return the current model source provider. If the provider is not set
104: * a default will be created and returned
105: * @return ModelSourceProvider
106: */
107: static ModelSourceProvider getModelSourceProvider() {
108: if (sModelSourceProvider == null) {
109: sModelSourceProvider = new ModelSourceProvider();
110: }
111: return sModelSourceProvider;
112: }
113:
114: /**
115: *
116: * @param catWSDL
117: * @param catFO
118: * @throws java.io.IOException
119: */
120: public void marshall(CatalogWSDL catWSDL, FileObject catFO)
121: throws IOException {
122: saveCatalogWSDL(catWSDL, catFO);
123: }
124:
125: /**
126: *
127: * @param catFO
128: * @return
129: * @throws java.io.IOException
130: */
131: public CatalogWSDL unmarshall(FileObject catFO) throws IOException {
132: CatalogWSDL catWSDL = null;
133: Definitions wsdlDef = loadCatalogWSDLDefinitions(catFO);
134: catWSDL = loadCatalogWSDL(wsdlDef);
135: return catWSDL;
136: }
137:
138: /**
139: * loads the wsdl definition model from the file.
140: * @param catalogWsdlFO
141: * @return
142: */
143: private Definitions loadCatalogWSDLDefinitions(
144: FileObject catalogWsdlFO) {
145: try {
146: ModelSource catModelSource = getModelSourceProvider()
147: .getModelSource(catalogWsdlFO, true);
148: WSDLModel wsdlModel = WSDLModelFactory.getDefault()
149: .getModel(catModelSource);
150: Definitions wsdlDef = wsdlModel.getDefinitions();
151: return wsdlDef;
152: } catch (CatalogModelException ex) {
153: //TODO: log exception.
154: sLogger.log(Level.WARNING, ex.getMessage(), ex);
155: return null;
156: }
157: }
158:
159: /**
160: * adds xsd entries to the catalog model from the wsdl definition's schema
161: * import elements
162: * @param catalog
163: * @param wsdlDef
164: */
165: private void addXSDEntries(CatalogWSDL catalog, Definitions wsdlDef) {
166:
167: Collection<Schema> schemas = wsdlDef.getTypes().getSchemas();
168: Schema xsdSchema = null;
169: for (Schema schema : schemas) {
170: //TODO: check if you have more than one schema. if yes. pick one with catalog tns
171: xsdSchema = schema;
172: break;
173: }
174: if (xsdSchema != null) {
175: Collection<org.netbeans.modules.xml.schema.model.Import> xsdImports = xsdSchema
176: .getImports();
177: for (org.netbeans.modules.xml.schema.model.Import xsdImport : xsdImports) {
178: Entry xsdEntry = new Entry(EntryType.XSD);
179: xsdEntry.setNamespace(xsdImport.getNamespace());
180: xsdEntry.setLocation(xsdImport.getSchemaLocation());
181: catalog.addEntry(xsdEntry);
182: }
183: }
184: }
185:
186: /**
187: * adds wsdl entries to the catalog model from wsdl import elements of the
188: * defintions
189: * @param catalog
190: * @param wsdlDef
191: */
192: private void addWSDLEntries(CatalogWSDL catalog, Definitions wsdlDef) {
193: Collection<Import> wsdlImports = wsdlDef.getImports();
194: for (Import wsdlImport : wsdlImports) {
195: Entry wsdlEntry = new Entry(EntryType.WSDL);
196: wsdlEntry.setNamespace(wsdlImport.getNamespace());
197: wsdlEntry.setLocation(wsdlImport.getLocation());
198: catalog.addEntry(wsdlEntry);
199: }
200: }
201:
202: /**
203: * loads the catalog model from the wsdl defintions model
204: * @param wsdlDef
205: * @return
206: * @throws java.io.IOException
207: */
208: private CatalogWSDL loadCatalogWSDL(Definitions wsdlDef)
209: throws IOException {
210: CatalogWSDL catalog = new CatalogWSDL();
211: if (!CatalogWSDL.CATALOG_NAME.equalsIgnoreCase(wsdlDef
212: .getName())
213: || !CatalogWSDL.TNS
214: .equals(wsdlDef.getTargetNamespace())) {
215: throw new IOException("Not a CATALOG WSDL File");
216: }
217: // add wsdl entries
218: addWSDLEntries(catalog, wsdlDef);
219: // add xsd entries
220: addXSDEntries(catalog, wsdlDef);
221:
222: return catalog;
223: }
224:
225: /**
226: * add the namespace prefixes to the wsdl model
227: * @param wsdlModel
228: * @param namespace
229: */
230: protected void addNamespacePrefix(WSDLModel wsdlModel,
231: String namespace) {
232: String prefix = null;
233: String prefixPrefix = "ns";
234: Map prefixes = null;
235: AbstractDocumentComponent def = (AbstractDocumentComponent) wsdlModel
236: .getDefinitions();
237: prefixes = def.getPrefixes();
238: for (int i = 0; i < Integer.MAX_VALUE; ++i) {
239: if (!prefixes.containsKey(prefixPrefix + i)) {
240: prefix = prefixPrefix + i;
241: def.addPrefix(prefix, namespace);
242: break;
243: }
244: }
245: }
246:
247: /**
248: * adds the schema import elements to the wsdl definitions model correponding
249: * to the xsd entries of the catalog model.
250: * Must call this between WSDLModel.startTransaction and WSDLModel.endTransaction.
251: * @param wsdlDef wsdl definition model
252: * @param entry wsdl catalog entry
253: */
254: private void addEntryAsSchemaImport(Definitions wsdlDef,
255: Entry xsdEntry) {
256: WSDLModel wsdlModel = wsdlDef.getModel();
257: Types types = wsdlDef.getTypes();
258: if (types == null) {
259: // no types, create one
260: types = wsdlModel.getFactory().createTypes();
261: wsdlDef.setTypes(types);
262: }
263: Schema xsdSchema = null;
264: Collection<Schema> schemas = types.getSchemas();
265: if (schemas == null || schemas.size() == 0) {
266: // no schema, create one
267: WSDLSchema wsdlSchema = wsdlModel.getFactory()
268: .createWSDLSchema();
269: types.addExtensibilityElement(wsdlSchema);
270: xsdSchema = wsdlSchema.getSchemaModel().getSchema();
271: xsdSchema.setTargetNamespace(CatalogWSDL.TNS);
272: } else {
273: // get the first one as the schema
274: for (Schema s : schemas) {
275: //TODO: check if you have more than one schema. if yes. pick one with catalog tns
276: xsdSchema = s;
277: break;
278: }
279: }
280: // create import schema
281: org.netbeans.modules.xml.schema.model.Import schemaImport = xsdSchema
282: .getModel().getFactory().createImport();
283: // init
284: schemaImport.setNamespace(xsdEntry.getNamesapce());
285: schemaImport.setSchemaLocation(xsdEntry.getLocation());
286: // add
287: xsdSchema.addExternalReference(schemaImport);
288: addNamespacePrefix(wsdlModel, xsdEntry.getNamesapce());
289: }
290:
291: /**
292: * adds the wsdl import elements to the wsdl definitions model correponding
293: * to the wsdl entries of the catalog model.
294: * Must call this between WSDLModel.startTransaction and WSDLModel.endTransaction.
295: * @param wsdlDef wsdl definition model
296: * @param wsdlEntry wsdl catalog entry
297: */
298: private void addEntryAsWSDLImport(Definitions wsdlDef,
299: Entry wsdlEntry) {
300:
301: WSDLModel wsdlModel = wsdlDef.getModel();
302: Import imp = wsdlModel.getFactory().createImport();
303: // init import
304: imp.setNamespace(wsdlEntry.getNamesapce());
305: imp.setLocation(wsdlEntry.getLocation());
306: // add
307: wsdlDef.addImport(imp);
308: addNamespacePrefix(wsdlModel, wsdlEntry.getNamesapce());
309: }
310:
311: /**
312: * saves the catalog model to the catalog file after translating the
313: * catalog model to the wsdl xdm model.
314: * @param catalog
315: * @param catalogFO
316: * @throws java.io.IOException
317: */
318: private void saveCatalogWSDL(CatalogWSDL catalog,
319: FileObject catalogFO) throws IOException {
320: Definitions wsdlDef = loadCatalogWSDLDefinitions(catalogFO);
321: List<Entry> entries = catalog.getEntries();
322: WSDLModel wsdlModel = wsdlDef.getModel();
323: try {
324: wsdlModel.startTransaction();
325: for (Entry entry : entries) {
326: if (EntryType.XSD.equals(entry.getType())) {
327: // add schema import
328: addEntryAsSchemaImport(wsdlDef, entry);
329: } else if (EntryType.WSDL.equals(entry.getType())) {
330: // add wsdl import
331: addEntryAsWSDLImport(wsdlDef, entry);
332: } else {
333: sLogger
334: .fine("!!!!!Unsupported CatalogWSDL entry!!!!!");
335: }
336: }
337: } finally {
338: if (wsdlModel.isIntransaction()) {
339: wsdlModel.endTransaction();
340: }
341: }
342:
343: // make sure that all the open editors are saved to disk and then overwrite it
344: // read the text in the base document.
345: String text = null;
346: Document doc = wsdlModel.getModelSource().getLookup().lookup(
347: BaseDocument.class);
348: if (doc != null) {
349: int size = doc.getLength();
350: try {
351: text = doc.getText(0, size);
352: } catch (Exception ex) {
353: sLogger.log(Level.FINE, ex.getMessage(), ex);
354: }
355: }
356: if (text != null) {
357: // catalog wsdl is not supposed to be edited outside this serializer. So, save all the
358: // outside edits and then overwrite them with the acutal modified content.
359: // use save cookie or editor cookie to save any open and edited document references
360: DataObject dObj = DataObject.find(catalogFO);
361: SaveCookie saveCookie = dObj.getCookie(SaveCookie.class);
362: EditorCookie editorCookie = (EditorCookie) dObj
363: .getCookie(EditorCookie.class);
364: if (saveCookie != null) {
365: saveCookie.save();
366: }
367: if (editorCookie != null) {
368: editorCookie.saveDocument();
369: }
370: // save the actual update
371: saveToFileObject(catalogFO, new StringBuffer(text));
372: } else {
373: sLogger
374: .fine("BASE DOCUMENT TEXT IS NULL. Can not save catalog wsdl");
375: }
376:
377: }
378:
379: /**
380: * This is the default implemenation of the ModelSource provider. The retriever
381: * modules Utility method Utilities.getModelSource(...) requires a lot of
382: * project and editor api dependencies which is not suitable for the simple
383: * serializer and its unit testing, we need this class to provide a simple
384: * implemenation of the model source that uses the swing document to
385: * represent file on the disk.
386: *
387: */
388: public static class ModelSourceProvider {
389: /**
390: * creates the ModelSource for a file
391: * @param fileObject
392: * @param editable
393: * @return
394: * @throws org.netbeans.modules.xml.xam.locator.CatalogModelException
395: */
396: public ModelSource getModelSource(final FileObject fileObject,
397: boolean editable) throws CatalogModelException {
398:
399: BaseDocument document = null;
400: document = (BaseDocument) loadSwingDocument(fileObject);
401: Lookup lookup = Lookups.fixed(new Object[] { document });
402: return new ModelSource(lookup, editable);
403: }
404:
405: /**
406: * loads the file data into swing document that is needed for the
407: * model source
408: * @param fileObject
409: * @return
410: */
411: public Document loadSwingDocument(FileObject fileObject) {
412: InputStream in = null;
413: Document sd = null;
414: try {
415: in = fileObject.getInputStream();
416: sd = (new XDMAccessProvider()).loadSwingDocument(in);
417: } catch (IOException ioEx) {
418: sLogger.log(Level.FINE, ioEx.getMessage(), ioEx);
419: } catch (BadLocationException locEx) {
420: sLogger.log(Level.FINE, locEx.getMessage(), locEx);
421: } finally {
422: if (in != null) {
423: try {
424: in.close();
425: } catch (IOException ex) {
426: //ignore
427: }
428: }
429: }
430: if (sd == null) {
431: sLogger
432: .fine("BaseDocument is NULL in loadSwingDocument");
433: }
434: return sd;
435: }
436: }
437: }
|