Save This Page
Home » xmlbeans-2.4.0-src » org.apache.xmlbeans.impl.schema » [javadoc | source]
    1   /*   Copyright 2004 The Apache Software Foundation
    2    *
    3    *   Licensed under the Apache License, Version 2.0 (the "License");
    4    *   you may not use this file except in compliance with the License.
    5    *   You may obtain a copy of the License at
    6    *
    7    *       http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    *   Unless required by applicable law or agreed to in writing, software
   10    *   distributed under the License is distributed on an "AS IS" BASIS,
   11    *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12    *   See the License for the specific language governing permissions and
   13    *  limitations under the License.
   14    */
   15   
   16   package org.apache.xmlbeans.impl.schema;
   17   
   18   import org.apache.xmlbeans.Filer;
   19   import org.apache.xmlbeans.QNameSet;
   20   import org.apache.xmlbeans.SchemaAnnotation;
   21   import org.apache.xmlbeans.SchemaAttributeGroup;
   22   import org.apache.xmlbeans.SchemaAttributeModel;
   23   import org.apache.xmlbeans.SchemaComponent;
   24   import org.apache.xmlbeans.SchemaField;
   25   import org.apache.xmlbeans.SchemaGlobalAttribute;
   26   import org.apache.xmlbeans.SchemaGlobalElement;
   27   import org.apache.xmlbeans.SchemaIdentityConstraint;
   28   import org.apache.xmlbeans.SchemaLocalAttribute;
   29   import org.apache.xmlbeans.SchemaLocalElement;
   30   import org.apache.xmlbeans.SchemaModelGroup;
   31   import org.apache.xmlbeans.SchemaParticle;
   32   import org.apache.xmlbeans.SchemaProperty;
   33   import org.apache.xmlbeans.SchemaStringEnumEntry;
   34   import org.apache.xmlbeans.SchemaType;
   35   import org.apache.xmlbeans.SchemaTypeLoader;
   36   import org.apache.xmlbeans.SchemaTypeLoaderException;
   37   import org.apache.xmlbeans.SchemaTypeSystem;
   38   import org.apache.xmlbeans.SimpleValue;
   39   import org.apache.xmlbeans.SystemProperties;
   40   import org.apache.xmlbeans.XmlAnySimpleType;
   41   import org.apache.xmlbeans.XmlObject;
   42   import org.apache.xmlbeans.XmlOptions;
   43   import org.apache.xmlbeans.ResourceLoader;
   44   import org.apache.xmlbeans.impl.common.NameUtil;
   45   import org.apache.xmlbeans.impl.common.QNameHelper;
   46   import org.apache.xmlbeans.impl.common.XBeanDebug;
   47   import org.apache.xmlbeans.impl.util.FilerImpl;
   48   import org.apache.xmlbeans.impl.util.HexBin;
   49   import org.apache.xmlbeans.impl.values.XmlObjectBase;
   50   import org.apache.xmlbeans.impl.xb.xsdschema.AttributeGroupDocument;
   51   import org.apache.xmlbeans.impl.xb.xsdschema.GroupDocument;
   52   import org.apache.xmlbeans.soap.SOAPArrayType;
   53   import org.apache.xmlbeans.soap.SchemaWSDLArrayType;
   54   import repackage.Repackager;
   55   
   56   import javax.xml.namespace.QName;
   57   import java.io.ByteArrayOutputStream;
   58   import java.io.DataInputStream;
   59   import java.io.DataOutputStream;
   60   import java.io.File;
   61   import java.io.IOException;
   62   import java.io.InputStream;
   63   import java.io.OutputStream;
   64   import java.math.BigInteger;
   65   import java.util.ArrayList;
   66   import java.util.Arrays;
   67   import java.util.Collections;
   68   import java.util.HashMap;
   69   import java.util.HashSet;
   70   import java.util.Iterator;
   71   import java.util.LinkedHashMap;
   72   import java.util.LinkedHashSet;
   73   import java.util.List;
   74   import java.util.Map;
   75   import java.util.Random;
   76   import java.util.Set;
   77   import java.util.zip.ZipEntry;
   78   import java.util.zip.ZipFile;
   79   
   80   public class SchemaTypeSystemImpl extends SchemaTypeLoaderBase implements SchemaTypeSystem
   81   {
   82       public static final int DATA_BABE = 0xDA7ABABE;
   83       public static final int MAJOR_VERSION = 2;  // must match == to be compatible
   84       public static final int MINOR_VERSION = 24; // must be <= to be compatible
   85       public static final int RELEASE_NUMBER = 0; // should be compatible even if < or >
   86   
   87       public static final int FILETYPE_SCHEMAINDEX = 1;
   88       public static final int FILETYPE_SCHEMATYPE = 2;
   89       public static final int FILETYPE_SCHEMAELEMENT = 3;
   90       public static final int FILETYPE_SCHEMAATTRIBUTE = 4;
   91       public static final int FILETYPE_SCHEMAPOINTER = 5;
   92       public static final int FILETYPE_SCHEMAMODELGROUP = 6;
   93       public static final int FILETYPE_SCHEMAATTRIBUTEGROUP = 7;
   94       public static final int FILETYPE_SCHEMAIDENTITYCONSTRAINT = 8;
   95   
   96       public static final int FLAG_PART_SKIPPABLE = 1;
   97       public static final int FLAG_PART_FIXED = 4;
   98       public static final int FLAG_PART_NILLABLE = 8;
   99       public static final int FLAG_PART_BLOCKEXT = 16;
  100       public static final int FLAG_PART_BLOCKREST = 32;
  101       public static final int FLAG_PART_BLOCKSUBST = 64;
  102       public static final int FLAG_PART_ABSTRACT = 128;
  103       public static final int FLAG_PART_FINALEXT = 256;
  104       public static final int FLAG_PART_FINALREST = 512;
  105   
  106       public static final int FLAG_PROP_ISATTR = 1;
  107       public static final int FLAG_PROP_JAVASINGLETON = 2;
  108       public static final int FLAG_PROP_JAVAOPTIONAL = 4;
  109       public static final int FLAG_PROP_JAVAARRAY = 8;
  110   
  111       public static final int FIELD_NONE = 0;
  112       public static final int FIELD_GLOBAL = 1;
  113       public static final int FIELD_LOCALATTR = 2;
  114       public static final int FIELD_LOCALELT = 3;
  115   
  116       // type flags
  117       static final int FLAG_SIMPLE_TYPE     = 0x1;
  118       static final int FLAG_DOCUMENT_TYPE   = 0x2;
  119       static final int FLAG_ORDERED         = 0x4;
  120       static final int FLAG_BOUNDED         = 0x8;
  121       static final int FLAG_FINITE          = 0x10;
  122       static final int FLAG_NUMERIC         = 0x20;
  123       static final int FLAG_STRINGENUM      = 0x40;
  124       static final int FLAG_UNION_OF_LISTS  = 0x80;
  125       static final int FLAG_HAS_PATTERN     = 0x100;
  126       static final int FLAG_ORDER_SENSITIVE = 0x200;
  127       static final int FLAG_TOTAL_ORDER     = 0x400;
  128       static final int FLAG_COMPILED        = 0x800;
  129       static final int FLAG_BLOCK_EXT       = 0x1000;
  130       static final int FLAG_BLOCK_REST      = 0x2000;
  131       static final int FLAG_FINAL_EXT       = 0x4000;
  132       static final int FLAG_FINAL_REST      = 0x8000;
  133       static final int FLAG_FINAL_UNION     = 0x10000;
  134       static final int FLAG_FINAL_LIST      = 0x20000;
  135       static final int FLAG_ABSTRACT        = 0x40000;
  136       static final int FLAG_ATTRIBUTE_TYPE  = 0x80000;
  137   
  138       /**
  139        * This is to support the feature of a separate/private XMLBeans
  140        * distribution that will not colide with the public org apache
  141        * xmlbeans one.
  142        * METADATA_PACKAGE_GEN will be "" for the original and something like
  143        * com_mycompany_private_xmlbeans for a private distribution of XMLBeans.
  144        *
  145        * There are two properties:
  146        *   METADATA_PACKAGE_GEN - used for generating metadata
  147        *   and METADATA_PACKAGE_LOAD - used for loading the metadata.
  148        * Most of the time they have the same value, with one exception, during the
  149        * repackage process scomp needs to load from old package and generate into
  150        * a new package.
  151        */
  152       public static String METADATA_PACKAGE_GEN;
  153       static
  154       {
  155           // fix for maven classloader
  156           Package stsPackage = SchemaTypeSystem.class.getPackage();
  157           String stsPackageName = (stsPackage==null) ?
  158               SchemaTypeSystem.class.getName().substring(0, SchemaTypeSystem.class.getName().lastIndexOf(".")) :
  159               stsPackage.getName();
  160   
  161           METADATA_PACKAGE_GEN = stsPackageName.replaceAll("\\.", "_");
  162       }
  163   
  164       private static String nameToPathString(String nameForSystem)
  165       {
  166           nameForSystem = nameForSystem.replace('.', '/');
  167   
  168           if (!nameForSystem.endsWith("/") && nameForSystem.length() > 0)
  169               nameForSystem = nameForSystem + "/";
  170   
  171           return nameForSystem;
  172       }
  173   
  174       public SchemaTypeSystemImpl(Class indexclass)
  175       {
  176           String fullname = indexclass.getName();
  177           _name = fullname.substring(0, fullname.lastIndexOf('.'));
  178           XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Loading type system " + _name, 1);
  179           _basePackage = nameToPathString(_name);
  180           _classloader = indexclass.getClassLoader();
  181           _linker = SchemaTypeLoaderImpl.build(null, null, _classloader);
  182           _resourceLoader = new ClassLoaderResourceLoader(_classloader);
  183           try
  184           {
  185               initFromHeader();
  186           }
  187           catch (RuntimeException e)
  188           {
  189               XBeanDebug.logException(e);
  190               throw e;
  191           }
  192           catch (Error e)
  193           {
  194               XBeanDebug.logException(e);
  195               throw e;
  196           }
  197           XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Finished loading type system " + _name, -1);
  198       }
  199   
  200       public static boolean fileContainsTypeSystem(File file, String name)
  201       {
  202           String indexname = nameToPathString(name) + "index.xsb";
  203   
  204           if (file.isDirectory())
  205           {
  206               return (new File(file, indexname)).isFile();
  207           }
  208           else
  209           {
  210               ZipFile zipfile = null;
  211               try
  212               {
  213                   zipfile = new ZipFile(file);
  214                   ZipEntry entry = zipfile.getEntry(indexname);
  215                   return (entry != null && !entry.isDirectory());
  216               }
  217               catch (IOException e)
  218               {
  219                   XBeanDebug.log("Problem loading SchemaTypeSystem, zipfilename " + file);
  220                   XBeanDebug.logException(e);
  221                   throw new SchemaTypeLoaderException(e.getMessage(), name, "index", SchemaTypeLoaderException.IO_EXCEPTION);
  222               }
  223               finally
  224               {
  225                   if (zipfile != null)
  226                       try { zipfile.close(); } catch (IOException e) {}
  227               }
  228           }
  229       }
  230   
  231       public static SchemaTypeSystemImpl forName(String name, ClassLoader loader)
  232       {
  233           try
  234           {
  235               Class c = Class.forName(name + "." + SchemaTypeCodePrinter.INDEX_CLASSNAME, true, loader);
  236               return (SchemaTypeSystemImpl)c.getField("typeSystem").get(null);
  237           }
  238           catch (Exception e)
  239           {
  240               return null;
  241           }
  242       }
  243   
  244       public SchemaTypeSystemImpl(ResourceLoader resourceLoader, String name, SchemaTypeLoader linker)
  245       {
  246           _name = name;
  247           _basePackage = nameToPathString(_name);
  248           _linker = linker;
  249           _resourceLoader = resourceLoader;
  250           try
  251           {
  252               initFromHeader();
  253           }
  254           catch (RuntimeException e)
  255           {
  256               XBeanDebug.logException(e);
  257               throw e;
  258           }
  259           catch (Error e)
  260           {
  261               XBeanDebug.logException(e);
  262               throw e;
  263           }
  264       }
  265   
  266       private void initFromHeader()
  267       {
  268           XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Reading unresolved handles for type system " + _name, 0);
  269           XsbReader reader = null;
  270           try
  271           {
  272               // Read the index file, which starts with a header.
  273               reader = new XsbReader("index", FILETYPE_SCHEMAINDEX);
  274   
  275               // has a handle pool (count, handle/type, handle/type...)
  276               _localHandles = new HandlePool();
  277               reader.readHandlePool(_localHandles);
  278   
  279               // then a qname map of global elements (count, qname/handle, qname/handle...)
  280               _globalElements = reader.readQNameRefMap();
  281   
  282               // qname map of global attributes
  283               _globalAttributes = reader.readQNameRefMap();
  284   
  285               // qname map of model groups
  286               _modelGroups = reader.readQNameRefMap();
  287   
  288               // qname map of attribute groups
  289               _attributeGroups = reader.readQNameRefMap();
  290   
  291               _identityConstraints = reader.readQNameRefMap();
  292   
  293               // qname map of global types
  294               _globalTypes = reader.readQNameRefMap();
  295   
  296               // qname map of document types, by the qname of the contained element
  297               _documentTypes = reader.readQNameRefMap();
  298   
  299               // qname mape of attribute types, by the qname of the contained attribute
  300               _attributeTypes = reader.readQNameRefMap();
  301   
  302               // string map of all types, by fully qualified classname
  303               _typeRefsByClassname = reader.readClassnameRefMap();
  304   
  305               _namespaces = reader.readNamespaces();
  306   
  307               // support for redefine, at the end of the file
  308               List typeNames = new ArrayList();
  309               List modelGroupNames = new ArrayList();
  310               List attributeGroupNames = new ArrayList();
  311               if (reader.atLeast(2, 15, 0))
  312               {
  313                   _redefinedGlobalTypes = reader.readQNameRefMapAsList(typeNames);
  314                   _redefinedModelGroups = reader.readQNameRefMapAsList(modelGroupNames);
  315                   _redefinedAttributeGroups = reader.readQNameRefMapAsList(attributeGroupNames);
  316               }
  317               if (reader.atLeast(2, 19, 0))
  318               {
  319                   _annotations = reader.readAnnotations();
  320               }
  321   
  322               buildContainers(typeNames, modelGroupNames, attributeGroupNames);
  323           }
  324           finally
  325           {
  326               if (reader != null)
  327                   reader.readEnd();
  328           }
  329       }
  330   
  331       void saveIndex()
  332       {
  333           String handle = "index";
  334           XsbReader saver = new XsbReader(handle);
  335           saver.writeIndexData();
  336           saver.writeRealHeader(handle, FILETYPE_SCHEMAINDEX);
  337           saver.writeIndexData();
  338           saver.writeEnd();
  339       }
  340   
  341       void savePointers()
  342       {
  343           savePointersForComponents(globalElements(), "schema" + METADATA_PACKAGE_GEN + "/element/");
  344           savePointersForComponents(globalAttributes(), "schema" + METADATA_PACKAGE_GEN + "/attribute/");
  345           savePointersForComponents(modelGroups(), "schema" + METADATA_PACKAGE_GEN + "/modelgroup/");
  346           savePointersForComponents(attributeGroups(), "schema" + METADATA_PACKAGE_GEN + "/attributegroup/");
  347           savePointersForComponents(globalTypes(), "schema" + METADATA_PACKAGE_GEN + "/type/");
  348           savePointersForComponents(identityConstraints(), "schema" + METADATA_PACKAGE_GEN + "/identityconstraint/");
  349           savePointersForNamespaces(_namespaces, "schema" + METADATA_PACKAGE_GEN + "/namespace/");
  350           savePointersForClassnames(_typeRefsByClassname.keySet(), "schema" + METADATA_PACKAGE_GEN + "/javaname/");
  351           savePointersForComponents(redefinedModelGroups(), "schema" + METADATA_PACKAGE_GEN + "/redefinedmodelgroup/");
  352           savePointersForComponents(redefinedAttributeGroups(), "schema" + METADATA_PACKAGE_GEN + "/redefinedattributegroup/");
  353           savePointersForComponents(redefinedGlobalTypes(), "schema" + METADATA_PACKAGE_GEN + "/redefinedtype/");
  354       }
  355   
  356       void savePointersForComponents(SchemaComponent[] components, String dir)
  357       {
  358           for (int i = 0; i < components.length; i++)
  359           {
  360               savePointerFile(dir + QNameHelper.hexsafedir(components[i].getName()), _name);
  361           }
  362       }
  363   
  364       void savePointersForClassnames(Set classnames, String dir)
  365       {
  366           for (Iterator i = classnames.iterator(); i.hasNext(); )
  367           {
  368               String classname = (String)i.next();
  369               savePointerFile(dir + classname.replace('.', '/'), _name);
  370           }
  371       }
  372   
  373       void savePointersForNamespaces(Set namespaces, String dir)
  374       {
  375           for (Iterator i = namespaces.iterator(); i.hasNext(); )
  376           {
  377               String ns = (String)i.next();
  378               savePointerFile(dir + QNameHelper.hexsafedir(new QName(ns, "xmlns")), _name);
  379           }
  380       }
  381   
  382       void savePointerFile(String filename, String name)
  383       {
  384           XsbReader saver = new XsbReader(filename);
  385           saver.writeString(name);
  386           saver.writeRealHeader(filename, FILETYPE_SCHEMAPOINTER);
  387           saver.writeString(name);
  388           saver.writeEnd();
  389       }
  390   
  391       /**
  392        * The strategy here is to copy the compiled TypeSystemHolder.template class
  393        * to a new TypeSystemHolder.class needed by the schema type system.  When
  394        * saving a loader, we read the TypeSystemHolder.template class file and
  395        * swap out the utf8 string constants with new ones to create a new
  396        * TypeSystemHolder class file.  This saves us the need to rely on javac
  397        * to compile a generated .java file into the class file.
  398        *
  399        * See the JVM spec on how to interpret the bytes of a class file.
  400        */
  401       void saveLoader()
  402       {
  403           String indexClassName = SchemaTypeCodePrinter.indexClassForSystem(this);
  404           String[] replace = makeClassStrings(indexClassName);
  405           assert replace.length == HOLDER_TEMPLATE_NAMES.length;
  406   
  407           InputStream is = null;
  408           OutputStream os = null;
  409   
  410           DataInputStream in = null;
  411           DataOutputStream out = null;
  412   
  413           Repackager repackager = null;
  414           if (_filer instanceof FilerImpl)
  415               repackager = ((FilerImpl)_filer).getRepackager();
  416   
  417           try
  418           {
  419               is = SchemaTypeSystemImpl.class.getResourceAsStream(HOLDER_TEMPLATE_CLASSFILE);
  420               if (is == null)
  421                   throw new SchemaTypeLoaderException("couldn't find resource: " + HOLDER_TEMPLATE_CLASSFILE, _name, null, SchemaTypeLoaderException.IO_EXCEPTION);
  422               in = new DataInputStream(is);
  423   
  424               os = _filer.createBinaryFile(indexClassName.replace('.', '/') + ".class");
  425               out = new DataOutputStream(os);
  426   
  427               // java magic
  428               out.writeInt(in.readInt());
  429   
  430               // java minor and major version
  431               out.writeShort(in.readUnsignedShort());
  432               out.writeShort(in.readUnsignedShort());
  433   
  434               int poolsize = in.readUnsignedShort();
  435               out.writeShort(poolsize);
  436   
  437               // the constant pool is indexed from 1 to poolsize-1
  438               for (int i = 1; i < poolsize; i++)
  439               {
  440                   int tag = in.readUnsignedByte();
  441                   out.writeByte(tag);
  442   
  443                   switch (tag)
  444                   {
  445                       case CONSTANT_UTF8:
  446                           String value = in.readUTF();
  447                           out.writeUTF(repackageConstant(value, replace, repackager));
  448                           break;
  449   
  450                       case CONSTANT_CLASS:
  451                       case CONSTANT_STRING:
  452                           out.writeShort(in.readUnsignedShort());
  453                           break;
  454   
  455                       case CONSTANT_NAMEANDTYPE:
  456                       case CONSTANT_METHOD:
  457                       case CONSTANT_FIELD:
  458                       case CONSTANT_INTERFACEMETHOD:
  459                           out.writeShort(in.readUnsignedShort());
  460                           out.writeShort(in.readUnsignedShort());
  461                           break;
  462   
  463                       case CONSTANT_INTEGER:
  464                       case CONSTANT_FLOAT:
  465                           out.writeInt(in.readInt());
  466                           break;
  467   
  468                       case CONSTANT_LONG:
  469                       case CONSTANT_DOUBLE:
  470                           out.writeInt(in.readInt());
  471                           out.writeInt(in.readInt());
  472                           break;
  473   
  474                       default:
  475                           throw new RuntimeException("Unexpected constant type: " + tag);
  476                   }
  477               }
  478   
  479               // we're done with the class' constant pool,
  480               // we can just copy the rest of the bytes
  481               try
  482               {
  483                   while (true)
  484                       out.writeByte(in.readByte());
  485               }
  486               catch (java.io.EOFException e)
  487               {
  488                   // ok
  489               }
  490   
  491           }
  492           catch (IOException e)
  493           {
  494               // ok
  495           }
  496           finally
  497           {
  498               if (is != null) try { is.close(); } catch (Exception e) { }
  499               if (os != null) try { os.close(); } catch (Exception e) { }
  500           }
  501       }
  502   
  503       private static final String HOLDER_TEMPLATE_CLASS = "org.apache.xmlbeans.impl.schema.TypeSystemHolder";
  504       private static final String HOLDER_TEMPLATE_CLASSFILE = "TypeSystemHolder.template";
  505       private static final String[] HOLDER_TEMPLATE_NAMES = makeClassStrings(HOLDER_TEMPLATE_CLASS);
  506   
  507       // constant pool entry types
  508       private static final int CONSTANT_UTF8 = 1;
  509       private static final int CONSTANT_UNICODE = 2;
  510       private static final int CONSTANT_INTEGER = 3;
  511       private static final int CONSTANT_FLOAT = 4;
  512       private static final int CONSTANT_LONG = 5;
  513       private static final int CONSTANT_DOUBLE = 6;
  514       private static final int CONSTANT_CLASS = 7;
  515       private static final int CONSTANT_STRING = 8;
  516       private static final int CONSTANT_FIELD = 9;
  517       private static final int CONSTANT_METHOD = 10;
  518       private static final int CONSTANT_INTERFACEMETHOD = 11;
  519       private static final int CONSTANT_NAMEANDTYPE = 12;
  520   
  521       // MAX_UNSIGNED_SHORT
  522       private static final int MAX_UNSIGNED_SHORT = Short.MAX_VALUE * 2 + 1;
  523   
  524       private static String repackageConstant(String value, String[] replace, Repackager repackager)
  525       {
  526           for (int i = 0; i < HOLDER_TEMPLATE_NAMES.length; i++)
  527               if (HOLDER_TEMPLATE_NAMES[i].equals(value))
  528                   return replace[i];
  529   
  530           if (repackager != null)
  531               return repackager.repackage(new StringBuffer(value)).toString();
  532   
  533           return value;
  534       }
  535   
  536       /**
  537        * Construct an array of Strings found in a class file for a classname.
  538        * For the class name 'a.b.C' it will generate an array of:
  539        * 'a.b.C', 'a/b/C', 'La/b/C;', and 'class$a$b$C'.
  540        */
  541       private static String[] makeClassStrings(String classname)
  542       {
  543           String[] result = new String[4];
  544   
  545           result[0] = classname;
  546           result[1] = classname.replace('.', '/');
  547           result[2] = "L" + result[1] + ";";
  548           result[3] = "class$" + classname.replace('.', '$');
  549   
  550           return result;
  551       }
  552   
  553       /**
  554        * Only used in the nonbootstrapped case.
  555        */
  556       private Map buildTypeRefsByClassname()
  557       {
  558           List allSeenTypes = new ArrayList();
  559           Map result = new LinkedHashMap();
  560           allSeenTypes.addAll(Arrays.asList(documentTypes()));
  561           allSeenTypes.addAll(Arrays.asList(attributeTypes()));
  562           allSeenTypes.addAll(Arrays.asList(globalTypes()));
  563   
  564           // now fully javaize everything deeply.
  565           for (int i = 0; i < allSeenTypes.size(); i++)
  566           {
  567               SchemaType gType = (SchemaType)allSeenTypes.get(i);
  568               String className = gType.getFullJavaName();
  569               if (className != null)
  570               {
  571                   result.put(className.replace('$', '.'), gType.getRef());
  572               }
  573               allSeenTypes.addAll(Arrays.asList(gType.getAnonymousTypes()));
  574           }
  575           return result;
  576       }
  577   
  578       private Map buildTypeRefsByClassname(Map typesByClassname)
  579       {
  580           Map result = new LinkedHashMap();
  581           for (Iterator i = typesByClassname.keySet().iterator(); i.hasNext(); )
  582           {
  583               String className = (String)i.next();
  584               result.put(className, ((SchemaType)typesByClassname.get(className)).getRef());
  585           }
  586           return result;
  587       }
  588   
  589       private static Map buildComponentRefMap(SchemaComponent[] components)
  590       {
  591           Map result = new LinkedHashMap();
  592           for (int i = 0; i < components.length; i++)
  593               result.put(components[i].getName(), components[i].getComponentRef());
  594           return result;
  595       }
  596   
  597       private static List buildComponentRefList(SchemaComponent[] components)
  598       {
  599           List result = new ArrayList();
  600           for (int i = 0; i < components.length; i++)
  601               result.add(components[i].getComponentRef());
  602           return result;
  603       }
  604   
  605       private static Map buildDocumentMap(SchemaType[] types)
  606       {
  607           Map result = new LinkedHashMap();
  608           for (int i = 0; i < types.length; i++)
  609               result.put(types[i].getDocumentElementName(), types[i].getRef());
  610           return result;
  611       }
  612   
  613       private static Map buildAttributeTypeMap(SchemaType[] types)
  614       {
  615           Map result = new LinkedHashMap();
  616           for (int i = 0; i < types.length; i++)
  617               result.put(types[i].getAttributeTypeAttributeName(), types[i].getRef());
  618           return result;
  619       }
  620   
  621       // Container operation
  622       private SchemaContainer getContainer(String namespace)
  623       {
  624           return (SchemaContainer) _containers.get(namespace);
  625       }
  626   
  627       private void addContainer(String namespace)
  628       {
  629           SchemaContainer c = new SchemaContainer(namespace);
  630           c.setTypeSystem(this);
  631           _containers.put(namespace, c);
  632       }
  633   
  634       private SchemaContainer getContainerNonNull(String namespace)
  635       {
  636           SchemaContainer result = getContainer(namespace);
  637           if (result == null)
  638           {
  639               addContainer(namespace);
  640               result = getContainer(namespace);
  641           }
  642           return result;
  643       }
  644   
  645       // Only called during init
  646       private void buildContainers(List redefTypeNames, List redefModelGroupNames, List redefAttributeGroupNames)
  647       {
  648           // This method walks the reference maps and copies said references
  649           // into the appropriate container
  650           for (Iterator it = _globalElements.entrySet().iterator(); it.hasNext(); )
  651           {
  652               Map.Entry entry = (Map.Entry) it.next();
  653               String ns = ((QName) entry.getKey()).getNamespaceURI();
  654               getContainerNonNull(ns).addGlobalElement((SchemaGlobalElement.Ref) entry.getValue());
  655           }
  656           for (Iterator it = _globalAttributes.entrySet().iterator(); it.hasNext(); )
  657           {
  658               Map.Entry entry = (Map.Entry) it.next();
  659               String ns = ((QName) entry.getKey()).getNamespaceURI();
  660               getContainerNonNull(ns).addGlobalAttribute((SchemaGlobalAttribute.Ref) entry.getValue());
  661           }
  662           for (Iterator it = _modelGroups.entrySet().iterator(); it.hasNext(); )
  663           {
  664               Map.Entry entry = (Map.Entry) it.next();
  665               String ns = ((QName) entry.getKey()).getNamespaceURI();
  666               getContainerNonNull(ns).addModelGroup((SchemaModelGroup.Ref) entry.getValue());
  667           }
  668           for (Iterator it = _attributeGroups.entrySet().iterator(); it.hasNext(); )
  669           {
  670               Map.Entry entry = (Map.Entry) it.next();
  671               String ns = ((QName) entry.getKey()).getNamespaceURI();
  672               getContainerNonNull(ns).addAttributeGroup((SchemaAttributeGroup.Ref) entry.getValue());
  673           }
  674           for (Iterator it = _identityConstraints.entrySet().iterator(); it.hasNext(); )
  675           {
  676               Map.Entry entry = (Map.Entry) it.next();
  677               String ns = ((QName) entry.getKey()).getNamespaceURI();
  678               getContainerNonNull(ns).addIdentityConstraint((SchemaIdentityConstraint.Ref) entry.getValue());
  679           }
  680           for (Iterator it = _globalTypes.entrySet().iterator(); it.hasNext(); )
  681           {
  682               Map.Entry entry = (Map.Entry) it.next();
  683               String ns = ((QName) entry.getKey()).getNamespaceURI();
  684               getContainerNonNull(ns).addGlobalType((SchemaType.Ref) entry.getValue());
  685           }
  686           for (Iterator it = _documentTypes.entrySet().iterator(); it.hasNext(); )
  687           {
  688               Map.Entry entry = (Map.Entry) it.next();
  689               String ns = ((QName) entry.getKey()).getNamespaceURI();
  690               getContainerNonNull(ns).addDocumentType((SchemaType.Ref) entry.getValue());
  691           }
  692           for (Iterator it = _attributeTypes.entrySet().iterator(); it.hasNext(); )
  693           {
  694               Map.Entry entry = (Map.Entry) it.next();
  695               String ns = ((QName) entry.getKey()).getNamespaceURI();
  696               getContainerNonNull(ns).addAttributeType((SchemaType.Ref) entry.getValue());
  697           }
  698           // Some earlier .xsb versions don't have records for redefinitions
  699           if (_redefinedGlobalTypes != null && _redefinedModelGroups != null &&
  700               _redefinedAttributeGroups != null)
  701           {
  702               assert _redefinedGlobalTypes.size() == redefTypeNames.size();
  703               for (Iterator it = _redefinedGlobalTypes.iterator(), itname = redefTypeNames.iterator(); it.hasNext(); )
  704               {
  705                   String ns = ((QName) itname.next()).getNamespaceURI();
  706                   getContainerNonNull(ns).addRedefinedType((SchemaType.Ref) it.next());
  707               }
  708               for (Iterator it = _redefinedModelGroups.iterator(), itname = redefModelGroupNames.iterator(); it.hasNext(); )
  709               {
  710                   String ns = ((QName) itname.next()).getNamespaceURI();
  711                   getContainerNonNull(ns).addRedefinedModelGroup((SchemaModelGroup.Ref) it.next());
  712               }
  713               for (Iterator it = _redefinedAttributeGroups.iterator(), itname = redefAttributeGroupNames.iterator(); it.hasNext(); )
  714               {
  715                   String ns = ((QName) itname.next()).getNamespaceURI();
  716                   getContainerNonNull(ns).addRedefinedAttributeGroup((SchemaAttributeGroup.Ref) it.next());
  717               }
  718           }
  719           // Some earlier .xsb versions don't have records for annotations
  720           if (_annotations != null)
  721           {
  722               for (Iterator it = _annotations.iterator(); it.hasNext(); )
  723               {
  724                   SchemaAnnotation ann = (SchemaAnnotation) it.next();
  725                   // BUGBUG(radup)
  726                   getContainerNonNull("").addAnnotation(ann);
  727               }
  728           }
  729           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  730               ((SchemaContainer) it.next()).setImmutable();
  731       }
  732   
  733       /**
  734        * This is the crux of the container work and role.
  735        * It makes a sweep over all containers and fixes each container's
  736        * typesystem to point to this typesystem.
  737        * Because SchemaComponents have a link to their containers, this has as
  738        * effect all components now indirectly pointing to this typesystem
  739        * even though they (as well as the typesystem itself) are immutable.
  740        */
  741       private void fixupContainers()
  742       {
  743           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  744           {
  745               SchemaContainer container = (SchemaContainer) it.next();
  746               container.setTypeSystem(this);
  747               container.setImmutable();
  748           }
  749       }
  750   
  751       private void assertContainersSynchronized()
  752       {
  753           boolean assertEnabled = false;
  754           // This code basically checks whether asserts are enabled so we don't do
  755           // all the work if they arent
  756           assert assertEnabled = true;
  757           if (!assertEnabled)
  758               return;
  759           // global elements
  760           Map temp = new HashMap();
  761           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  762               temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).globalElements().toArray(new SchemaComponent[0])));
  763           assert _globalElements.equals(temp);
  764           // global attributes
  765           temp = new HashMap();
  766           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  767               temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).globalAttributes().toArray(new SchemaComponent[0])));
  768           assert _globalAttributes.equals(temp);
  769           // model groups
  770           temp = new HashMap();
  771           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  772               temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).modelGroups().toArray(new SchemaComponent[0])));
  773           assert _modelGroups.equals(temp);
  774           // redefined model groups
  775           Set temp2 = new HashSet();
  776           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  777               temp2.addAll(buildComponentRefList((SchemaComponent[]) ((SchemaContainer) it.next()).redefinedModelGroups().toArray(new SchemaComponent[0])));
  778           assert new HashSet(_redefinedModelGroups).equals(temp2);
  779           // attribute groups
  780           temp = new HashMap();
  781           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  782               temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).attributeGroups().toArray(new SchemaComponent[0])));
  783           assert _attributeGroups.equals(temp);
  784           // redefined attribute groups
  785           temp2 = new HashSet();
  786           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  787               temp2.addAll(buildComponentRefList((SchemaComponent[]) ((SchemaContainer) it.next()).redefinedAttributeGroups().toArray(new SchemaComponent[0])));
  788           assert new HashSet(_redefinedAttributeGroups).equals(temp2);
  789           // global types
  790           temp = new HashMap();
  791           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  792               temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).globalTypes().toArray(new SchemaComponent[0])));
  793           assert _globalTypes.equals(temp);
  794           // redefined global types
  795           temp2 = new HashSet();
  796           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  797               temp2.addAll(buildComponentRefList((SchemaComponent[]) ((SchemaContainer) it.next()).redefinedGlobalTypes().toArray(new SchemaComponent[0])));
  798           assert new HashSet(_redefinedGlobalTypes).equals(temp2);
  799           // document types
  800           temp = new HashMap();
  801           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  802               temp.putAll(buildDocumentMap((SchemaType[]) ((SchemaContainer) it.next()).documentTypes().toArray(new SchemaType[0])));
  803           assert _documentTypes.equals(temp);
  804           // attribute types
  805           temp = new HashMap();
  806           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  807               temp.putAll(buildAttributeTypeMap((SchemaType[]) ((SchemaContainer) it.next()).attributeTypes().toArray(new SchemaType[0])));
  808           assert _attributeTypes.equals(temp);
  809           // identity constraints
  810           temp = new HashMap();
  811           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  812               temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).identityConstraints().toArray(new SchemaComponent[0])));
  813           assert _identityConstraints.equals(temp);
  814           // annotations
  815           temp2 = new HashSet();
  816           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  817               temp2.addAll(((SchemaContainer) it.next()).annotations());
  818           assert new HashSet(_annotations).equals(temp2);
  819           // namespaces
  820           temp2 = new HashSet();
  821           for (Iterator it = _containers.values().iterator(); it.hasNext(); )
  822               temp2.add(((SchemaContainer) it.next()).getNamespace());
  823           assert _namespaces.equals(temp2);
  824       }
  825   
  826       private static Random _random;
  827       private static byte[] _mask = new byte[128 / 8];
  828   
  829       /**
  830        * Fun, fun.  Produce 128 bits of uniqueness randomly.
  831        * We used to use SecureRandom, but now we don't because SecureRandom
  832        * hits the filesystem and hangs us on a filesystem lock.  It also eats
  833        * a thread and other expensive resources.. :-).
  834        *
  835        * We don't really care that non-secure Random() can only do 48 bits of
  836        * randomness, since we're certainly not going to be called more than 2^48
  837        * times within our process lifetime.
  838        *
  839        * Our real concern is that by seeding Random() with the current
  840        * time, two users will end up with the same bits if they start a
  841        * schema compilation within the same millisecond.  That makes the
  842        * probability of collision in the real world slightly too high.
  843        * We're going to have millions of users, remember?  With a million
  844        * users, and one-compilation-per-day each, we'd see a collision every
  845        * few months.
  846        *
  847        * So we'll just xor the results of random with our few extra
  848        * bits of information computed below to help reduce the probability
  849        * of collision by a few decimal places.  To collide, you will have had
  850        * to have the same amount of free memory, the same user name, timezone,
  851        * and country, the same current directory, the same java classpath,
  852        * the same operating system and jvm version, and the same choices of
  853        * identity hashcodes for a few objects. And be started within the same
  854        * millisecond. Or you can collide if you have a cosmic 128-bit mathematical
  855        * coincidence. No worries.
  856        */
  857       private static synchronized void nextBytes(byte[] result)
  858       {
  859           if (_random == null)
  860           {
  861               try
  862               {
  863                   ByteArrayOutputStream baos = new ByteArrayOutputStream();
  864                   DataOutputStream daos = new DataOutputStream(baos);
  865   
  866                   // at least 10 bits of unqieueness, right?  Maybe even 50 or 60.
  867                   daos.writeInt(System.identityHashCode(SchemaTypeSystemImpl.class));
  868                   String[] props = new String[] { "user.name", "user.dir", "user.timezone", "user.country", "java.class.path", "java.home", "java.vendor", "java.version", "os.version" };
  869                   for (int i = 0; i < props.length; i++)
  870                   {
  871                       String prop = SystemProperties.getProperty(props[i]);
  872                       if (prop != null)
  873                       {
  874                           daos.writeUTF(prop);
  875                           daos.writeInt(System.identityHashCode(prop));
  876                       }
  877                   }
  878                   daos.writeLong(Runtime.getRuntime().freeMemory());
  879                   daos.close();
  880                   byte[] bytes = baos.toByteArray();
  881                   for (int i = 0; i < bytes.length; i++)
  882                   {
  883                       int j = i % _mask.length;
  884                       _mask[j] *= 21;
  885                       _mask[j] += i;
  886                   }
  887               }
  888               catch (IOException e)
  889               {
  890                   XBeanDebug.logException(e);
  891               }
  892   
  893               _random = new Random(System.currentTimeMillis());
  894           }
  895           _random.nextBytes(result);
  896           for (int i = 0; i < result.length; i++)
  897           {
  898               int j = i & _mask.length;
  899               result[i] ^= _mask[j];
  900           }
  901       }
  902   
  903       public SchemaTypeSystemImpl(String nameForSystem)
  904       {
  905           // if we have no name, select a random one
  906           if (nameForSystem == null)
  907           {
  908               // get 128 random bits (that'll be 32 hex digits)
  909               byte[] bytes = new byte[128/8];
  910               nextBytes(bytes);
  911               nameForSystem = "s" + new String(HexBin.encode(bytes));
  912           }
  913   
  914           _name = "schema" + METADATA_PACKAGE_GEN + ".system." + nameForSystem;
  915           _basePackage = nameToPathString(_name);
  916           _classloader = null;
  917   
  918       }
  919   
  920       public void loadFromBuilder(SchemaGlobalElement[] globalElements,
  921                                   SchemaGlobalAttribute[] globalAttributes,
  922                                   SchemaType[] globalTypes,
  923                                   SchemaType[] documentTypes,
  924                                   SchemaType[] attributeTypes)
  925       {
  926           assert(_classloader == null);
  927           _localHandles = new HandlePool();
  928           _globalElements = buildComponentRefMap(globalElements);
  929           _globalAttributes = buildComponentRefMap(globalAttributes);
  930           _globalTypes = buildComponentRefMap(globalTypes);
  931           _documentTypes = buildDocumentMap(documentTypes);
  932           _attributeTypes = buildAttributeTypeMap(attributeTypes);
  933           _typeRefsByClassname = buildTypeRefsByClassname();
  934           buildContainers(Collections.EMPTY_LIST, Collections.EMPTY_LIST,
  935               Collections.EMPTY_LIST);
  936           _namespaces = new HashSet();
  937       }
  938   
  939       public void loadFromStscState(StscState state)
  940       {
  941           assert(_classloader == null);
  942           _localHandles = new HandlePool();
  943           _globalElements = buildComponentRefMap(state.globalElements());
  944           _globalAttributes = buildComponentRefMap(state.globalAttributes());
  945           _modelGroups = buildComponentRefMap(state.modelGroups());
  946           _redefinedModelGroups = buildComponentRefList(state.redefinedModelGroups());
  947           _attributeGroups = buildComponentRefMap(state.attributeGroups());
  948           _redefinedAttributeGroups = buildComponentRefList(state.redefinedAttributeGroups());
  949           _globalTypes = buildComponentRefMap(state.globalTypes());
  950           _redefinedGlobalTypes = buildComponentRefList(state.redefinedGlobalTypes());
  951           _documentTypes = buildDocumentMap(state.documentTypes());
  952           _attributeTypes = buildAttributeTypeMap(state.attributeTypes());
  953           _typeRefsByClassname = buildTypeRefsByClassname(state.typesByClassname());
  954           _identityConstraints = buildComponentRefMap(state.idConstraints());
  955           _annotations = state.annotations();
  956           _namespaces = new HashSet(Arrays.asList(state.getNamespaces()));
  957           _containers = state.getContainerMap();
  958           fixupContainers();
  959           // Checks that data in the containers matches the lookup maps
  960           assertContainersSynchronized();
  961           setDependencies(state.getDependencies());
  962       }
  963   
  964       final SchemaTypeSystemImpl getTypeSystem()
  965       {
  966           return this;
  967       }
  968   
  969       void setDependencies(SchemaDependencies deps)
  970       {   _deps = deps; }
  971   
  972       SchemaDependencies getDependencies()
  973       {   return _deps; }
  974       
  975       // EXPERIMENTAL
  976       public boolean isIncomplete() { return _incomplete; }
  977       
  978       // EXPERIMENTAL
  979       void setIncomplete(boolean incomplete) { _incomplete = incomplete; }
  980   
  981       static class StringPool
  982       {
  983           private List intsToStrings = new ArrayList();
  984           private Map stringsToInts = new HashMap();
  985           private String _handle;
  986           private String _name;
  987   
  988           /**
  989            * Constructs an empty StringPool to be filled with strings.
  990            */
  991           StringPool(String handle, String name)
  992           {
  993               _handle = handle;
  994               _name = name;
  995               intsToStrings.add(null);
  996           }
  997   
  998           int codeForString(String str)
  999           {
 1000               if (str == null)
 1001                   return 0;
 1002               Integer result = (Integer)stringsToInts.get(str);
 1003               if (result == null)
 1004               {
 1005                   result = new Integer(intsToStrings.size());
 1006                   intsToStrings.add(str);
 1007                   stringsToInts.put(str, result);
 1008               }
 1009               return result.intValue();
 1010           }
 1011   
 1012           String stringForCode(int code)
 1013           {
 1014               if (code == 0)
 1015                   return null;
 1016               return (String)intsToStrings.get(code);
 1017           }
 1018   
 1019           void writeTo(DataOutputStream output)
 1020           {
 1021               if (intsToStrings.size() >= MAX_UNSIGNED_SHORT)
 1022                   throw new SchemaTypeLoaderException("Too many strings (" + intsToStrings.size() + ")", _name, _handle, SchemaTypeLoaderException.INT_TOO_LARGE);
 1023   
 1024               try
 1025               {
 1026                   output.writeShort(intsToStrings.size());
 1027                   Iterator i = intsToStrings.iterator();
 1028                   for (i.next(); i.hasNext(); )
 1029                   {
 1030                       String str = (String)i.next();
 1031                       output.writeUTF(str);
 1032                   }
 1033               }
 1034               catch (IOException e)
 1035               {
 1036                   throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 1037               }
 1038           }
 1039   
 1040           void readFrom(DataInputStream input)
 1041           {
 1042               if (intsToStrings.size() != 1 || stringsToInts.size() != 0)
 1043                   throw new IllegalStateException();
 1044   
 1045               try
 1046               {
 1047                   int size = input.readUnsignedShort();
 1048                   for (int i = 1; i < size; i++)
 1049                   {
 1050                       String str = input.readUTF().intern();
 1051                       int code = codeForString(str);
 1052                       if (code != i)
 1053                           throw new IllegalStateException();
 1054                   }
 1055               }
 1056               catch (IOException e)
 1057               {
 1058                   throw new SchemaTypeLoaderException(e.getMessage() == null ? e.getMessage() : "IO Exception", _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION, e);
 1059               }
 1060           }
 1061       }
 1062   
 1063       class HandlePool
 1064       {
 1065           private Map _handlesToRefs = new LinkedHashMap();
 1066           private Map _componentsToHandles = new LinkedHashMap(); // populated on write
 1067           private boolean _started;
 1068   
 1069           /**
 1070            * Constructs an empty HandlePool to be populated.
 1071            */
 1072           HandlePool()
 1073           {
 1074           }
 1075   
 1076           private String addUniqueHandle(SchemaComponent obj, String base)
 1077           {
 1078               base = base.toLowerCase();  // we lowercase handles because of case-insensitive Windows filenames!!!
 1079               String handle = base;
 1080               for (int index = 2; _handlesToRefs.containsKey(handle); index++)
 1081               {
 1082                   handle = base + index;
 1083               }
 1084               _handlesToRefs.put(handle, obj.getComponentRef());
 1085               _componentsToHandles.put(obj, handle);
 1086               return handle;
 1087           }
 1088   
 1089           String handleForComponent(SchemaComponent comp)
 1090           {
 1091               if (comp == null)
 1092                   return null;
 1093               if (comp.getTypeSystem() != getTypeSystem())
 1094                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1095               if (comp instanceof SchemaType)
 1096                   return handleForType((SchemaType)comp);
 1097               if (comp instanceof SchemaGlobalElement)
 1098                   return handleForElement((SchemaGlobalElement)comp);
 1099               if (comp instanceof SchemaGlobalAttribute)
 1100                   return handleForAttribute((SchemaGlobalAttribute)comp);
 1101               if (comp instanceof SchemaModelGroup)
 1102                   return handleForModelGroup((SchemaModelGroup)comp);
 1103               if (comp instanceof SchemaAttributeGroup)
 1104                   return handleForAttributeGroup((SchemaAttributeGroup)comp);
 1105               if (comp instanceof SchemaIdentityConstraint)
 1106                   return handleForIdentityConstraint((SchemaIdentityConstraint)comp);
 1107               throw new IllegalStateException("Component type cannot have a handle");
 1108           }
 1109   
 1110           String handleForElement(SchemaGlobalElement element)
 1111           {
 1112               if (element == null)
 1113                   return null;
 1114               if (element.getTypeSystem() != getTypeSystem())
 1115                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1116               String handle = (String)_componentsToHandles.get(element);
 1117               if (handle == null)
 1118                   handle = addUniqueHandle(element, NameUtil.upperCamelCase(element.getName().getLocalPart()) + "Element");
 1119               return handle;
 1120           }
 1121   
 1122           String handleForAttribute(SchemaGlobalAttribute attribute)
 1123           {
 1124               if (attribute == null)
 1125                   return null;
 1126               if (attribute.getTypeSystem() != getTypeSystem())
 1127                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1128               String handle = (String)_componentsToHandles.get(attribute);
 1129               if (handle == null)
 1130                   handle = addUniqueHandle(attribute, NameUtil.upperCamelCase(attribute.getName().getLocalPart()) + "Attribute");
 1131               return handle;
 1132           }
 1133   
 1134           String handleForModelGroup(SchemaModelGroup group)
 1135           {
 1136               if (group == null)
 1137                   return null;
 1138               if (group.getTypeSystem() != getTypeSystem())
 1139                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1140               String handle = (String)_componentsToHandles.get(group);
 1141               if (handle == null)
 1142                   handle = addUniqueHandle(group, NameUtil.upperCamelCase(group.getName().getLocalPart()) + "ModelGroup");
 1143               return handle;
 1144           }
 1145   
 1146           String handleForAttributeGroup(SchemaAttributeGroup group)
 1147           {
 1148               if (group == null)
 1149                   return null;
 1150               if (group.getTypeSystem() != getTypeSystem())
 1151                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1152               String handle = (String)_componentsToHandles.get(group);
 1153               if (handle == null)
 1154                   handle = addUniqueHandle(group, NameUtil.upperCamelCase(group.getName().getLocalPart()) + "AttributeGroup");
 1155               return handle;
 1156           }
 1157   
 1158           String handleForIdentityConstraint(SchemaIdentityConstraint idc)
 1159           {
 1160               if (idc == null)
 1161                   return null;
 1162               if (idc.getTypeSystem() != getTypeSystem())
 1163                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1164               String handle = (String)_componentsToHandles.get(idc);
 1165               if (handle == null)
 1166                   handle = addUniqueHandle(idc, NameUtil.upperCamelCase(idc.getName().getLocalPart()) + "IdentityConstraint");
 1167               return handle;
 1168           }
 1169   
 1170           String handleForType(SchemaType type)
 1171           {
 1172               if (type == null)
 1173                   return null;
 1174               if (type.getTypeSystem() != getTypeSystem())
 1175                   throw new IllegalArgumentException("Cannot supply handles for types from another type system");
 1176               String handle = (String)_componentsToHandles.get(type);
 1177               if (handle == null)
 1178               {
 1179                   QName name = type.getName();
 1180                   String suffix = "";
 1181                   if (name == null)
 1182                   {
 1183                       if (type.isDocumentType())
 1184                       {
 1185                           name = type.getDocumentElementName();
 1186                           suffix = "Doc";
 1187                       }
 1188                       else if (type.isAttributeType())
 1189                       {
 1190                           name = type.getAttributeTypeAttributeName();
 1191                           suffix = "AttrType";
 1192                       }
 1193                       else if (type.getContainerField() != null)
 1194                       {
 1195                           name = type.getContainerField().getName();
 1196                           suffix = type.getContainerField().isAttribute() ? "Attr" : "Elem";
 1197                       }
 1198                   }
 1199   
 1200                   String baseName;
 1201                   String uniq = Integer.toHexString(type.toString().hashCode() | 0x80000000).substring(4).toUpperCase();
 1202                   if (name == null)
 1203                       baseName = "Anon" + uniq + "Type";
 1204                   else
 1205                       baseName = NameUtil.upperCamelCase(name.getLocalPart()) + uniq + suffix + "Type";
 1206   
 1207                   handle = addUniqueHandle(type, baseName);
 1208               }
 1209   
 1210               return handle;
 1211           }
 1212   
 1213           SchemaComponent.Ref refForHandle(String handle)
 1214           {
 1215               if (handle == null)
 1216                   return null;
 1217   
 1218               return (SchemaComponent.Ref)_handlesToRefs.get(handle);
 1219           }
 1220   
 1221           Set getAllHandles()
 1222           {
 1223               return _handlesToRefs.keySet();
 1224           }
 1225   
 1226           void startWriteMode()
 1227           {
 1228               _started = true;
 1229               _componentsToHandles = new LinkedHashMap();
 1230               for (Iterator i = _handlesToRefs.keySet().iterator(); i.hasNext(); )
 1231               {
 1232                   String handle = (String)i.next();
 1233   //                System.err.println("Writing preexisting handle " + handle);
 1234                   SchemaComponent comp = ((SchemaComponent.Ref)_handlesToRefs.get(handle)).getComponent();
 1235                   _componentsToHandles.put(comp, handle);
 1236               }
 1237           }
 1238   
 1239       }
 1240   
 1241       private String _name;
 1242       private String _basePackage;
 1243       
 1244       // EXPERIMENTAL: recovery from compilation errors and partial type systems
 1245       private boolean _incomplete = false;
 1246   
 1247       // classloader is available for sts's that were compiled and loaded, not dynamic ones
 1248       private ClassLoader _classloader;
 1249   
 1250       // the loader for loading .xsb resources
 1251       private ResourceLoader _resourceLoader;
 1252   
 1253       // the following is used to link references during load
 1254       SchemaTypeLoader _linker;
 1255   
 1256       private HandlePool _localHandles;
 1257       private Filer _filer;
 1258   
 1259       // top-level annotations
 1260       private List _annotations;
 1261   
 1262       // container
 1263       private Map _containers = new HashMap();
 1264       // dependencies
 1265       private SchemaDependencies _deps;
 1266   
 1267       private List _redefinedModelGroups;
 1268       private List _redefinedAttributeGroups;
 1269       private List _redefinedGlobalTypes;
 1270   
 1271       // actual type system data, map QNames -> SchemaComponent.Ref
 1272       private Map _globalElements;
 1273       private Map _globalAttributes;
 1274       private Map _modelGroups;
 1275       private Map _attributeGroups;
 1276       private Map _globalTypes;
 1277       private Map _documentTypes;
 1278       private Map _attributeTypes;
 1279       private Map _identityConstraints = Collections.EMPTY_MAP;
 1280       private Map _typeRefsByClassname = new HashMap();
 1281       private Set _namespaces;
 1282   
 1283       static private final SchemaType[] EMPTY_ST_ARRAY = new SchemaType[0];
 1284       static private final SchemaGlobalElement[] EMPTY_GE_ARRAY = new SchemaGlobalElement[0];
 1285       static private final SchemaGlobalAttribute[] EMPTY_GA_ARRAY = new SchemaGlobalAttribute[0];
 1286       static private final SchemaModelGroup[] EMPTY_MG_ARRAY = new SchemaModelGroup[0];
 1287       static private final SchemaAttributeGroup[] EMPTY_AG_ARRAY = new SchemaAttributeGroup[0];
 1288       static private final SchemaIdentityConstraint[] EMPTY_IC_ARRAY = new SchemaIdentityConstraint[0];
 1289       static private final SchemaAnnotation[] EMPTY_ANN_ARRAY = new SchemaAnnotation[0];
 1290   
 1291       public void saveToDirectory(File classDir)
 1292       {
 1293           save(new FilerImpl(classDir, null, null, false, false));
 1294       }
 1295   
 1296       public void save(Filer filer)
 1297       {
 1298           if (_incomplete)
 1299               throw new IllegalStateException("Incomplete SchemaTypeSystems cannot be saved.");
 1300   
 1301           if (filer == null)
 1302               throw new IllegalArgumentException("filer must not be null");
 1303           _filer = filer;
 1304   
 1305           _localHandles.startWriteMode();
 1306           saveTypesRecursively(globalTypes());
 1307           saveTypesRecursively(documentTypes());
 1308           saveTypesRecursively(attributeTypes());
 1309           saveGlobalElements(globalElements());
 1310           saveGlobalAttributes(globalAttributes());
 1311           saveModelGroups(modelGroups());
 1312           saveAttributeGroups(attributeGroups());
 1313           saveIdentityConstraints(identityConstraints());
 1314   
 1315           saveTypesRecursively(redefinedGlobalTypes());
 1316           saveModelGroups(redefinedModelGroups());
 1317           saveAttributeGroups(redefinedAttributeGroups());
 1318   
 1319           saveIndex();
 1320           savePointers();
 1321   
 1322           saveLoader();
 1323       }
 1324   
 1325       void saveTypesRecursively(SchemaType[] types)
 1326       {
 1327           for (int i = 0; i < types.length; i++)
 1328           {
 1329               if (types[i].getTypeSystem() != getTypeSystem())
 1330                   continue;
 1331               saveType(types[i]);
 1332               saveTypesRecursively(types[i].getAnonymousTypes());
 1333           }
 1334       }
 1335   
 1336       public void saveGlobalElements(SchemaGlobalElement[] elts)
 1337       {
 1338           if (_incomplete)
 1339               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1340           for (int i = 0; i < elts.length; i++)
 1341           {
 1342               saveGlobalElement(elts[i]);
 1343           }
 1344       }
 1345   
 1346       public void saveGlobalAttributes(SchemaGlobalAttribute[] attrs)
 1347       {
 1348           if (_incomplete)
 1349               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1350           for (int i = 0; i < attrs.length; i++)
 1351           {
 1352               saveGlobalAttribute(attrs[i]);
 1353           }
 1354       }
 1355   
 1356       public void saveModelGroups(SchemaModelGroup[] groups)
 1357       {
 1358           if (_incomplete)
 1359               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1360           for (int i = 0; i < groups.length; i++)
 1361           {
 1362               saveModelGroup(groups[i]);
 1363           }
 1364       }
 1365   
 1366       public void saveAttributeGroups(SchemaAttributeGroup[] groups)
 1367       {
 1368           if (_incomplete)
 1369               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1370           for (int i = 0; i < groups.length; i++)
 1371           {
 1372               saveAttributeGroup(groups[i]);
 1373           }
 1374       }
 1375   
 1376       public void saveIdentityConstraints(SchemaIdentityConstraint[] idcs)
 1377       {
 1378           if (_incomplete)
 1379               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1380           for (int i = 0; i < idcs.length; i++)
 1381           {
 1382               saveIdentityConstraint(idcs[i]);
 1383           }
 1384       }
 1385   
 1386       public void saveGlobalElement(SchemaGlobalElement elt)
 1387       {
 1388           if (_incomplete)
 1389               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1390           String handle = _localHandles.handleForElement(elt);
 1391           XsbReader saver = new XsbReader(handle);
 1392           saver.writeParticleData((SchemaParticle)elt);
 1393           saver.writeString(elt.getSourceName());
 1394           saver.writeRealHeader(handle, FILETYPE_SCHEMAELEMENT);
 1395           saver.writeParticleData((SchemaParticle)elt);
 1396           saver.writeString(elt.getSourceName());
 1397           saver.writeEnd();
 1398       }
 1399   
 1400       public void saveGlobalAttribute(SchemaGlobalAttribute attr)
 1401       {
 1402           if (_incomplete)
 1403               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1404           String handle = _localHandles.handleForAttribute(attr);
 1405           XsbReader saver = new XsbReader(handle);
 1406           saver.writeAttributeData(attr);
 1407           saver.writeString(attr.getSourceName());
 1408           saver.writeRealHeader(handle, FILETYPE_SCHEMAATTRIBUTE);
 1409           saver.writeAttributeData(attr);
 1410           saver.writeString(attr.getSourceName());
 1411           saver.writeEnd();
 1412       }
 1413   
 1414       public void saveModelGroup(SchemaModelGroup grp)
 1415       {
 1416           if (_incomplete)
 1417               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1418           String handle = _localHandles.handleForModelGroup(grp);
 1419           XsbReader saver = new XsbReader(handle);
 1420           saver.writeModelGroupData(grp);
 1421           saver.writeRealHeader(handle, FILETYPE_SCHEMAMODELGROUP);
 1422           saver.writeModelGroupData(grp);
 1423           saver.writeEnd();
 1424       }
 1425   
 1426       public void saveAttributeGroup(SchemaAttributeGroup grp)
 1427       {
 1428           if (_incomplete)
 1429               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1430           String handle = _localHandles.handleForAttributeGroup(grp);
 1431           XsbReader saver = new XsbReader(handle);
 1432           saver.writeAttributeGroupData(grp);
 1433           saver.writeRealHeader(handle, FILETYPE_SCHEMAATTRIBUTEGROUP);
 1434           saver.writeAttributeGroupData(grp);
 1435           saver.writeEnd();
 1436       }
 1437   
 1438       public void saveIdentityConstraint(SchemaIdentityConstraint idc)
 1439       {
 1440           if (_incomplete)
 1441               throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
 1442           String handle = _localHandles.handleForIdentityConstraint(idc);
 1443           XsbReader saver = new XsbReader(handle);
 1444           saver.writeIdConstraintData(idc);
 1445           saver.writeRealHeader(handle, FILETYPE_SCHEMAIDENTITYCONSTRAINT);
 1446           saver.writeIdConstraintData(idc);
 1447           saver.writeEnd();
 1448       }
 1449   
 1450       void saveType(SchemaType type)
 1451       {
 1452           String handle = _localHandles.handleForType(type);
 1453           XsbReader saver = new XsbReader(handle);
 1454           saver.writeTypeData(type);
 1455           saver.writeRealHeader(handle, FILETYPE_SCHEMATYPE);
 1456           saver.writeTypeData(type);
 1457           saver.writeEnd();
 1458       }
 1459   
 1460       public static String crackPointer(InputStream stream)
 1461       {
 1462           DataInputStream input = null;
 1463           try
 1464           {
 1465               input = new DataInputStream(stream);
 1466   
 1467               int magic = input.readInt();
 1468               if (magic != DATA_BABE)
 1469                   return null;
 1470   
 1471               int majorver = input.readShort();
 1472               int minorver = input.readShort();
 1473   
 1474               if (majorver != MAJOR_VERSION)
 1475                   return null;
 1476   
 1477               if (minorver > MINOR_VERSION)
 1478                   return null;
 1479   
 1480               if (majorver > 2 || majorver == 2 && minorver >= 18)
 1481                   input.readShort(); // release number present in atLeast(2, 18, 0)
 1482   
 1483               int actualfiletype = input.readShort();
 1484               if (actualfiletype != FILETYPE_SCHEMAPOINTER)
 1485                   return null;
 1486   
 1487               StringPool stringPool = new StringPool("pointer", "unk");
 1488               stringPool.readFrom(input);
 1489   
 1490               return stringPool.stringForCode(input.readShort());
 1491           }
 1492           catch (IOException e)
 1493           {
 1494               return null;
 1495           }
 1496           finally
 1497           {
 1498               if (input != null)
 1499                   try { input.close(); } catch (IOException e) {}
 1500           }
 1501       }
 1502   
 1503       private class XsbReader
 1504       {
 1505           DataInputStream _input;
 1506           DataOutputStream _output;
 1507           StringPool _stringPool;
 1508           String _handle;
 1509           private int _majorver;
 1510           private int _minorver;
 1511           private int _releaseno;
 1512           int _actualfiletype;
 1513   
 1514           public XsbReader(String handle, int filetype)
 1515           {
 1516               String resourcename = _basePackage + handle + ".xsb";
 1517               InputStream rawinput = getLoaderStream(resourcename);
 1518               if (rawinput == null)
 1519                   throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Could not locate compiled schema resource " + resourcename, _name, handle, SchemaTypeLoaderException.NO_RESOURCE);
 1520   
 1521               _input = new DataInputStream(rawinput);
 1522               _handle = handle;
 1523   
 1524               int magic = readInt();
 1525               if (magic != DATA_BABE)
 1526                   throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Wrong magic cookie", _name, handle, SchemaTypeLoaderException.WRONG_MAGIC_COOKIE);
 1527   
 1528               _majorver = readShort();
 1529               _minorver = readShort();
 1530   
 1531               if (_majorver != MAJOR_VERSION)
 1532                   throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Wrong major version - expecting " + MAJOR_VERSION + ", got " + _majorver, _name, handle, SchemaTypeLoaderException.WRONG_MAJOR_VERSION);
 1533   
 1534               if (_minorver > MINOR_VERSION)
 1535                   throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Incompatible minor version - expecting up to " + MINOR_VERSION + ", got " + _minorver, _name, handle, SchemaTypeLoaderException.WRONG_MINOR_VERSION);
 1536   
 1537               // Clip to 14 because we're not backward compatible with earlier
 1538               // minor versions.  Remove this when upgrading to a new major
 1539               // version
 1540   
 1541               if (_minorver < 14)
 1542                   throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Incompatible minor version - expecting at least 14, got " + _minorver, _name, handle, SchemaTypeLoaderException.WRONG_MINOR_VERSION);
 1543   
 1544               if (atLeast(2, 18, 0))
 1545                   _releaseno = readShort();
 1546   
 1547               int actualfiletype = readShort();
 1548               if (actualfiletype != filetype && filetype != 0xFFFF)
 1549                   throw new SchemaTypeLoaderException("XML-BEANS compiled schema: File has the wrong type - expecting type " + filetype + ", got type " + actualfiletype, _name, handle, SchemaTypeLoaderException.WRONG_FILE_TYPE);
 1550   
 1551               _stringPool = new StringPool(_handle, _name);
 1552               _stringPool.readFrom(_input);
 1553   
 1554               _actualfiletype = actualfiletype;
 1555           }
 1556   
 1557           protected boolean atLeast(int majorver, int minorver, int releaseno)
 1558           {
 1559               if (_majorver > majorver)
 1560                   return true;
 1561               if (_majorver < majorver)
 1562                   return false;
 1563               if (_minorver > minorver)
 1564                   return true;
 1565               if (_minorver < minorver)
 1566                   return false;
 1567               return (_releaseno >= releaseno);
 1568           }
 1569   
 1570           protected boolean atMost(int majorver, int minorver, int releaseno)
 1571           {
 1572               if (_majorver > majorver)
 1573                   return false;
 1574               if (_majorver < majorver)
 1575                   return true;
 1576               if (_minorver > minorver)
 1577                   return false;
 1578               if (_minorver < minorver)
 1579                   return true;
 1580               return (_releaseno <= releaseno);
 1581           }
 1582   
 1583           int getActualFiletype()
 1584           {
 1585               return _actualfiletype;
 1586           }
 1587   
 1588           XsbReader(String handle)
 1589           {
 1590               _handle = handle;
 1591               _stringPool = new StringPool(_handle, _name);
 1592           }
 1593   
 1594           void writeRealHeader(String handle, int filetype)
 1595           {
 1596               // hackeroo: if handle contains a "/" it's not relative.
 1597               String resourcename;
 1598   
 1599               if (handle.indexOf('/') >= 0)
 1600                   resourcename = handle + ".xsb";
 1601               else
 1602                   resourcename = _basePackage + handle + ".xsb";
 1603   
 1604               OutputStream rawoutput = getSaverStream(resourcename);
 1605               if (rawoutput == null)
 1606                   throw new SchemaTypeLoaderException("Could not write compiled schema resource " + resourcename, _name, handle, SchemaTypeLoaderException.NOT_WRITEABLE);
 1607   
 1608               _output = new DataOutputStream(rawoutput);
 1609               _handle = handle;
 1610   
 1611               writeInt(DATA_BABE);
 1612               writeShort(MAJOR_VERSION);
 1613               writeShort(MINOR_VERSION);
 1614               writeShort(RELEASE_NUMBER);
 1615               writeShort(filetype);
 1616   
 1617               _stringPool.writeTo(_output);
 1618           }
 1619   
 1620           void readEnd()
 1621           {
 1622               try
 1623               {
 1624                   if (_input != null)
 1625                       _input.close();
 1626               }
 1627               catch (IOException e)
 1628               {
 1629                   // oh, well.
 1630               }
 1631               _input = null;
 1632               _stringPool = null;
 1633               _handle = null;
 1634           }
 1635   
 1636           void writeEnd()
 1637           {
 1638               try
 1639               {
 1640                   if (_output != null)
 1641                   {
 1642                       _output.flush();
 1643                       _output.close();
 1644                   }
 1645               }
 1646               catch (IOException e)
 1647               {
 1648                   throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 1649               }
 1650               _output = null;
 1651               _stringPool = null;
 1652               _handle = null;
 1653           }
 1654   
 1655           int fileTypeFromComponentType(int componentType)
 1656           {
 1657               switch (componentType)
 1658               {
 1659                   case SchemaComponent.TYPE:
 1660                       return SchemaTypeSystemImpl.FILETYPE_SCHEMATYPE;
 1661                   case SchemaComponent.ELEMENT:
 1662                       return SchemaTypeSystemImpl.FILETYPE_SCHEMAELEMENT;
 1663                   case SchemaComponent.ATTRIBUTE:
 1664                       return SchemaTypeSystemImpl.FILETYPE_SCHEMAATTRIBUTE;
 1665                   case SchemaComponent.MODEL_GROUP:
 1666                       return SchemaTypeSystemImpl.FILETYPE_SCHEMAMODELGROUP;
 1667                   case SchemaComponent.ATTRIBUTE_GROUP:
 1668                       return SchemaTypeSystemImpl.FILETYPE_SCHEMAATTRIBUTEGROUP;
 1669                   case SchemaComponent.IDENTITY_CONSTRAINT:
 1670                       return SchemaTypeSystemImpl.FILETYPE_SCHEMAIDENTITYCONSTRAINT;
 1671                   default:
 1672                       throw new IllegalStateException("Unexpected component type");
 1673               }
 1674           }
 1675   
 1676           void writeIndexData()
 1677           {
 1678               // has a handle pool (count, handle/type, handle/type...)
 1679               writeHandlePool(_localHandles);
 1680   
 1681               // then a qname map of global elements (count, qname/handle, qname/handle...)
 1682               writeQNameMap(globalElements());
 1683   
 1684               // qname map of global attributes
 1685               writeQNameMap(globalAttributes());
 1686   
 1687               // qname map of model groups
 1688               writeQNameMap(modelGroups());
 1689   
 1690               // qname map of attribute groups
 1691               writeQNameMap(attributeGroups());
 1692   
 1693               // qname map of identity constraints
 1694               writeQNameMap(identityConstraints());
 1695   
 1696               // qname map of global types
 1697               writeQNameMap(globalTypes());
 1698   
 1699               // qname map of document types, by the qname of the contained element
 1700               writeDocumentTypeMap(documentTypes());
 1701   
 1702               // qname map of attribute types, by the qname of the contained attribute
 1703               writeAttributeTypeMap(attributeTypes());
 1704   
 1705               // all the types by classname
 1706               writeClassnameMap(_typeRefsByClassname);
 1707   
 1708               // all the namespaces
 1709               writeNamespaces(_namespaces);
 1710   
 1711               // VERSION 2.15 and newer below
 1712               writeQNameMap(redefinedGlobalTypes());
 1713               writeQNameMap(redefinedModelGroups());
 1714               writeQNameMap(redefinedAttributeGroups());
 1715               writeAnnotations(annotations());
 1716           }
 1717   
 1718           void writeHandlePool(HandlePool pool)
 1719           {
 1720               writeShort(pool._componentsToHandles.size());
 1721               for (Iterator i = pool._componentsToHandles.keySet().iterator(); i.hasNext(); )
 1722               {
 1723                   SchemaComponent comp = (SchemaComponent)i.next();
 1724                   String handle = (String)pool._componentsToHandles.get(comp);
 1725                   int code = fileTypeFromComponentType(comp.getComponentType());
 1726                   writeString(handle);
 1727                   writeShort(code);
 1728               }
 1729           }
 1730   
 1731           void readHandlePool(HandlePool pool)
 1732           {
 1733               if (pool._handlesToRefs.size() != 0 || pool._started)
 1734                   throw new IllegalStateException("Nonempty handle set before read");
 1735   
 1736               int size = readShort();
 1737               for (int i = 0; i < size; i++)
 1738               {
 1739                   String handle = readString();
 1740                   int code = readShort();
 1741                   Object result;
 1742                   switch (code)
 1743                   {
 1744                       case FILETYPE_SCHEMATYPE:
 1745                           result = new SchemaType.Ref(getTypeSystem(), handle);
 1746                           break;
 1747                       case FILETYPE_SCHEMAELEMENT:
 1748                           result = new SchemaGlobalElement.Ref(getTypeSystem(), handle);
 1749                           break;
 1750                       case FILETYPE_SCHEMAATTRIBUTE:
 1751                           result = new SchemaGlobalAttribute.Ref(getTypeSystem(), handle);
 1752                           break;
 1753                       case FILETYPE_SCHEMAMODELGROUP:
 1754                           result = new SchemaModelGroup.Ref(getTypeSystem(), handle);
 1755                           break;
 1756                       case FILETYPE_SCHEMAATTRIBUTEGROUP:
 1757                           result = new SchemaAttributeGroup.Ref(getTypeSystem(), handle);
 1758                           break;
 1759                       case FILETYPE_SCHEMAIDENTITYCONSTRAINT:
 1760                           result = new SchemaIdentityConstraint.Ref(getTypeSystem(), handle);
 1761                           break;
 1762                       default:
 1763                           throw new SchemaTypeLoaderException("Schema index has an unrecognized entry of type " + code, _name, handle, SchemaTypeLoaderException.UNRECOGNIZED_INDEX_ENTRY);
 1764                   }
 1765                   pool._handlesToRefs.put(handle, result);
 1766               }
 1767           }
 1768   
 1769           int readShort()
 1770           {
 1771               try
 1772               {
 1773                   return _input.readUnsignedShort();
 1774               }
 1775               catch (IOException e)
 1776               {
 1777                   throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 1778               }
 1779           }
 1780   
 1781           void writeShort(int s)
 1782           {
 1783               if (s >= MAX_UNSIGNED_SHORT || s < -1)
 1784                   throw new SchemaTypeLoaderException("Value " + s + " out of range: must fit in a 16-bit unsigned short.", _name, _handle, SchemaTypeLoaderException.INT_TOO_LARGE);
 1785               if (_output != null)
 1786               {
 1787                   try
 1788                   {
 1789                       _output.writeShort(s);
 1790                   }
 1791                   catch (IOException e)
 1792                   {
 1793                       throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 1794                   }
 1795               }
 1796           }
 1797   
 1798           int readInt()
 1799           {
 1800               try
 1801               {
 1802                   return _input.readInt();
 1803               }
 1804               catch (IOException e)
 1805               {
 1806                   throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 1807               }
 1808           }
 1809   
 1810           void writeInt(int i)
 1811           {
 1812               if (_output != null)
 1813               {
 1814                   try
 1815                   {
 1816                       _output.writeInt(i);
 1817                   }
 1818                   catch (IOException e)
 1819                   {
 1820                       throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 1821                   }
 1822               }
 1823           }
 1824   
 1825           String readString()
 1826           {
 1827               return _stringPool.stringForCode(readShort());
 1828           }
 1829   
 1830           void writeString(String str)
 1831           {
 1832               int code = _stringPool.codeForString(str);
 1833               writeShort(code);
 1834           }
 1835   
 1836           QName readQName()
 1837           {
 1838               String namespace = readString();
 1839               String localname = readString();
 1840               if (localname == null)
 1841                   return null;
 1842               return new QName(namespace, localname);
 1843           }
 1844   
 1845           void writeQName(QName qname)
 1846           {
 1847               if (qname == null)
 1848               {
 1849                   writeString(null);
 1850                   writeString(null);
 1851                   return;
 1852               }
 1853               writeString(qname.getNamespaceURI());
 1854               writeString(qname.getLocalPart());
 1855           }
 1856   
 1857           SOAPArrayType readSOAPArrayType()
 1858           {
 1859               QName qName = readQName();
 1860               String dimensions = readString();
 1861               if (qName == null)
 1862                   return null;
 1863               return new SOAPArrayType(qName, dimensions);
 1864           }
 1865   
 1866           void writeSOAPArrayType(SOAPArrayType arrayType)
 1867           {
 1868               if (arrayType == null)
 1869               {
 1870                   writeQName(null);
 1871                   writeString(null);
 1872               }
 1873               else
 1874               {
 1875                   writeQName(arrayType.getQName());
 1876                   writeString(arrayType.soap11DimensionString());
 1877               }
 1878           }
 1879   
 1880           void writeAnnotation(SchemaAnnotation a)
 1881           {
 1882               // Write attributes
 1883               if (a == null)
 1884               {
 1885                   writeInt(-1);
 1886                   return;
 1887               }
 1888               SchemaAnnotation.Attribute[] attributes = a.getAttributes();
 1889               writeInt(attributes.length);
 1890               for (int i = 0; i < attributes.length; i++)
 1891               {
 1892                   QName name = attributes[i].getName();
 1893                   String value = attributes[i].getValue();
 1894                   String valueURI = attributes[i].getValueUri();
 1895                   writeQName(name);
 1896                   writeString(value);
 1897                   writeString(valueURI);
 1898               }
 1899   
 1900               // Write documentation items
 1901               XmlObject[] documentationItems = a.getUserInformation();
 1902               writeInt(documentationItems.length);
 1903               XmlOptions opt = new XmlOptions().setSaveOuter().
 1904                   setSaveAggressiveNamespaces();
 1905               for (int i = 0; i < documentationItems.length; i++)
 1906               {
 1907                   XmlObject doc = documentationItems[i];
 1908                   writeString(doc.xmlText(opt));
 1909               }
 1910   
 1911               // Write application info items
 1912               XmlObject[] appInfoItems = a.getApplicationInformation();
 1913               writeInt(appInfoItems.length);
 1914               for (int i = 0; i < appInfoItems.length; i++)
 1915               {
 1916                   XmlObject doc = appInfoItems[i];
 1917                   writeString(doc.xmlText(opt));
 1918               }
 1919           }
 1920   
 1921           SchemaAnnotation readAnnotation(SchemaContainer c)
 1922           {
 1923               if (!atLeast(2, 19, 0))
 1924                   return null; // no annotations for this version of the file
 1925               // Read attributes
 1926               int n = readInt();
 1927               if (n == -1)
 1928                   return null;
 1929               SchemaAnnotation.Attribute[] attributes =
 1930                   new SchemaAnnotation.Attribute[n];
 1931               for (int i = 0; i < n; i++)
 1932               {
 1933                   QName name = readQName();
 1934                   String value = readString();
 1935                   String valueUri = null;
 1936                   if (atLeast(2, 24, 0))
 1937                       valueUri = readString();
 1938                   attributes[i] = new SchemaAnnotationImpl.AttributeImpl(name, value, valueUri);
 1939               }
 1940   
 1941               // Read documentation items
 1942               n = readInt();
 1943               String[] docStrings = new String[n];
 1944               for (int i = 0; i <  n; i++)
 1945               {
 1946                   docStrings[i] = readString();
 1947               }
 1948   
 1949               // Read application info items
 1950               n = readInt();
 1951               String[] appInfoStrings = new String[n];
 1952               for (int i = 0; i < n; i++)
 1953               {
 1954                   appInfoStrings[i] = readString();
 1955               }
 1956   
 1957               return new SchemaAnnotationImpl(c, appInfoStrings,
 1958                   docStrings, attributes);
 1959           }
 1960   
 1961           void writeAnnotations(SchemaAnnotation[] anns)
 1962           {
 1963               writeInt(anns.length);
 1964               for (int i = 0; i < anns.length; i++)
 1965                   writeAnnotation(anns[i]);
 1966           }
 1967   
 1968           List readAnnotations()
 1969           {
 1970               int n = readInt();
 1971               List result = new ArrayList(n);
 1972               // BUGBUG(radup)
 1973               SchemaContainer container = getContainerNonNull("");
 1974               for (int i = 0; i < n; i++)
 1975                   result.add(readAnnotation(container));
 1976               return result;
 1977           }
 1978   
 1979           SchemaComponent.Ref readHandle()
 1980           {
 1981               String handle = readString();
 1982               if (handle == null)
 1983                   return null;
 1984   
 1985               if (handle.charAt(0) != '_')
 1986                   return _localHandles.refForHandle(handle);
 1987   
 1988               switch (handle.charAt(2))
 1989               {
 1990                   case 'I': // _BI_ - built-in schema type system
 1991                       return ((SchemaType)BuiltinSchemaTypeSystem.get().resolveHandle(handle)).getRef();
 1992                   case 'T': // _XT_ - external type
 1993                       return _linker.findTypeRef(QNameHelper.forPretty(handle, 4));
 1994                   case 'E': // _XE_ - external element
 1995                       return _linker.findElementRef(QNameHelper.forPretty(handle, 4));
 1996                   case 'A': // _XA_ - external attribute
 1997                       return _linker.findAttributeRef(QNameHelper.forPretty(handle, 4));
 1998                   case 'M': // _XM_ - external model group
 1999                       return _linker.findModelGroupRef(QNameHelper.forPretty(handle, 4));
 2000                   case 'N': // _XN_ - external attribute group
 2001                       return _linker.findAttributeGroupRef(QNameHelper.forPretty(handle, 4));
 2002                   case 'D': // _XD_ - external identity constraint
 2003                       return _linker.findIdentityConstraintRef(QNameHelper.forPretty(handle, 4));
 2004                   case 'R': // _XR_ - external ref to attribute's type
 2005                       // deprecated: replaced by _XY_
 2006                       SchemaGlobalAttribute attr = _linker.findAttribute(QNameHelper.forPretty(handle, 4));
 2007                       if (attr == null)
 2008                           throw new SchemaTypeLoaderException("Cannot resolve attribute for handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
 2009                       return attr.getType().getRef();
 2010                   case 'S': // _XS_ - external ref to element's type
 2011                       // deprecated: replaced by _XY_
 2012                       SchemaGlobalElement elem = _linker.findElement(QNameHelper.forPretty(handle, 4));
 2013                       if (elem == null)
 2014                           throw new SchemaTypeLoaderException("Cannot resolve element for handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
 2015                       return elem.getType().getRef();
 2016                   case 'O': // _XO_ - external ref to document type
 2017                       return _linker.findDocumentTypeRef(QNameHelper.forPretty(handle, 4));
 2018                   case 'Y': // _XY_ - external ref to any possible type
 2019                       SchemaType type = _linker.typeForSignature(handle.substring(4));
 2020                       if (type == null)
 2021                           throw new SchemaTypeLoaderException("Cannot resolve type for handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
 2022                       return type.getRef();
 2023                   default:
 2024                       throw new SchemaTypeLoaderException("Cannot resolve handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
 2025               }
 2026           }
 2027   
 2028           void writeHandle(SchemaComponent comp)
 2029           {
 2030               if (comp == null || comp.getTypeSystem() == getTypeSystem())
 2031               {
 2032                   writeString(_localHandles.handleForComponent(comp));
 2033                   return;
 2034               }
 2035   
 2036               switch (comp.getComponentType())
 2037               {
 2038                   case SchemaComponent.ATTRIBUTE:
 2039                       writeString("_XA_" + QNameHelper.pretty(comp.getName()));
 2040                       return;
 2041                   case SchemaComponent.MODEL_GROUP:
 2042                       writeString("_XM_" + QNameHelper.pretty(comp.getName()));
 2043                       return;
 2044                   case SchemaComponent.ATTRIBUTE_GROUP:
 2045                       writeString("_XN_" + QNameHelper.pretty(comp.getName()));
 2046                       return;
 2047                   case SchemaComponent.ELEMENT:
 2048                       writeString("_XE_" + QNameHelper.pretty(comp.getName()));
 2049                       return;
 2050                   case SchemaComponent.IDENTITY_CONSTRAINT:
 2051                       writeString("_XD_" + QNameHelper.pretty(comp.getName()));
 2052                       return;
 2053                   case SchemaComponent.TYPE:
 2054                       SchemaType type = (SchemaType)comp;
 2055                       if (type.isBuiltinType())
 2056                       {
 2057                           writeString("_BI_" + type.getName().getLocalPart());
 2058                           return;
 2059                       }
 2060   
 2061                       // fix for CR120759 - added output of types _XR_ & _XS_
 2062                       // when an attribute (_XR_) or element (_XS_) declaration
 2063                       // uses ref to refer to an attribute or element in another
 2064                       // schema and the type of that attribute or element
 2065                       // is an anonymous (local) type
 2066                       // kkrouse 02/1/2005: _XR_ and _XS_ refs are replaced by _XY_
 2067                       if (type.getName() != null)
 2068                       {
 2069                           writeString("_XT_" + QNameHelper.pretty(type.getName()));
 2070                       }
 2071                       else if (type.isDocumentType())
 2072                       {
 2073                           // Substitution groups will create document types that
 2074                           // extend from other document types, possibly in
 2075                           // different jars
 2076                           writeString("_XO_" + QNameHelper.pretty(type.getDocumentElementName()));
 2077                       }
 2078                       else
 2079                       {
 2080                           // fix for XMLBEANS-105:
 2081                           // save out the external type reference using the type's signature.
 2082                           writeString("_XY_" + type.toString());
 2083                       }
 2084   
 2085                       return;
 2086   
 2087                   default:
 2088                       assert(false);
 2089                       throw new SchemaTypeLoaderException("Cannot write handle for component " + comp, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
 2090               }
 2091           }
 2092   
 2093           SchemaType.Ref readTypeRef()
 2094           {
 2095               return (SchemaType.Ref)readHandle();
 2096           }
 2097   
 2098           void writeType(SchemaType type)
 2099           {
 2100               writeHandle(type);
 2101           }
 2102   
 2103           Map readQNameRefMap()
 2104           {
 2105               Map result = new HashMap();
 2106               int size = readShort();
 2107               for (int i = 0; i < size; i++)
 2108               {
 2109                   QName name = readQName();
 2110                   SchemaComponent.Ref obj = readHandle();
 2111                   result.put(name, obj);
 2112               }
 2113               return result;
 2114           }
 2115   
 2116           List readQNameRefMapAsList(List names)
 2117           {
 2118               int size = readShort();
 2119               List result = new ArrayList(size);
 2120               for (int i = 0; i < size; i++)
 2121               {
 2122                   QName name = readQName();
 2123                   SchemaComponent.Ref obj = readHandle();
 2124                   result.add(obj);
 2125                   names.add(name);
 2126               }
 2127               return result;
 2128           }
 2129   
 2130           void writeQNameMap(SchemaComponent[] components)
 2131           {
 2132               writeShort(components.length);
 2133               for (int i = 0; i < components.length; i++)
 2134               {
 2135                   writeQName(components[i].getName());
 2136                   writeHandle(components[i]);
 2137               }
 2138           }
 2139   
 2140           void writeDocumentTypeMap(SchemaType[] doctypes)
 2141           {
 2142               writeShort(doctypes.length);
 2143               for (int i = 0; i < doctypes.length; i++)
 2144               {
 2145                   writeQName(doctypes[i].getDocumentElementName());
 2146                   writeHandle(doctypes[i]);
 2147               }
 2148           }
 2149   
 2150           void writeAttributeTypeMap(SchemaType[] attrtypes)
 2151           {
 2152               writeShort(attrtypes.length);
 2153               for (int i = 0; i < attrtypes.length; i++)
 2154               {
 2155                   writeQName(attrtypes[i].getAttributeTypeAttributeName());
 2156                   writeHandle(attrtypes[i]);
 2157               }
 2158           }
 2159   
 2160           SchemaType.Ref[] readTypeRefArray()
 2161           {
 2162               int size = readShort();
 2163               SchemaType.Ref[] result = new SchemaType.Ref[size];
 2164               for (int i = 0; i < size; i++)
 2165               {
 2166                   result[i] = readTypeRef();
 2167               }
 2168               return result;
 2169           }
 2170   
 2171           void writeTypeArray(SchemaType[] array)
 2172           {
 2173               writeShort(array.length);
 2174               for (int i = 0; i < array.length; i++)
 2175               {
 2176                   writeHandle(array[i]);
 2177               }
 2178           }
 2179   
 2180           Map readClassnameRefMap()
 2181           {
 2182               Map result = new HashMap();
 2183               int size = readShort();
 2184               for (int i = 0; i < size; i++)
 2185               {
 2186                   String name = readString();
 2187                   SchemaComponent.Ref obj = readHandle();
 2188                   result.put(name, obj);
 2189               }
 2190               return result;
 2191           }
 2192   
 2193           void writeClassnameMap(Map typesByClass)
 2194           {
 2195               writeShort(typesByClass.size());
 2196               for (Iterator i = typesByClass.keySet().iterator(); i.hasNext(); )
 2197               {
 2198                   String className = (String)i.next();
 2199                   writeString(className);
 2200                   writeHandle(((SchemaType.Ref)typesByClass.get(className)).get());
 2201               }
 2202           }
 2203   
 2204           Set readNamespaces()
 2205           {
 2206               Set result = new HashSet();
 2207               int size = readShort();
 2208               for (int i = 0; i < size; i++)
 2209               {
 2210                   String ns = readString();
 2211                   result.add(ns);
 2212               }
 2213               return result;
 2214           }
 2215   
 2216           void writeNamespaces(Set namespaces)
 2217           {
 2218               writeShort(namespaces.size());
 2219               for (Iterator i = namespaces.iterator(); i.hasNext(); )
 2220               {
 2221                   String ns = (String)i.next();
 2222                   writeString(ns);
 2223               }
 2224           }
 2225   
 2226           OutputStream getSaverStream(String name)
 2227           {
 2228               try
 2229               {
 2230                   return _filer.createBinaryFile(name);
 2231               }
 2232               catch (IOException e)
 2233               {
 2234                   throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
 2235               }
 2236           }
 2237   
 2238           InputStream getLoaderStream(String resourcename)
 2239           {
 2240               return _resourceLoader.getResourceAsStream(resourcename);
 2241           }
 2242   
 2243           void checkContainerNotNull(SchemaContainer container, QName name)
 2244           {
 2245               if (container == null)
 2246               {
 2247                   throw new LinkageError("Loading of resource " + _name + '.' + _handle +
 2248                       "failed, information from " + _name + ".index.xsb is " +
 2249                       " out of sync (or conflicting index files found)");
 2250               }
 2251           }
 2252   
 2253           /**
 2254            * Finishes loading an element after the header has already been loaded.
 2255            */
 2256           public SchemaGlobalElement finishLoadingElement()
 2257           {
 2258               String handle = null;
 2259               try
 2260               {
 2261                   int particleType = readShort();
 2262                   if (particleType != SchemaParticle.ELEMENT)
 2263                       throw new SchemaTypeLoaderException("Wrong particle type ", _name, _handle, SchemaTypeLoaderException.BAD_PARTICLE_TYPE);
 2264                   int particleFlags = readShort();
 2265                   BigInteger minOccurs = readBigInteger();
 2266                   BigInteger maxOccurs = readBigInteger();
 2267                   QNameSet transitionRules = readQNameSet();
 2268                   QName name = readQName();
 2269                   SchemaContainer container = getContainer(name.getNamespaceURI());
 2270                   checkContainerNotNull(container, name);
 2271                   SchemaGlobalElementImpl impl = new SchemaGlobalElementImpl(container);
 2272                   impl.setParticleType(particleType);
 2273                   impl.setMinOccurs(minOccurs);
 2274                   impl.setMaxOccurs(maxOccurs);
 2275                   impl.setTransitionRules(transitionRules,
 2276                       (particleFlags & FLAG_PART_SKIPPABLE) != 0);
 2277                   impl.setNameAndTypeRef(name, readTypeRef());
 2278                   impl.setDefault(readString(), (particleFlags & FLAG_PART_FIXED) != 0, null);
 2279                   if (atLeast(2, 16, 0))
 2280                       impl.setDefaultValue(readXmlValueObject());
 2281                   impl.setNillable((particleFlags & FLAG_PART_NILLABLE) != 0);
 2282                   impl.setBlock((particleFlags & FLAG_PART_BLOCKEXT) != 0,
 2283                       (particleFlags & FLAG_PART_BLOCKREST) != 0,
 2284                       (particleFlags & FLAG_PART_BLOCKSUBST) != 0);
 2285                   impl.setWsdlArrayType(readSOAPArrayType());
 2286                   impl.setAbstract((particleFlags & FLAG_PART_ABSTRACT) != 0);
 2287                   impl.setAnnotation(readAnnotation(container));
 2288                   impl.setFinal(
 2289