KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > wsdl > symbolTable > SymbolTable


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55
56 package org.jboss.axis.wsdl.symbolTable;
57
58 import org.jboss.axis.Constants;
59 import org.jboss.axis.enums.Style;
60 import org.jboss.axis.enums.Use;
61 import org.jboss.axis.utils.LinkedHashMap;
62 import org.jboss.axis.utils.Messages;
63 import org.jboss.axis.utils.URLHashSet;
64 import org.jboss.axis.utils.XMLUtils;
65 import org.jboss.logging.Logger;
66 import org.w3c.dom.Document JavaDoc;
67 import org.w3c.dom.NamedNodeMap JavaDoc;
68 import org.w3c.dom.Node JavaDoc;
69 import org.w3c.dom.NodeList JavaDoc;
70 import org.xml.sax.SAXException JavaDoc;
71
72 import javax.wsdl.Binding;
73 import javax.wsdl.BindingFault;
74 import javax.wsdl.BindingInput;
75 import javax.wsdl.BindingOperation;
76 import javax.wsdl.BindingOutput;
77 import javax.wsdl.Definition;
78 import javax.wsdl.Fault;
79 import javax.wsdl.Import;
80 import javax.wsdl.Input;
81 import javax.wsdl.Message;
82 import javax.wsdl.Operation;
83 import javax.wsdl.Output;
84 import javax.wsdl.Part;
85 import javax.wsdl.Port;
86 import javax.wsdl.PortType;
87 import javax.wsdl.Service;
88 import javax.wsdl.WSDLException;
89 import javax.wsdl.extensions.UnknownExtensibilityElement;
90 import javax.wsdl.extensions.http.HTTPBinding;
91 import javax.wsdl.extensions.mime.MIMEContent;
92 import javax.wsdl.extensions.mime.MIMEMultipartRelated;
93 import javax.wsdl.extensions.mime.MIMEPart;
94 import javax.wsdl.extensions.soap.SOAPBinding;
95 import javax.wsdl.extensions.soap.SOAPBody;
96 import javax.wsdl.extensions.soap.SOAPFault;
97 import javax.wsdl.extensions.soap.SOAPHeader;
98 import javax.wsdl.extensions.soap.SOAPHeaderFault;
99 import javax.wsdl.factory.WSDLFactory;
100 import javax.wsdl.xml.WSDLReader;
101 import javax.xml.namespace.QName JavaDoc;
102 import javax.xml.parsers.ParserConfigurationException JavaDoc;
103 import javax.xml.rpc.holders.BooleanHolder JavaDoc;
104 import javax.xml.rpc.holders.IntHolder JavaDoc;
105 import java.io.File JavaDoc;
106 import java.io.IOException JavaDoc;
107 import java.net.MalformedURLException JavaDoc;
108 import java.net.URL JavaDoc;
109 import java.util.ArrayList JavaDoc;
110 import java.util.Collection JavaDoc;
111 import java.util.Collections JavaDoc;
112 import java.util.HashMap JavaDoc;
113 import java.util.HashSet JavaDoc;
114 import java.util.Iterator JavaDoc;
115 import java.util.List JavaDoc;
116 import java.util.Map JavaDoc;
117 import java.util.Vector JavaDoc;
118
119 /**
120  * This class represents a table of all of the top-level symbols from a set of WSDL Definitions and
121  * DOM Documents: XML types; WSDL messages, portTypes, bindings, and services.
122  * <p/>
123  * This symbolTable contains entries of the form <key, value> where key is of type QName and value is
124  * of type Vector. The Vector's elements are all of the objects that have the given QName. This is
125  * necessary since names aren't unique among the WSDL types. message, portType, binding, service,
126  * could all have the same QName and are differentiated merely by type. SymbolTable contains
127  * type-specific getters to bypass the Vector layer:
128  * public PortTypeEntry getPortTypeEntry(QName name), etc.
129  */

130 public class SymbolTable
131 {
132    private static final Logger log = Logger.getLogger(SymbolTable.class);
133
134    // Should the contents of imported files be added to the symbol table?
135
private boolean addImports;
136
137    // The actual symbol table. This symbolTable contains entries of the form
138
// <key, value> where key is of type QName and value is of type Vector. The
139
// Vector's elements are all of the objects that have the given QName. This
140
// is necessary since names aren't unique among the WSDL types. message,
141
// portType, binding, service, could all have the same QName and are
142
// differentiated merely by type. SymbolTable contains type-specific
143
// getters to bypass the Vector layer:
144
// public PortTypeEntry getPortTypeEntry(QName name), etc.
145

146    private HashMap symbolTable = new HashMap();
147
148    // a map of qnames -> Elements in the symbol table
149
private final Map elementTypeEntries = new HashMap();
150    // an unmodifiable wrapper so that we can share the index with others, safely
151
private final Map elementIndex = Collections.unmodifiableMap(elementTypeEntries);
152    // a map of qnames -> Types in the symbol table
153
private final Map typeTypeEntries = new HashMap();
154    // an unmodifiable wrapper so that we can share the index with others, safely
155
private final Map typeIndex = Collections.unmodifiableMap(typeTypeEntries);
156
157    /**
158     * cache of nodes -> base types for complexTypes. The cache is
159     * built on nodes because multiple TypeEntry objects may use the
160     * same node.
161     */

162    protected final Map node2ExtensionBase = new HashMap(); // allow friendly access
163

164    private boolean verbose;
165
166    private BaseTypeMapping btm = null;
167
168    // should we attempt to treat document/literal WSDL as "rpc-style"
169
private boolean nowrap;
170    // Did we encounter wraped mode WSDL
171
private boolean wrapped = false;
172
173    public static final String JavaDoc ANON_TOKEN = ">";
174
175    private Definition def = null;
176    private String JavaDoc wsdlURI = null;
177
178    /**
179     * Construct a symbol table with the given Namespaces.
180     */

181    public SymbolTable(BaseTypeMapping btm, boolean addImports,
182                       boolean verbose, boolean nowrap)
183    {
184       this.btm = btm;
185       this.addImports = addImports;
186       this.verbose = verbose;
187       this.nowrap = nowrap;
188    } // ctor
189

190    /**
191     * Get the raw symbol table HashMap.
192     */

193    public HashMap getHashMap()
194    {
195       return symbolTable;
196    } // getHashMap
197

198    /**
199     * Get the list of entries with the given QName. Since symbols can share QNames, this list is
200     * necessary. This list will not contain any more than one element of any given SymTabEntry.
201     */

202    public Vector JavaDoc getSymbols(QName JavaDoc qname)
203    {
204       return (Vector JavaDoc)symbolTable.get(qname);
205    } // get
206

207    /**
208     * Get the entry with the given QName of the given class. If it does not exist, return null.
209     */

210    public SymTabEntry get(QName JavaDoc qname, Class JavaDoc cls)
211    {
212       Vector JavaDoc v = (Vector JavaDoc)symbolTable.get(qname);
213       if (v == null)
214       {
215          return null;
216       }
217       else
218       {
219          for (int i = 0; i < v.size(); ++i)
220          {
221             SymTabEntry entry = (SymTabEntry)v.elementAt(i);
222             if (cls.isInstance(entry))
223             {
224                return entry;
225             }
226          }
227          return null;
228       }
229    } // get
230

231
232    /**
233     * Get the type entry for the given qname.
234     *
235     * @param qname
236     * @param wantElementType boolean that indicates type or element (for type= or ref=)
237     */

238    public TypeEntry getTypeEntry(QName JavaDoc qname, boolean wantElementType)
239    {
240       if (wantElementType)
241       {
242          return getElement(qname);
243       }
244       else
245          return getType(qname);
246    } // getTypeEntry
247

248    /**
249     * Get the Type TypeEntry with the given QName. If it doesn't
250     * exist, return null.
251     */

252    public Type getType(QName JavaDoc qname)
253    {
254       return (Type)typeTypeEntries.get(qname);
255    } // getType
256

257    /**
258     * Get the Element TypeEntry with the given QName. If it doesn't
259     * exist, return null.
260     */

261    public Element getElement(QName JavaDoc qname)
262    {
263       return (Element)elementTypeEntries.get(qname);
264    } // getElement
265

266    /**
267     * Get the MessageEntry with the given QName. If it doesn't exist, return null.
268     */

269    public MessageEntry getMessageEntry(QName JavaDoc qname)
270    {
271       return (MessageEntry)get(qname, MessageEntry.class);
272    } // getMessageEntry
273

274    /**
275     * Get the PortTypeEntry with the given QName. If it doesn't exist, return null.
276     */

277    public PortTypeEntry getPortTypeEntry(QName JavaDoc qname)
278    {
279       return (PortTypeEntry)get(qname, PortTypeEntry.class);
280    } // getPortTypeEntry
281

282    /**
283     * Get the BindingEntry with the given QName. If it doesn't exist, return null.
284     */

285    public BindingEntry getBindingEntry(QName JavaDoc qname)
286    {
287       return (BindingEntry)get(qname, BindingEntry.class);
288    } // getBindingEntry
289

290    /**
291     * Get the ServiceEntry with the given QName. If it doesn't exist, return null.
292     */

293    public ServiceEntry getServiceEntry(QName JavaDoc qname)
294    {
295       return (ServiceEntry)get(qname, ServiceEntry.class);
296    } // getServiceEntry
297

298    /**
299     * Get the list of all the XML schema types in the symbol table. In other words, all entries
300     * that are instances of TypeEntry.
301     *
302     * @deprecated use specialized get{Element,Type}Index() methods instead
303     */

304    public Vector JavaDoc getTypes()
305    {
306       Vector JavaDoc v = new Vector JavaDoc();
307       v.addAll(elementTypeEntries.values());
308       v.addAll(typeTypeEntries.values());
309       return v;
310    } // getTypes
311

312    /**
313     * Return an unmodifiable map of qnames -> Elements in the symbol
314     * table.
315     *
316     * @return an unmodifiable <code>Map</code> value
317     */

318    public Map getElementIndex()
319    {
320       return elementIndex;
321    }
322
323    /**
324     * Return an unmodifiable map of qnames -> Elements in the symbol
325     * table.
326     *
327     * @return an unmodifiable <code>Map</code> value
328     */

329    public Map getTypeIndex()
330    {
331       return typeIndex;
332    }
333
334    /**
335     * Return the count of TypeEntries in the symbol table.
336     *
337     * @return an <code>int</code> value
338     */

339    public int getTypeEntryCount()
340    {
341       return elementTypeEntries.size() + typeTypeEntries.size();
342    }
343
344    /**
345     * Get the Definition. The definition is null until
346     * populate is called.
347     */

348    public Definition getDefinition()
349    {
350       return def;
351    } // getDefinition
352

353    /**
354     * Get the WSDL URI. The WSDL URI is null until populate
355     * is called, and ONLY if a WSDL URI is provided.
356     */

357    public String JavaDoc getWSDLURI()
358    {
359       return wsdlURI;
360    } // getWSDLURI
361

362    /**
363     * Are we wrapping literal soap body elements.
364     */

365    public boolean isWrapped()
366    {
367       return wrapped;
368    }
369
370    /**
371     * Turn on/off element wrapping for literal soap body's.
372     */

373    public void setWrapped(boolean wrapped)
374    {
375       this.wrapped = wrapped;
376    }
377
378    /**
379     * Dump the contents of the symbol table. For debugging purposes only.
380     */

381    public void dump(java.io.PrintStream JavaDoc out)
382    {
383       out.println();
384       out.println(Messages.getMessage("symbolTable00"));
385       out.println("-----------------------");
386       Iterator JavaDoc it = symbolTable.values().iterator();
387       while (it.hasNext())
388       {
389          Vector JavaDoc v = (Vector JavaDoc)it.next();
390          for (int i = 0; i < v.size(); ++i)
391          {
392             out.println(v.elementAt(i).getClass().getName());
393             out.println(v.elementAt(i));
394          }
395       }
396       out.println("-----------------------");
397    } // dump
398

399
400    /**
401     * Call this method if you have a uri for the WSDL document
402     *
403     * @param uri wsdlURI the location of the WSDL file.
404     */

405
406    public void populate(String JavaDoc uri)
407            throws IOException JavaDoc, WSDLException,
408            SAXException JavaDoc, ParserConfigurationException JavaDoc
409    {
410       populate(uri, null, null);
411    } // populate
412

413    public void populate(String JavaDoc uri, String JavaDoc username, String JavaDoc password)
414            throws IOException JavaDoc, WSDLException,
415            SAXException JavaDoc, ParserConfigurationException JavaDoc
416    {
417       if (verbose)
418          System.out.println(Messages.getMessage("parsing00", uri));
419
420       Document JavaDoc doc = XMLUtils.newDocument(uri, username, password);
421       this.wsdlURI = uri;
422       try
423       {
424          File JavaDoc f = new File JavaDoc(uri);
425          if (f.exists())
426          {
427             uri = f.toURL().toString();
428          }
429       }
430       catch (Exception JavaDoc e)
431       {
432       }
433       populate(uri, doc);
434    } // populate
435

436    /**
437     * Call this method if your WSDL document has already been parsed as an XML DOM document.
438     *
439     * @param context context This is directory context for the Document. If the Document were from file "/x/y/z.wsdl" then the context could be "/x/y" (even "/x/y/z.wsdl" would work). If context is null, then the context becomes the current directory.
440     * @param doc doc This is the XML Document containing the WSDL.
441     */

442    public void populate(String JavaDoc context, Document JavaDoc doc)
443            throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
444            ParserConfigurationException JavaDoc
445    {
446       WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
447       reader.setFeature("javax.wsdl.verbose", verbose);
448       this.def = reader.readWSDL(context, doc);
449
450       add(context, def, doc);
451    } // populate
452

453    /**
454     * Add the given Definition and Document information to the symbol table (including imported
455     * symbols), populating it with SymTabEntries for each of the top-level symbols. When the
456     * symbol table has been populated, iterate through it, setting the isReferenced flag
457     * appropriately for each entry.
458     */

459    protected void add(String JavaDoc context, Definition def, Document JavaDoc doc)
460            throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
461            ParserConfigurationException JavaDoc
462    {
463       URL JavaDoc contextURL = context == null ? null : getURL(null, context);
464       populate(contextURL, def, doc, null);
465       checkForUndefined();
466       populateParameters();
467       setReferences(def, doc); // uses wrapped flag set in populateParameters
468
} // add
469

470    /**
471     * Scan the Definition for undefined objects and throw an error.
472     */

473    private void checkForUndefined(Definition def, String JavaDoc filename) throws IOException JavaDoc
474    {
475       if (def != null)
476       {
477          // Bindings
478
Iterator JavaDoc ib = def.getBindings().values().iterator();
479          while (ib.hasNext())
480          {
481             Binding binding = (Binding)ib.next();
482             if (binding.isUndefined())
483             {
484                if (filename == null)
485                {
486                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedBinding01",
487                           binding.getQName().getLocalPart()));
488                }
489                else
490                {
491                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedBinding02",
492                           binding.getQName().getLocalPart(), filename));
493                }
494             }
495          }
496
497          // portTypes
498
Iterator JavaDoc ip = def.getPortTypes().values().iterator();
499          while (ip.hasNext())
500          {
501             PortType portType = (PortType)ip.next();
502             if (portType.isUndefined())
503             {
504                if (filename == null)
505                {
506                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedPort01",
507                           portType.getQName().getLocalPart()));
508                }
509                else
510                {
511                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedPort02",
512                           portType.getQName().getLocalPart(), filename));
513                }
514             }
515          }
516
517 /* tomj: This is a bad idea, faults seem to be undefined
518 // RJB reply: this MUST be done for those systems that do something with
519 // messages. Perhaps we have to do an extra step for faults? I'll leave
520 // this commented for now, until someone uses this generator for something
521 // other than WSDL2Java.
522             // Messages
523             Iterator i = def.getMessages().values().iterator();
524             while (i.hasNext()) {
525                 Message message = (Message) i.next();
526                 if (message.isUndefined()) {
527                     throw new IOException(
528                             Messages.getMessage("emitFailtUndefinedMessage01",
529                                     message.getQName().getLocalPart()));
530                 }
531             }
532 */

533       }
534    }
535
536    /**
537     * Scan the symbol table for undefined types and throw an exception.
538     */

539    private void checkForUndefined() throws IOException JavaDoc
540    {
541       Iterator JavaDoc it = symbolTable.values().iterator();
542       while (it.hasNext())
543       {
544          Vector JavaDoc v = (Vector JavaDoc)it.next();
545          for (int i = 0; i < v.size(); ++i)
546          {
547             SymTabEntry entry = (SymTabEntry)v.get(i);
548
549             // Report undefined types
550
if (entry instanceof UndefinedType)
551             {
552                QName JavaDoc qn = entry.getQName();
553
554                // Special case dateTime/timeInstant that changed
555
// from version to version.
556
if ((qn.getLocalPart().equals("dateTime") &&
557                        !qn.getNamespaceURI().equals(Constants.URI_2001_SCHEMA_XSD)) ||
558                        (qn.getLocalPart().equals("timeInstant") &&
559                        qn.getNamespaceURI().equals(Constants.URI_2001_SCHEMA_XSD)))
560                {
561                   throw new IOException JavaDoc(Messages.getMessage("wrongNamespace00",
562                           qn.getLocalPart(),
563                           qn.getNamespaceURI()));
564                }
565
566                // Check for a undefined XSD Schema Type and throw
567
// an unsupported message instead of undefined
568
if (SchemaUtils.isSimpleSchemaType(entry.getQName()))
569                {
570                   throw new IOException JavaDoc(Messages.getMessage("unsupportedSchemaType00",
571                           qn.getLocalPart()));
572                }
573
574                // last case, its some other undefined thing
575
throw new IOException JavaDoc(Messages.getMessage("undefined00",
576                        entry.getQName().toString()));
577             } // if undefined
578
else if (entry instanceof UndefinedElement)
579             {
580                throw new IOException JavaDoc(Messages.getMessage("undefinedElem00",
581                        entry.getQName().toString()));
582             }
583          }
584       }
585    } // checkForUndefined
586

587    /**
588     * Add the given Definition and Document information to the symbol table (including imported
589     * symbols), populating it with SymTabEntries for each of the top-level symbols.
590     * NOTE: filename is used only by checkForUndefined so that it can report which WSDL file
591     * has the problem. If we're on the primary WSDL file, then we don't know the name and
592     * filename will be null. But we know the names of all imported files.
593     */

594    private URLHashSet importedFiles = new URLHashSet();
595
596    private void populate(URL JavaDoc context, Definition def, Document JavaDoc doc,
597                          String JavaDoc filename)
598            throws IOException JavaDoc, ParserConfigurationException JavaDoc,
599            SAXException JavaDoc, WSDLException
600    {
601       if (doc != null)
602       {
603          populateTypes(context, doc);
604
605          if (addImports)
606          {
607             // Add the symbols from any xsd:import'ed documents.
608
lookForImports(context, doc);
609          }
610       }
611       if (def != null)
612       {
613          checkForUndefined(def, filename);
614          if (addImports)
615          {
616             // Add the symbols from the wsdl:import'ed WSDL documents
617
Map imports = def.getImports();
618             Object JavaDoc[] importKeys = imports.keySet().toArray();
619             for (int i = 0; i < importKeys.length; ++i)
620             {
621                Vector JavaDoc v = (Vector JavaDoc)imports.get(importKeys[i]);
622                for (int j = 0; j < v.size(); ++j)
623                {
624                   Import imp = (Import)v.get(j);
625                   if (!importedFiles.contains(imp.getLocationURI()))
626                   {
627                      importedFiles.add(imp.getLocationURI());
628                      URL JavaDoc url = getURL(context, imp.getLocationURI());
629                      populate(url, imp.getDefinition(),
630                              XMLUtils.newDocument(url.toString()),
631                              url.toString());
632                   }
633                }
634             }
635          }
636          populateMessages(def);
637          populatePortTypes(def);
638          populateBindings(def);
639          populateServices(def);
640       }
641    } // populate
642

643    /**
644     * This is essentially a call to "new URL(contextURL, spec)" with extra handling in case spec is
645     * a file.
646     */

647    private static URL JavaDoc getURL(URL JavaDoc contextURL, String JavaDoc spec) throws IOException JavaDoc
648    {
649       // First, fix the slashes as windows filenames may have backslashes
650
// in them, but the URL class wont do the right thing when we later
651
// process this URL as the contextURL.
652
String JavaDoc path = spec.replace('\\', '/');
653
654       // See if we have a good URL.
655
URL JavaDoc url = null;
656       try
657       {
658          // first, try to treat spec as a full URL
659
url = new URL JavaDoc(contextURL, path);
660
661          // if we are deail with files in both cases, create a url
662
// by using the directory of the context URL.
663
if (contextURL != null &&
664                  url.getProtocol().equals("file") &&
665                  contextURL.getProtocol().equals("file"))
666          {
667             url = getFileURL(contextURL, path);
668          }
669       }
670       catch (MalformedURLException JavaDoc me)
671       {
672          // try treating is as a file pathname
673
url = getFileURL(contextURL, path);
674       }
675
676       // Everything is OK with this URL, although a file url constructed
677
// above may not exist. This will be caught later when the URL is
678
// accessed.
679
return url;
680    } // getURL
681

682    private static URL JavaDoc getFileURL(URL JavaDoc contextURL, String JavaDoc path)
683            throws IOException JavaDoc
684    {
685       if (contextURL != null)
686       {
687          // get the parent directory of the contextURL, and append
688
// the spec string to the end.
689
String JavaDoc contextFileName = contextURL.getFile();
690          URL JavaDoc parent = new File JavaDoc(contextFileName).getParentFile().toURL();
691          if (parent != null)
692          {
693             return new URL JavaDoc(parent, path);
694          }
695       }
696       return new URL JavaDoc("file", "", path);
697    } // getFileURL
698

699    /**
700     * Recursively find all xsd:import'ed objects and call populate for each one.
701     */

702    private void lookForImports(URL JavaDoc context, Node JavaDoc node)
703            throws IOException JavaDoc, ParserConfigurationException JavaDoc,
704            SAXException JavaDoc, WSDLException
705    {
706       NodeList JavaDoc children = node.getChildNodes();
707       for (int i = 0; i < children.getLength(); i++)
708       {
709          Node JavaDoc child = children.item(i);
710          if ("import".equals(child.getLocalName()))
711          {
712             NamedNodeMap JavaDoc attributes = child.getAttributes();
713             Node JavaDoc namespace = attributes.getNamedItem("namespace");
714             // skip XSD import of soap encoding
715
if (namespace != null &&
716                     isKnownNamespace(namespace.getNodeValue()))
717             {
718                continue;
719             }
720             Node JavaDoc importFile = attributes.getNamedItem("schemaLocation");
721             if (importFile != null)
722             {
723                URL JavaDoc url = getURL(context,
724                        importFile.getNodeValue());
725                if (!importedFiles.contains(url))
726                {
727                   importedFiles.add(url);
728                   String JavaDoc filename = url.toString();
729                   populate(url, null,
730                           XMLUtils.newDocument(filename), filename);
731                }
732             }
733          }
734          lookForImports(context, child);
735       }
736    } // lookForImports
737

738    /**
739     * Check if this is a known namespace (soap-enc or schema xsd or schema xsi or xml)
740     *
741     * @param namespace
742     * @return true if this is a know namespace.
743     */

744    public boolean isKnownNamespace(String JavaDoc namespace)
745    {
746       if (Constants.isSOAP_ENC(namespace))
747          return true;
748       if (Constants.isSchemaXSD(namespace))
749          return true;
750       if (Constants.isSchemaXSI(namespace))
751          return true;
752       if (namespace.equals(Constants.NS_URI_XML))
753          return true;
754       return false;
755    }
756
757    /**
758     * Populate the symbol table with all of the Types from the Document.
759     */

760    public void populateTypes(URL JavaDoc context, Document JavaDoc doc)
761            throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
762            ParserConfigurationException JavaDoc
763    {
764       addTypes(context, doc, ABOVE_SCHEMA_LEVEL);
765    } // populateTypes
766

767    /**
768     * Utility method which walks the Document and creates Type objects for
769     * each complexType, simpleType, or element referenced or defined.
770     * <p/>
771     * What goes into the symbol table? In general, only the top-level types
772     * (ie., those just below
773     * the schema tag). But base types and references can
774     * appear below the top level. So anything
775     * at the top level is added to the symbol table,
776     * plus non-Element types (ie, base and refd)
777     * that appear deep within other types.
778     */

779    private static final int ABOVE_SCHEMA_LEVEL = -1;
780    private static final int SCHEMA_LEVEL = 0;
781
782    private void addTypes(URL JavaDoc context, Node JavaDoc node, int level)
783            throws IOException JavaDoc, ParserConfigurationException JavaDoc,
784            WSDLException, SAXException JavaDoc
785    {
786       if (node == null)
787       {
788          return;
789       }
790       // Get the kind of node (complexType, wsdl:part, etc.)
791
QName JavaDoc nodeKind = Utils.getNodeQName(node);
792
793       if (nodeKind != null)
794       {
795          String JavaDoc localPart = nodeKind.getLocalPart();
796          boolean isXSD = Constants.isSchemaXSD(nodeKind.getNamespaceURI());
797          if ((isXSD && localPart.equals("complexType") ||
798                  localPart.equals("simpleType")))
799          {
800
801             // If an extension or restriction is present,
802
// create a type for the reference
803
Node JavaDoc re = SchemaUtils.getRestrictionOrExtensionNode(node);
804             if (re != null &&
805                     Utils.getAttribute(re, "base") != null)
806             {
807                createTypeFromRef(re);
808             }
809
810             // This is a definition of a complex type.
811
// Create a Type.
812
createTypeFromDef(node, false, false);
813          }
814          else if (isXSD && localPart.equals("element"))
815          {
816             // Create a type entry for the referenced type
817
createTypeFromRef(node);
818