blob: 2c5ea0272442f526d7b21cd906e1c78327607d61 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.schema;
import org.apache.xmlbeans.Filer;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.SchemaAnnotation;
import org.apache.xmlbeans.SchemaAttributeGroup;
import org.apache.xmlbeans.SchemaAttributeModel;
import org.apache.xmlbeans.SchemaComponent;
import org.apache.xmlbeans.SchemaGlobalAttribute;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaIdentityConstraint;
import org.apache.xmlbeans.SchemaLocalAttribute;
import org.apache.xmlbeans.SchemaLocalElement;
import org.apache.xmlbeans.SchemaModelGroup;
import org.apache.xmlbeans.SchemaParticle;
import org.apache.xmlbeans.SchemaProperty;
import org.apache.xmlbeans.SchemaStringEnumEntry;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.SchemaTypeLoaderException;
import org.apache.xmlbeans.SchemaTypeSystem;
import org.apache.xmlbeans.SimpleValue;
import org.apache.xmlbeans.SystemProperties;
import org.apache.xmlbeans.XmlAnySimpleType;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.ResourceLoader;
import org.apache.xmlbeans.impl.common.DefaultClassLoaderResourceLoader;
import org.apache.xmlbeans.impl.common.NameUtil;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.common.XBeanDebug;
import org.apache.xmlbeans.impl.util.FilerImpl;
import org.apache.xmlbeans.impl.util.HexBin;
import org.apache.xmlbeans.impl.values.XmlObjectBase;
import org.apache.xmlbeans.impl.xb.xsdschema.AttributeGroupDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.GroupDocument;
import org.apache.xmlbeans.soap.SOAPArrayType;
import org.apache.xmlbeans.soap.SchemaWSDLArrayType;
import org.apache.xmlbeans.impl.repackage.Repackager;
import javax.xml.namespace.QName;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class SchemaTypeSystemImpl extends SchemaTypeLoaderBase implements SchemaTypeSystem
{
public static final int DATA_BABE = 0xDA7ABABE;
public static final int MAJOR_VERSION = 2; // must match == to be compatible
public static final int MINOR_VERSION = 24; // must be <= to be compatible
public static final int RELEASE_NUMBER = 0; // should be compatible even if < or >
public static final int FILETYPE_SCHEMAINDEX = 1;
public static final int FILETYPE_SCHEMATYPE = 2;
public static final int FILETYPE_SCHEMAELEMENT = 3;
public static final int FILETYPE_SCHEMAATTRIBUTE = 4;
public static final int FILETYPE_SCHEMAPOINTER = 5;
public static final int FILETYPE_SCHEMAMODELGROUP = 6;
public static final int FILETYPE_SCHEMAATTRIBUTEGROUP = 7;
public static final int FILETYPE_SCHEMAIDENTITYCONSTRAINT = 8;
public static final int FLAG_PART_SKIPPABLE = 1;
public static final int FLAG_PART_FIXED = 4;
public static final int FLAG_PART_NILLABLE = 8;
public static final int FLAG_PART_BLOCKEXT = 16;
public static final int FLAG_PART_BLOCKREST = 32;
public static final int FLAG_PART_BLOCKSUBST = 64;
public static final int FLAG_PART_ABSTRACT = 128;
public static final int FLAG_PART_FINALEXT = 256;
public static final int FLAG_PART_FINALREST = 512;
public static final int FLAG_PROP_ISATTR = 1;
public static final int FLAG_PROP_JAVASINGLETON = 2;
public static final int FLAG_PROP_JAVAOPTIONAL = 4;
public static final int FLAG_PROP_JAVAARRAY = 8;
public static final int FIELD_NONE = 0;
public static final int FIELD_GLOBAL = 1;
public static final int FIELD_LOCALATTR = 2;
public static final int FIELD_LOCALELT = 3;
// type flags
static final int FLAG_SIMPLE_TYPE = 0x1;
static final int FLAG_DOCUMENT_TYPE = 0x2;
static final int FLAG_ORDERED = 0x4;
static final int FLAG_BOUNDED = 0x8;
static final int FLAG_FINITE = 0x10;
static final int FLAG_NUMERIC = 0x20;
static final int FLAG_STRINGENUM = 0x40;
static final int FLAG_UNION_OF_LISTS = 0x80;
static final int FLAG_HAS_PATTERN = 0x100;
static final int FLAG_ORDER_SENSITIVE = 0x200;
static final int FLAG_TOTAL_ORDER = 0x400;
static final int FLAG_COMPILED = 0x800;
static final int FLAG_BLOCK_EXT = 0x1000;
static final int FLAG_BLOCK_REST = 0x2000;
static final int FLAG_FINAL_EXT = 0x4000;
static final int FLAG_FINAL_REST = 0x8000;
static final int FLAG_FINAL_UNION = 0x10000;
static final int FLAG_FINAL_LIST = 0x20000;
static final int FLAG_ABSTRACT = 0x40000;
static final int FLAG_ATTRIBUTE_TYPE = 0x80000;
/**
* This is to support the feature of a separate/private XMLBeans
* distribution that will not colide with the public org apache
* xmlbeans one.
* METADATA_PACKAGE_GEN will be "" for the original and something like
* com_mycompany_private_xmlbeans for a private distribution of XMLBeans.
*
* There are two properties:
* METADATA_PACKAGE_GEN - used for generating metadata
* and METADATA_PACKAGE_LOAD - used for loading the metadata.
* Most of the time they have the same value, with one exception, during the
* repackage process scomp needs to load from old package and generate into
* a new package.
*/
public static String METADATA_PACKAGE_GEN;
static
{
// fix for maven classloader
Package stsPackage = SchemaTypeSystem.class.getPackage();
String stsPackageName = (stsPackage==null) ?
SchemaTypeSystem.class.getName().substring(0, SchemaTypeSystem.class.getName().lastIndexOf(".")) :
stsPackage.getName();
METADATA_PACKAGE_GEN = stsPackageName.replaceAll("\\.", "_");
}
private static String nameToPathString(String nameForSystem)
{
nameForSystem = nameForSystem.replace('.', '/');
if (!nameForSystem.endsWith("/") && nameForSystem.length() > 0)
nameForSystem = nameForSystem + "/";
return nameForSystem;
}
public SchemaTypeSystemImpl(Class indexclass)
{
String fullname = indexclass.getName();
_name = fullname.substring(0, fullname.lastIndexOf('.'));
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Loading type system " + _name, 1);
_basePackage = nameToPathString(_name);
_classloader = indexclass.getClassLoader();
_linker = SchemaTypeLoaderImpl.build(null, null, _classloader, getMetadataPath());
_resourceLoader = new ClassLoaderResourceLoader(_classloader);
try
{
initFromHeader();
}
catch (RuntimeException e)
{
XBeanDebug.logException(e);
throw e;
}
catch (Error e)
{
XBeanDebug.logException(e);
throw e;
}
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Finished loading type system " + _name, -1);
}
public static boolean fileContainsTypeSystem(File file, String name)
{
String indexname = nameToPathString(name) + "index.xsb";
if (file.isDirectory())
{
return (new File(file, indexname)).isFile();
}
else
{
ZipFile zipfile = null;
try
{
zipfile = new ZipFile(file);
ZipEntry entry = zipfile.getEntry(indexname);
return (entry != null && !entry.isDirectory());
}
catch (IOException e)
{
XBeanDebug.log("Problem loading SchemaTypeSystem, zipfilename " + file);
XBeanDebug.logException(e);
throw new SchemaTypeLoaderException(e.getMessage(), name, "index", SchemaTypeLoaderException.IO_EXCEPTION);
}
finally
{
if (zipfile != null)
try { zipfile.close(); } catch (IOException e) {}
}
}
}
public static SchemaTypeSystemImpl forName(String name, ClassLoader loader)
{
try
{
Class c = Class.forName(name + "." + SchemaTypeCodePrinter.INDEX_CLASSNAME, true, loader);
return (SchemaTypeSystemImpl)c.getField("typeSystem").get(null);
}
catch (Exception e)
{
return null;
}
}
public SchemaTypeSystemImpl(ResourceLoader resourceLoader, String name, SchemaTypeLoader linker)
{
_name = name;
_basePackage = nameToPathString(_name);
_linker = linker;
_resourceLoader = resourceLoader;
try
{
initFromHeader();
}
catch (RuntimeException e)
{
XBeanDebug.logException(e);
throw e;
}
catch (Error e)
{
XBeanDebug.logException(e);
throw e;
}
}
private void initFromHeader()
{
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Reading unresolved handles for type system " + _name, 0);
XsbReader reader = null;
try
{
// Read the index file, which starts with a header.
reader = new XsbReader("index", FILETYPE_SCHEMAINDEX);
// has a handle pool (count, handle/type, handle/type...)
_localHandles = new HandlePool();
reader.readHandlePool(_localHandles);
// then a qname map of global elements (count, qname/handle, qname/handle...)
_globalElements = reader.readQNameRefMap();
// qname map of global attributes
_globalAttributes = reader.readQNameRefMap();
// qname map of model groups
_modelGroups = reader.readQNameRefMap();
// qname map of attribute groups
_attributeGroups = reader.readQNameRefMap();
_identityConstraints = reader.readQNameRefMap();
// qname map of global types
_globalTypes = reader.readQNameRefMap();
// qname map of document types, by the qname of the contained element
_documentTypes = reader.readQNameRefMap();
// qname mape of attribute types, by the qname of the contained attribute
_attributeTypes = reader.readQNameRefMap();
// string map of all types, by fully qualified classname
_typeRefsByClassname = reader.readClassnameRefMap();
_namespaces = reader.readNamespaces();
// support for redefine, at the end of the file
List typeNames = new ArrayList();
List modelGroupNames = new ArrayList();
List attributeGroupNames = new ArrayList();
if (reader.atLeast(2, 15, 0))
{
_redefinedGlobalTypes = reader.readQNameRefMapAsList(typeNames);
_redefinedModelGroups = reader.readQNameRefMapAsList(modelGroupNames);
_redefinedAttributeGroups = reader.readQNameRefMapAsList(attributeGroupNames);
}
if (reader.atLeast(2, 19, 0))
{
_annotations = reader.readAnnotations();
}
buildContainers(typeNames, modelGroupNames, attributeGroupNames);
}
finally
{
if (reader != null)
reader.readEnd();
}
}
void saveIndex()
{
String handle = "index";
XsbReader saver = new XsbReader(handle);
saver.writeIndexData();
saver.writeRealHeader(handle, FILETYPE_SCHEMAINDEX);
saver.writeIndexData();
saver.writeEnd();
}
void savePointers()
{
savePointersForComponents(globalElements(), getMetadataPath() + "/element/");
savePointersForComponents(globalAttributes(), getMetadataPath() + "/attribute/");
savePointersForComponents(modelGroups(), getMetadataPath() + "/modelgroup/");
savePointersForComponents(attributeGroups(), getMetadataPath() + "/attributegroup/");
savePointersForComponents(globalTypes(), getMetadataPath() + "/type/");
savePointersForComponents(identityConstraints(), getMetadataPath() + "/identityconstraint/");
savePointersForNamespaces(_namespaces, getMetadataPath() + "/namespace/");
savePointersForClassnames(_typeRefsByClassname.keySet(), getMetadataPath() + "/javaname/");
savePointersForComponents(redefinedModelGroups(), getMetadataPath() + "/redefinedmodelgroup/");
savePointersForComponents(redefinedAttributeGroups(), getMetadataPath() + "/redefinedattributegroup/");
savePointersForComponents(redefinedGlobalTypes(), getMetadataPath() + "/redefinedtype/");
}
void savePointersForComponents(SchemaComponent[] components, String dir)
{
for (int i = 0; i < components.length; i++)
{
savePointerFile(dir + QNameHelper.hexsafedir(components[i].getName()), _name);
}
}
void savePointersForClassnames(Set classnames, String dir)
{
for (Iterator i = classnames.iterator(); i.hasNext(); )
{
String classname = (String)i.next();
savePointerFile(dir + classname.replace('.', '/'), _name);
}
}
void savePointersForNamespaces(Set namespaces, String dir)
{
for (Iterator i = namespaces.iterator(); i.hasNext(); )
{
String ns = (String)i.next();
savePointerFile(dir + QNameHelper.hexsafedir(new QName(ns, "xmlns")), _name);
}
}
void savePointerFile(String filename, String name)
{
XsbReader saver = new XsbReader(filename);
saver.writeString(name);
saver.writeRealHeader(filename, FILETYPE_SCHEMAPOINTER);
saver.writeString(name);
saver.writeEnd();
}
/**
* The strategy here is to copy the compiled TypeSystemHolder.template class
* to a new TypeSystemHolder.class needed by the schema type system. When
* saving a loader, we read the TypeSystemHolder.template class file and
* swap out the utf8 string constants with new ones to create a new
* TypeSystemHolder class file. This saves us the need to rely on javac
* to compile a generated .java file into the class file.
*
* See the JVM spec on how to interpret the bytes of a class file.
*/
void saveLoader()
{
String indexClassName = SchemaTypeCodePrinter.indexClassForSystem(this);
String[] replace = makeClassStrings(indexClassName);
assert replace.length == HOLDER_TEMPLATE_NAMES.length;
InputStream is = null;
OutputStream os = null;
DataInputStream in = null;
DataOutputStream out = null;
Repackager repackager = null;
if (_filer instanceof FilerImpl)
repackager = ((FilerImpl)_filer).getRepackager();
try
{
is = SchemaTypeSystemImpl.class.getResourceAsStream(HOLDER_TEMPLATE_CLASSFILE);
if (is == null) {
DefaultClassLoaderResourceLoader clLoader = new DefaultClassLoaderResourceLoader();
is = clLoader.getResourceAsStream(HOLDER_TEMPLATE_CLASSFILE);
}
if (is == null) {
throw new SchemaTypeLoaderException("couldn't find resource: " + HOLDER_TEMPLATE_CLASSFILE, _name, null, SchemaTypeLoaderException.IO_EXCEPTION);
}
in = new DataInputStream(is);
os = _filer.createBinaryFile(indexClassName.replace('.', '/') + ".class");
out = new DataOutputStream(os);
// java magic
out.writeInt(in.readInt());
// java minor and major version
out.writeShort(in.readUnsignedShort());
out.writeShort(in.readUnsignedShort());
int poolsize = in.readUnsignedShort();
out.writeShort(poolsize);
// the constant pool is indexed from 1 to poolsize-1
for (int i = 1; i < poolsize; i++)
{
int tag = in.readUnsignedByte();
out.writeByte(tag);
switch (tag)
{
case CONSTANT_UTF8:
String value = in.readUTF();
out.writeUTF(repackageConstant(value, replace, repackager));
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
out.writeShort(in.readUnsignedShort());
break;
case CONSTANT_NAMEANDTYPE:
case CONSTANT_METHOD:
case CONSTANT_FIELD:
case CONSTANT_INTERFACEMETHOD:
out.writeShort(in.readUnsignedShort());
out.writeShort(in.readUnsignedShort());
break;
case CONSTANT_INTEGER:
case CONSTANT_FLOAT:
out.writeInt(in.readInt());
break;
case CONSTANT_LONG:
case CONSTANT_DOUBLE:
out.writeInt(in.readInt());
out.writeInt(in.readInt());
break;
default:
throw new RuntimeException("Unexpected constant type: " + tag);
}
}
// we're done with the class' constant pool,
// we can just copy the rest of the bytes
try
{
while (true)
out.writeByte(in.readByte());
}
catch (java.io.EOFException e)
{
// ok
}
}
catch (IOException e)
{
// ok
}
finally
{
if (is != null) try { is.close(); } catch (Exception e) { }
if (os != null) try { os.close(); } catch (Exception e) { }
}
}
private static final String HOLDER_TEMPLATE_CLASS = "org.apache.xmlbeans.impl.schema.TypeSystemHolder";
private static final String HOLDER_TEMPLATE_CLASSFILE = "TypeSystemHolder.template";
private static final String[] HOLDER_TEMPLATE_NAMES = makeClassStrings(HOLDER_TEMPLATE_CLASS);
// constant pool entry types
private static final int CONSTANT_UTF8 = 1;
private static final int CONSTANT_UNICODE = 2;
private static final int CONSTANT_INTEGER = 3;
private static final int CONSTANT_FLOAT = 4;
private static final int CONSTANT_LONG = 5;
private static final int CONSTANT_DOUBLE = 6;
private static final int CONSTANT_CLASS = 7;
private static final int CONSTANT_STRING = 8;
private static final int CONSTANT_FIELD = 9;
private static final int CONSTANT_METHOD = 10;
private static final int CONSTANT_INTERFACEMETHOD = 11;
private static final int CONSTANT_NAMEANDTYPE = 12;
// MAX_UNSIGNED_SHORT
private static final int MAX_UNSIGNED_SHORT = Short.MAX_VALUE * 2 + 1;
private static String repackageConstant(String value, String[] replace, Repackager repackager)
{
for (int i = 0; i < HOLDER_TEMPLATE_NAMES.length; i++)
if (HOLDER_TEMPLATE_NAMES[i].equals(value))
return replace[i];
if (repackager != null)
return repackager.repackage(new StringBuffer(value)).toString();
return value;
}
/**
* Construct an array of Strings found in a class file for a classname.
* For the class name 'a.b.C' it will generate an array of:
* 'a.b.C', 'a/b/C', 'La/b/C;', and 'class$a$b$C'.
*/
private static String[] makeClassStrings(String classname)
{
String[] result = new String[4];
result[0] = classname;
result[1] = classname.replace('.', '/');
result[2] = "L" + result[1] + ";";
result[3] = "class$" + classname.replace('.', '$');
return result;
}
/**
* Only used in the nonbootstrapped case.
*/
private Map buildTypeRefsByClassname()
{
List allSeenTypes = new ArrayList();
Map result = new LinkedHashMap();
allSeenTypes.addAll(Arrays.asList(documentTypes()));
allSeenTypes.addAll(Arrays.asList(attributeTypes()));
allSeenTypes.addAll(Arrays.asList(globalTypes()));
// now fully javaize everything deeply.
for (int i = 0; i < allSeenTypes.size(); i++)
{
SchemaType gType = (SchemaType)allSeenTypes.get(i);
String className = gType.getFullJavaName();
if (className != null)
{
result.put(className.replace('$', '.'), gType.getRef());
}
allSeenTypes.addAll(Arrays.asList(gType.getAnonymousTypes()));
}
return result;
}
private Map buildTypeRefsByClassname(Map typesByClassname)
{
Map result = new LinkedHashMap();
for (Iterator i = typesByClassname.keySet().iterator(); i.hasNext(); )
{
String className = (String)i.next();
result.put(className, ((SchemaType)typesByClassname.get(className)).getRef());
}
return result;
}
private static Map buildComponentRefMap(SchemaComponent[] components)
{
Map result = new LinkedHashMap();
for (int i = 0; i < components.length; i++)
result.put(components[i].getName(), components[i].getComponentRef());
return result;
}
private static List buildComponentRefList(SchemaComponent[] components)
{
List result = new ArrayList();
for (int i = 0; i < components.length; i++)
result.add(components[i].getComponentRef());
return result;
}
private static Map buildDocumentMap(SchemaType[] types)
{
Map result = new LinkedHashMap();
for (int i = 0; i < types.length; i++)
result.put(types[i].getDocumentElementName(), types[i].getRef());
return result;
}
private static Map buildAttributeTypeMap(SchemaType[] types)
{
Map result = new LinkedHashMap();
for (int i = 0; i < types.length; i++)
result.put(types[i].getAttributeTypeAttributeName(), types[i].getRef());
return result;
}
// Container operation
private SchemaContainer getContainer(String namespace)
{
return (SchemaContainer) _containers.get(namespace);
}
private void addContainer(String namespace)
{
SchemaContainer c = new SchemaContainer(namespace);
c.setTypeSystem(this);
_containers.put(namespace, c);
}
private SchemaContainer getContainerNonNull(String namespace)
{
SchemaContainer result = getContainer(namespace);
if (result == null)
{
addContainer(namespace);
result = getContainer(namespace);
}
return result;
}
// Only called during init
private void buildContainers(List redefTypeNames, List redefModelGroupNames, List redefAttributeGroupNames)
{
// This method walks the reference maps and copies said references
// into the appropriate container
for (Iterator it = _globalElements.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addGlobalElement((SchemaGlobalElement.Ref) entry.getValue());
}
for (Iterator it = _globalAttributes.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addGlobalAttribute((SchemaGlobalAttribute.Ref) entry.getValue());
}
for (Iterator it = _modelGroups.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addModelGroup((SchemaModelGroup.Ref) entry.getValue());
}
for (Iterator it = _attributeGroups.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addAttributeGroup((SchemaAttributeGroup.Ref) entry.getValue());
}
for (Iterator it = _identityConstraints.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addIdentityConstraint((SchemaIdentityConstraint.Ref) entry.getValue());
}
for (Iterator it = _globalTypes.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addGlobalType((SchemaType.Ref) entry.getValue());
}
for (Iterator it = _documentTypes.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addDocumentType((SchemaType.Ref) entry.getValue());
}
for (Iterator it = _attributeTypes.entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = (Map.Entry) it.next();
String ns = ((QName) entry.getKey()).getNamespaceURI();
getContainerNonNull(ns).addAttributeType((SchemaType.Ref) entry.getValue());
}
// Some earlier .xsb versions don't have records for redefinitions
if (_redefinedGlobalTypes != null && _redefinedModelGroups != null &&
_redefinedAttributeGroups != null)
{
assert _redefinedGlobalTypes.size() == redefTypeNames.size();
for (Iterator it = _redefinedGlobalTypes.iterator(), itname = redefTypeNames.iterator(); it.hasNext(); )
{
String ns = ((QName) itname.next()).getNamespaceURI();
getContainerNonNull(ns).addRedefinedType((SchemaType.Ref) it.next());
}
for (Iterator it = _redefinedModelGroups.iterator(), itname = redefModelGroupNames.iterator(); it.hasNext(); )
{
String ns = ((QName) itname.next()).getNamespaceURI();
getContainerNonNull(ns).addRedefinedModelGroup((SchemaModelGroup.Ref) it.next());
}
for (Iterator it = _redefinedAttributeGroups.iterator(), itname = redefAttributeGroupNames.iterator(); it.hasNext(); )
{
String ns = ((QName) itname.next()).getNamespaceURI();
getContainerNonNull(ns).addRedefinedAttributeGroup((SchemaAttributeGroup.Ref) it.next());
}
}
// Some earlier .xsb versions don't have records for annotations
if (_annotations != null)
{
for (Iterator it = _annotations.iterator(); it.hasNext(); )
{
SchemaAnnotation ann = (SchemaAnnotation) it.next();
// BUGBUG(radup)
getContainerNonNull("").addAnnotation(ann);
}
}
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
((SchemaContainer) it.next()).setImmutable();
}
/**
* This is the crux of the container work and role.
* It makes a sweep over all containers and fixes each container's
* typesystem to point to this typesystem.
* Because SchemaComponents have a link to their containers, this has as
* effect all components now indirectly pointing to this typesystem
* even though they (as well as the typesystem itself) are immutable.
*/
private void fixupContainers()
{
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
{
SchemaContainer container = (SchemaContainer) it.next();
container.setTypeSystem(this);
container.setImmutable();
}
}
private void assertContainersSynchronized()
{
boolean assertEnabled = false;
// This code basically checks whether asserts are enabled so we don't do
// all the work if they arent
assert assertEnabled = true;
if (!assertEnabled)
return;
// global elements
Map temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).globalElements().toArray(new SchemaComponent[0])));
assert _globalElements.equals(temp);
// global attributes
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).globalAttributes().toArray(new SchemaComponent[0])));
assert _globalAttributes.equals(temp);
// model groups
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).modelGroups().toArray(new SchemaComponent[0])));
assert _modelGroups.equals(temp);
// redefined model groups
Set temp2 = new HashSet();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp2.addAll(buildComponentRefList((SchemaComponent[]) ((SchemaContainer) it.next()).redefinedModelGroups().toArray(new SchemaComponent[0])));
assert new HashSet(_redefinedModelGroups).equals(temp2);
// attribute groups
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).attributeGroups().toArray(new SchemaComponent[0])));
assert _attributeGroups.equals(temp);
// redefined attribute groups
temp2 = new HashSet();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp2.addAll(buildComponentRefList((SchemaComponent[]) ((SchemaContainer) it.next()).redefinedAttributeGroups().toArray(new SchemaComponent[0])));
assert new HashSet(_redefinedAttributeGroups).equals(temp2);
// global types
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).globalTypes().toArray(new SchemaComponent[0])));
assert _globalTypes.equals(temp);
// redefined global types
temp2 = new HashSet();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp2.addAll(buildComponentRefList((SchemaComponent[]) ((SchemaContainer) it.next()).redefinedGlobalTypes().toArray(new SchemaComponent[0])));
assert new HashSet(_redefinedGlobalTypes).equals(temp2);
// document types
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildDocumentMap((SchemaType[]) ((SchemaContainer) it.next()).documentTypes().toArray(new SchemaType[0])));
assert _documentTypes.equals(temp);
// attribute types
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildAttributeTypeMap((SchemaType[]) ((SchemaContainer) it.next()).attributeTypes().toArray(new SchemaType[0])));
assert _attributeTypes.equals(temp);
// identity constraints
temp = new HashMap();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp.putAll(buildComponentRefMap((SchemaComponent[]) ((SchemaContainer) it.next()).identityConstraints().toArray(new SchemaComponent[0])));
assert _identityConstraints.equals(temp);
// annotations
temp2 = new HashSet();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp2.addAll(((SchemaContainer) it.next()).annotations());
assert new HashSet(_annotations).equals(temp2);
// namespaces
temp2 = new HashSet();
for (Iterator it = _containers.values().iterator(); it.hasNext(); )
temp2.add(((SchemaContainer) it.next()).getNamespace());
assert _namespaces.equals(temp2);
}
private static Random _random;
private static byte[] _mask = new byte[128 / 8];
/**
* Fun, fun. Produce 128 bits of uniqueness randomly.
* We used to use SecureRandom, but now we don't because SecureRandom
* hits the filesystem and hangs us on a filesystem lock. It also eats
* a thread and other expensive resources.. :-).
*
* We don't really care that non-secure Random() can only do 48 bits of
* randomness, since we're certainly not going to be called more than 2^48
* times within our process lifetime.
*
* Our real concern is that by seeding Random() with the current
* time, two users will end up with the same bits if they start a
* schema compilation within the same millisecond. That makes the
* probability of collision in the real world slightly too high.
* We're going to have millions of users, remember? With a million
* users, and one-compilation-per-day each, we'd see a collision every
* few months.
*
* So we'll just xor the results of random with our few extra
* bits of information computed below to help reduce the probability
* of collision by a few decimal places. To collide, you will have had
* to have the same amount of free memory, the same user name, timezone,
* and country, the same current directory, the same java classpath,
* the same operating system and jvm version, and the same choices of
* identity hashcodes for a few objects. And be started within the same
* millisecond. Or you can collide if you have a cosmic 128-bit mathematical
* coincidence. No worries.
*/
private static synchronized void nextBytes(byte[] result)
{
if (_random == null)
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream daos = new DataOutputStream(baos);
// at least 10 bits of unqieueness, right? Maybe even 50 or 60.
daos.writeInt(System.identityHashCode(SchemaTypeSystemImpl.class));
String[] props = new String[] { "user.name", "user.dir", "user.timezone", "user.country", "java.class.path", "java.home", "java.vendor", "java.version", "os.version" };
for (int i = 0; i < props.length; i++)
{
String prop = SystemProperties.getProperty(props[i]);
if (prop != null)
{
daos.writeUTF(prop);
daos.writeInt(System.identityHashCode(prop));
}
}
daos.writeLong(Runtime.getRuntime().freeMemory());
daos.close();
byte[] bytes = baos.toByteArray();
for (int i = 0; i < bytes.length; i++)
{
int j = i % _mask.length;
_mask[j] *= 21;
_mask[j] += i;
}
}
catch (IOException e)
{
XBeanDebug.logException(e);
}
_random = new Random(System.currentTimeMillis());
}
_random.nextBytes(result);
for (int i = 0; i < result.length; i++)
{
int j = i & _mask.length;
result[i] ^= _mask[j];
}
}
public SchemaTypeSystemImpl(String nameForSystem)
{
// if we have no name, select a random one
if (nameForSystem == null)
{
// get 128 random bits (that'll be 32 hex digits)
byte[] bytes = new byte[128/8];
nextBytes(bytes);
nameForSystem = "s" + new String(HexBin.encode(bytes));
}
_name = getMetadataPath().replace('/','.') + ".system." + nameForSystem;
_basePackage = nameToPathString(_name);
_classloader = null;
//System.out.println(" _base: " + _basePackage);
}
public void loadFromBuilder(SchemaGlobalElement[] globalElements,
SchemaGlobalAttribute[] globalAttributes,
SchemaType[] globalTypes,
SchemaType[] documentTypes,
SchemaType[] attributeTypes)
{
assert(_classloader == null);
_localHandles = new HandlePool();
_globalElements = buildComponentRefMap(globalElements);
_globalAttributes = buildComponentRefMap(globalAttributes);
_globalTypes = buildComponentRefMap(globalTypes);
_documentTypes = buildDocumentMap(documentTypes);
_attributeTypes = buildAttributeTypeMap(attributeTypes);
_typeRefsByClassname = buildTypeRefsByClassname();
buildContainers(Collections.EMPTY_LIST, Collections.EMPTY_LIST,
Collections.EMPTY_LIST);
_namespaces = new HashSet();
}
public void loadFromStscState(StscState state)
{
assert(_classloader == null);
_localHandles = new HandlePool();
_globalElements = buildComponentRefMap(state.globalElements());
_globalAttributes = buildComponentRefMap(state.globalAttributes());
_modelGroups = buildComponentRefMap(state.modelGroups());
_redefinedModelGroups = buildComponentRefList(state.redefinedModelGroups());
_attributeGroups = buildComponentRefMap(state.attributeGroups());
_redefinedAttributeGroups = buildComponentRefList(state.redefinedAttributeGroups());
_globalTypes = buildComponentRefMap(state.globalTypes());
_redefinedGlobalTypes = buildComponentRefList(state.redefinedGlobalTypes());
_documentTypes = buildDocumentMap(state.documentTypes());
_attributeTypes = buildAttributeTypeMap(state.attributeTypes());
_typeRefsByClassname = buildTypeRefsByClassname(state.typesByClassname());
_identityConstraints = buildComponentRefMap(state.idConstraints());
_annotations = state.annotations();
_namespaces = new HashSet(Arrays.asList(state.getNamespaces()));
_containers = state.getContainerMap();
fixupContainers();
// Checks that data in the containers matches the lookup maps
assertContainersSynchronized();
setDependencies(state.getDependencies());
}
final SchemaTypeSystemImpl getTypeSystem()
{
return this;
}
void setDependencies(SchemaDependencies deps)
{ _deps = deps; }
SchemaDependencies getDependencies()
{ return _deps; }
// EXPERIMENTAL
public boolean isIncomplete() { return _incomplete; }
// EXPERIMENTAL
void setIncomplete(boolean incomplete) { _incomplete = incomplete; }
static class StringPool
{
private List intsToStrings = new ArrayList();
private Map stringsToInts = new HashMap();
private String _handle;
private String _name;
/**
* Constructs an empty StringPool to be filled with strings.
*/
StringPool(String handle, String name)
{
_handle = handle;
_name = name;
intsToStrings.add(null);
}
int codeForString(String str)
{
if (str == null)
return 0;
Integer result = (Integer)stringsToInts.get(str);
if (result == null)
{
result = new Integer(intsToStrings.size());
intsToStrings.add(str);
stringsToInts.put(str, result);
}
return result.intValue();
}
String stringForCode(int code)
{
if (code == 0)
return null;
return (String)intsToStrings.get(code);
}
void writeTo(DataOutputStream output)
{
if (intsToStrings.size() >= MAX_UNSIGNED_SHORT)
throw new SchemaTypeLoaderException("Too many strings (" + intsToStrings.size() + ")", _name, _handle, SchemaTypeLoaderException.INT_TOO_LARGE);
try
{
output.writeShort(intsToStrings.size());
Iterator i = intsToStrings.iterator();
for (i.next(); i.hasNext(); )
{
String str = (String)i.next();
output.writeUTF(str);
}
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
void readFrom(DataInputStream input)
{
if (intsToStrings.size() != 1 || stringsToInts.size() != 0)
throw new IllegalStateException();
try
{
int size = input.readUnsignedShort();
for (int i = 1; i < size; i++)
{
String str = input.readUTF().intern();
int code = codeForString(str);
if (code != i)
throw new IllegalStateException();
}
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage() == null ? e.getMessage() : "IO Exception", _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION, e);
}
}
}
class HandlePool
{
private Map _handlesToRefs = new LinkedHashMap();
private Map _componentsToHandles = new LinkedHashMap(); // populated on write
private boolean _started;
/**
* Constructs an empty HandlePool to be populated.
*/
HandlePool()
{
}
private String addUniqueHandle(SchemaComponent obj, String base)
{
base = base.toLowerCase(); // we lowercase handles because of case-insensitive Windows filenames!!!
String handle = base;
for (int index = 2; _handlesToRefs.containsKey(handle); index++)
{
handle = base + index;
}
_handlesToRefs.put(handle, obj.getComponentRef());
_componentsToHandles.put(obj, handle);
return handle;
}
String handleForComponent(SchemaComponent comp)
{
if (comp == null)
return null;
if (comp.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
if (comp instanceof SchemaType)
return handleForType((SchemaType)comp);
if (comp instanceof SchemaGlobalElement)
return handleForElement((SchemaGlobalElement)comp);
if (comp instanceof SchemaGlobalAttribute)
return handleForAttribute((SchemaGlobalAttribute)comp);
if (comp instanceof SchemaModelGroup)
return handleForModelGroup((SchemaModelGroup)comp);
if (comp instanceof SchemaAttributeGroup)
return handleForAttributeGroup((SchemaAttributeGroup)comp);
if (comp instanceof SchemaIdentityConstraint)
return handleForIdentityConstraint((SchemaIdentityConstraint)comp);
throw new IllegalStateException("Component type cannot have a handle");
}
String handleForElement(SchemaGlobalElement element)
{
if (element == null)
return null;
if (element.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
String handle = (String)_componentsToHandles.get(element);
if (handle == null)
handle = addUniqueHandle(element, NameUtil.upperCamelCase(element.getName().getLocalPart()) + "Element");
return handle;
}
String handleForAttribute(SchemaGlobalAttribute attribute)
{
if (attribute == null)
return null;
if (attribute.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
String handle = (String)_componentsToHandles.get(attribute);
if (handle == null)
handle = addUniqueHandle(attribute, NameUtil.upperCamelCase(attribute.getName().getLocalPart()) + "Attribute");
return handle;
}
String handleForModelGroup(SchemaModelGroup group)
{
if (group == null)
return null;
if (group.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
String handle = (String)_componentsToHandles.get(group);
if (handle == null)
handle = addUniqueHandle(group, NameUtil.upperCamelCase(group.getName().getLocalPart()) + "ModelGroup");
return handle;
}
String handleForAttributeGroup(SchemaAttributeGroup group)
{
if (group == null)
return null;
if (group.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
String handle = (String)_componentsToHandles.get(group);
if (handle == null)
handle = addUniqueHandle(group, NameUtil.upperCamelCase(group.getName().getLocalPart()) + "AttributeGroup");
return handle;
}
String handleForIdentityConstraint(SchemaIdentityConstraint idc)
{
if (idc == null)
return null;
if (idc.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
String handle = (String)_componentsToHandles.get(idc);
if (handle == null)
handle = addUniqueHandle(idc, NameUtil.upperCamelCase(idc.getName().getLocalPart()) + "IdentityConstraint");
return handle;
}
String handleForType(SchemaType type)
{
if (type == null)
return null;
if (type.getTypeSystem() != getTypeSystem())
throw new IllegalArgumentException("Cannot supply handles for types from another type system");
String handle = (String)_componentsToHandles.get(type);
if (handle == null)
{
QName name = type.getName();
String suffix = "";
if (name == null)
{
if (type.isDocumentType())
{
name = type.getDocumentElementName();
suffix = "Doc";
}
else if (type.isAttributeType())
{
name = type.getAttributeTypeAttributeName();
suffix = "AttrType";
}
else if (type.getContainerField() != null)
{
name = type.getContainerField().getName();
suffix = type.getContainerField().isAttribute() ? "Attr" : "Elem";
}
}
String baseName;
String uniq = Integer.toHexString(type.toString().hashCode() | 0x80000000).substring(4).toUpperCase();
if (name == null)
baseName = "Anon" + uniq + "Type";
else
baseName = NameUtil.upperCamelCase(name.getLocalPart()) + uniq + suffix + "Type";
handle = addUniqueHandle(type, baseName);
}
return handle;
}
SchemaComponent.Ref refForHandle(String handle)
{
if (handle == null)
return null;
return (SchemaComponent.Ref)_handlesToRefs.get(handle);
}
Set getAllHandles()
{
return _handlesToRefs.keySet();
}
void startWriteMode()
{
_started = true;
_componentsToHandles = new LinkedHashMap();
for (Iterator i = _handlesToRefs.keySet().iterator(); i.hasNext(); )
{
String handle = (String)i.next();
// System.err.println("Writing preexisting handle " + handle);
SchemaComponent comp = ((SchemaComponent.Ref)_handlesToRefs.get(handle)).getComponent();
_componentsToHandles.put(comp, handle);
}
}
}
private String _name;
private String _basePackage;
// EXPERIMENTAL: recovery from compilation errors and partial type systems
private boolean _incomplete = false;
// classloader is available for sts's that were compiled and loaded, not dynamic ones
private ClassLoader _classloader;
// the loader for loading .xsb resources
private ResourceLoader _resourceLoader;
// the following is used to link references during load
SchemaTypeLoader _linker;
private HandlePool _localHandles;
private Filer _filer;
// top-level annotations
private List _annotations;
// container
private Map _containers = new HashMap();
// dependencies
private SchemaDependencies _deps;
private List _redefinedModelGroups;
private List _redefinedAttributeGroups;
private List _redefinedGlobalTypes;
// actual type system data, map QNames -> SchemaComponent.Ref
private Map _globalElements;
private Map _globalAttributes;
private Map _modelGroups;
private Map _attributeGroups;
private Map _globalTypes;
private Map _documentTypes;
private Map _attributeTypes;
private Map _identityConstraints = Collections.EMPTY_MAP;
private Map _typeRefsByClassname = new HashMap();
private Set _namespaces;
static private final SchemaType[] EMPTY_ST_ARRAY = new SchemaType[0];
static private final SchemaGlobalElement[] EMPTY_GE_ARRAY = new SchemaGlobalElement[0];
static private final SchemaGlobalAttribute[] EMPTY_GA_ARRAY = new SchemaGlobalAttribute[0];
static private final SchemaModelGroup[] EMPTY_MG_ARRAY = new SchemaModelGroup[0];
static private final SchemaAttributeGroup[] EMPTY_AG_ARRAY = new SchemaAttributeGroup[0];
static private final SchemaIdentityConstraint[] EMPTY_IC_ARRAY = new SchemaIdentityConstraint[0];
static private final SchemaAnnotation[] EMPTY_ANN_ARRAY = new SchemaAnnotation[0];
public void saveToDirectory(File classDir)
{
save(new FilerImpl(classDir, null, null, false, false));
}
public void save(Filer filer)
{
if (_incomplete)
throw new IllegalStateException("Incomplete SchemaTypeSystems cannot be saved.");
if (filer == null)
throw new IllegalArgumentException("filer must not be null");
_filer = filer;
_localHandles.startWriteMode();
saveTypesRecursively(globalTypes());
saveTypesRecursively(documentTypes());
saveTypesRecursively(attributeTypes());
saveGlobalElements(globalElements());
saveGlobalAttributes(globalAttributes());
saveModelGroups(modelGroups());
saveAttributeGroups(attributeGroups());
saveIdentityConstraints(identityConstraints());
saveTypesRecursively(redefinedGlobalTypes());
saveModelGroups(redefinedModelGroups());
saveAttributeGroups(redefinedAttributeGroups());
saveIndex();
savePointers();
saveLoader();
}
void saveTypesRecursively(SchemaType[] types)
{
for (int i = 0; i < types.length; i++)
{
if (types[i].getTypeSystem() != getTypeSystem())
continue;
saveType(types[i]);
saveTypesRecursively(types[i].getAnonymousTypes());
}
}
public void saveGlobalElements(SchemaGlobalElement[] elts)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
for (int i = 0; i < elts.length; i++)
{
saveGlobalElement(elts[i]);
}
}
public void saveGlobalAttributes(SchemaGlobalAttribute[] attrs)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
for (int i = 0; i < attrs.length; i++)
{
saveGlobalAttribute(attrs[i]);
}
}
public void saveModelGroups(SchemaModelGroup[] groups)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
for (int i = 0; i < groups.length; i++)
{
saveModelGroup(groups[i]);
}
}
public void saveAttributeGroups(SchemaAttributeGroup[] groups)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
for (int i = 0; i < groups.length; i++)
{
saveAttributeGroup(groups[i]);
}
}
public void saveIdentityConstraints(SchemaIdentityConstraint[] idcs)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
for (int i = 0; i < idcs.length; i++)
{
saveIdentityConstraint(idcs[i]);
}
}
public void saveGlobalElement(SchemaGlobalElement elt)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
String handle = _localHandles.handleForElement(elt);
XsbReader saver = new XsbReader(handle);
saver.writeParticleData((SchemaParticle)elt);
saver.writeString(elt.getSourceName());
saver.writeRealHeader(handle, FILETYPE_SCHEMAELEMENT);
saver.writeParticleData((SchemaParticle)elt);
saver.writeString(elt.getSourceName());
saver.writeEnd();
}
public void saveGlobalAttribute(SchemaGlobalAttribute attr)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
String handle = _localHandles.handleForAttribute(attr);
XsbReader saver = new XsbReader(handle);
saver.writeAttributeData(attr);
saver.writeString(attr.getSourceName());
saver.writeRealHeader(handle, FILETYPE_SCHEMAATTRIBUTE);
saver.writeAttributeData(attr);
saver.writeString(attr.getSourceName());
saver.writeEnd();
}
public void saveModelGroup(SchemaModelGroup grp)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
String handle = _localHandles.handleForModelGroup(grp);
XsbReader saver = new XsbReader(handle);
saver.writeModelGroupData(grp);
saver.writeRealHeader(handle, FILETYPE_SCHEMAMODELGROUP);
saver.writeModelGroupData(grp);
saver.writeEnd();
}
public void saveAttributeGroup(SchemaAttributeGroup grp)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
String handle = _localHandles.handleForAttributeGroup(grp);
XsbReader saver = new XsbReader(handle);
saver.writeAttributeGroupData(grp);
saver.writeRealHeader(handle, FILETYPE_SCHEMAATTRIBUTEGROUP);
saver.writeAttributeGroupData(grp);
saver.writeEnd();
}
public void saveIdentityConstraint(SchemaIdentityConstraint idc)
{
if (_incomplete)
throw new IllegalStateException("This SchemaTypeSystem cannot be saved.");
String handle = _localHandles.handleForIdentityConstraint(idc);
XsbReader saver = new XsbReader(handle);
saver.writeIdConstraintData(idc);
saver.writeRealHeader(handle, FILETYPE_SCHEMAIDENTITYCONSTRAINT);
saver.writeIdConstraintData(idc);
saver.writeEnd();
}
void saveType(SchemaType type)
{
String handle = _localHandles.handleForType(type);
XsbReader saver = new XsbReader(handle);
saver.writeTypeData(type);
saver.writeRealHeader(handle, FILETYPE_SCHEMATYPE);
saver.writeTypeData(type);
saver.writeEnd();
}
public static String crackPointer(InputStream stream)
{
DataInputStream input = null;
try
{
input = new DataInputStream(stream);
int magic = input.readInt();
if (magic != DATA_BABE)
return null;
int majorver = input.readShort();
int minorver = input.readShort();
if (majorver != MAJOR_VERSION)
return null;
if (minorver > MINOR_VERSION)
return null;
if (majorver > 2 || majorver == 2 && minorver >= 18)
input.readShort(); // release number present in atLeast(2, 18, 0)
int actualfiletype = input.readShort();
if (actualfiletype != FILETYPE_SCHEMAPOINTER)
return null;
StringPool stringPool = new StringPool("pointer", "unk");
stringPool.readFrom(input);
return stringPool.stringForCode(input.readShort());
}
catch (IOException e)
{
return null;
}
finally
{
if (input != null)
try { input.close(); } catch (IOException e) {}
}
}
private class XsbReader
{
DataInputStream _input;
DataOutputStream _output;
StringPool _stringPool;
String _handle;
private int _majorver;
private int _minorver;
private int _releaseno;
int _actualfiletype;
public XsbReader(String handle, int filetype)
{
String resourcename = _basePackage + handle + ".xsb";
InputStream rawinput = getLoaderStream(resourcename);
if (rawinput == null)
throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Could not locate compiled schema resource " + resourcename, _name, handle, SchemaTypeLoaderException.NO_RESOURCE);
_input = new DataInputStream(rawinput);
_handle = handle;
int magic = readInt();
if (magic != DATA_BABE)
throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Wrong magic cookie", _name, handle, SchemaTypeLoaderException.WRONG_MAGIC_COOKIE);
_majorver = readShort();
_minorver = readShort();
if (_majorver != MAJOR_VERSION)
throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Wrong major version - expecting " + MAJOR_VERSION + ", got " + _majorver, _name, handle, SchemaTypeLoaderException.WRONG_MAJOR_VERSION);
if (_minorver > MINOR_VERSION)
throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Incompatible minor version - expecting up to " + MINOR_VERSION + ", got " + _minorver, _name, handle, SchemaTypeLoaderException.WRONG_MINOR_VERSION);
// Clip to 14 because we're not backward compatible with earlier
// minor versions. Remove this when upgrading to a new major
// version
if (_minorver < 14)
throw new SchemaTypeLoaderException("XML-BEANS compiled schema: Incompatible minor version - expecting at least 14, got " + _minorver, _name, handle, SchemaTypeLoaderException.WRONG_MINOR_VERSION);
if (atLeast(2, 18, 0))
_releaseno = readShort();
int actualfiletype = readShort();
if (actualfiletype != filetype && filetype != 0xFFFF)
throw new SchemaTypeLoaderException("XML-BEANS compiled schema: File has the wrong type - expecting type " + filetype + ", got type " + actualfiletype, _name, handle, SchemaTypeLoaderException.WRONG_FILE_TYPE);
_stringPool = new StringPool(_handle, _name);
_stringPool.readFrom(_input);
_actualfiletype = actualfiletype;
}
protected boolean atLeast(int majorver, int minorver, int releaseno)
{
if (_majorver > majorver)
return true;
if (_majorver < majorver)
return false;
if (_minorver > minorver)
return true;
if (_minorver < minorver)
return false;
return (_releaseno >= releaseno);
}
protected boolean atMost(int majorver, int minorver, int releaseno)
{
if (_majorver > majorver)
return false;
if (_majorver < majorver)
return true;
if (_minorver > minorver)
return false;
if (_minorver < minorver)
return true;
return (_releaseno <= releaseno);
}
int getActualFiletype()
{
return _actualfiletype;
}
XsbReader(String handle)
{
_handle = handle;
_stringPool = new StringPool(_handle, _name);
}
void writeRealHeader(String handle, int filetype)
{
// hackeroo: if handle contains a "/" it's not relative.
String resourcename;
if (handle.indexOf('/') >= 0)
resourcename = handle + ".xsb";
else
resourcename = _basePackage + handle + ".xsb";
OutputStream rawoutput = getSaverStream(resourcename);
if (rawoutput == null)
throw new SchemaTypeLoaderException("Could not write compiled schema resource " + resourcename, _name, handle, SchemaTypeLoaderException.NOT_WRITEABLE);
_output = new DataOutputStream(rawoutput);
_handle = handle;
writeInt(DATA_BABE);
writeShort(MAJOR_VERSION);
writeShort(MINOR_VERSION);
writeShort(RELEASE_NUMBER);
writeShort(filetype);
_stringPool.writeTo(_output);
}
void readEnd()
{
try
{
if (_input != null)
_input.close();
}
catch (IOException e)
{
// oh, well.
}
_input = null;
_stringPool = null;
_handle = null;
}
void writeEnd()
{
try
{
if (_output != null)
{
_output.flush();
_output.close();
}
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
_output = null;
_stringPool = null;
_handle = null;
}
int fileTypeFromComponentType(int componentType)
{
switch (componentType)
{
case SchemaComponent.TYPE:
return SchemaTypeSystemImpl.FILETYPE_SCHEMATYPE;
case SchemaComponent.ELEMENT:
return SchemaTypeSystemImpl.FILETYPE_SCHEMAELEMENT;
case SchemaComponent.ATTRIBUTE:
return SchemaTypeSystemImpl.FILETYPE_SCHEMAATTRIBUTE;
case SchemaComponent.MODEL_GROUP:
return SchemaTypeSystemImpl.FILETYPE_SCHEMAMODELGROUP;
case SchemaComponent.ATTRIBUTE_GROUP:
return SchemaTypeSystemImpl.FILETYPE_SCHEMAATTRIBUTEGROUP;
case SchemaComponent.IDENTITY_CONSTRAINT:
return SchemaTypeSystemImpl.FILETYPE_SCHEMAIDENTITYCONSTRAINT;
default:
throw new IllegalStateException("Unexpected component type");
}
}
void writeIndexData()
{
// has a handle pool (count, handle/type, handle/type...)
writeHandlePool(_localHandles);
// then a qname map of global elements (count, qname/handle, qname/handle...)
writeQNameMap(globalElements());
// qname map of global attributes
writeQNameMap(globalAttributes());
// qname map of model groups
writeQNameMap(modelGroups());
// qname map of attribute groups
writeQNameMap(attributeGroups());
// qname map of identity constraints
writeQNameMap(identityConstraints());
// qname map of global types
writeQNameMap(globalTypes());
// qname map of document types, by the qname of the contained element
writeDocumentTypeMap(documentTypes());
// qname map of attribute types, by the qname of the contained attribute
writeAttributeTypeMap(attributeTypes());
// all the types by classname
writeClassnameMap(_typeRefsByClassname);
// all the namespaces
writeNamespaces(_namespaces);
// VERSION 2.15 and newer below
writeQNameMap(redefinedGlobalTypes());
writeQNameMap(redefinedModelGroups());
writeQNameMap(redefinedAttributeGroups());
writeAnnotations(annotations());
}
void writeHandlePool(HandlePool pool)
{
writeShort(pool._componentsToHandles.size());
for (Iterator i = pool._componentsToHandles.keySet().iterator(); i.hasNext(); )
{
SchemaComponent comp = (SchemaComponent)i.next();
String handle = (String)pool._componentsToHandles.get(comp);
int code = fileTypeFromComponentType(comp.getComponentType());
writeString(handle);
writeShort(code);
}
}
void readHandlePool(HandlePool pool)
{
if (pool._handlesToRefs.size() != 0 || pool._started)
throw new IllegalStateException("Nonempty handle set before read");
int size = readShort();
for (int i = 0; i < size; i++)
{
String handle = readString();
int code = readShort();
Object result;
switch (code)
{
case FILETYPE_SCHEMATYPE:
result = new SchemaType.Ref(getTypeSystem(), handle);
break;
case FILETYPE_SCHEMAELEMENT:
result = new SchemaGlobalElement.Ref(getTypeSystem(), handle);
break;
case FILETYPE_SCHEMAATTRIBUTE:
result = new SchemaGlobalAttribute.Ref(getTypeSystem(), handle);
break;
case FILETYPE_SCHEMAMODELGROUP:
result = new SchemaModelGroup.Ref(getTypeSystem(), handle);
break;
case FILETYPE_SCHEMAATTRIBUTEGROUP:
result = new SchemaAttributeGroup.Ref(getTypeSystem(), handle);
break;
case FILETYPE_SCHEMAIDENTITYCONSTRAINT:
result = new SchemaIdentityConstraint.Ref(getTypeSystem(), handle);
break;
default:
throw new SchemaTypeLoaderException("Schema index has an unrecognized entry of type " + code, _name, handle, SchemaTypeLoaderException.UNRECOGNIZED_INDEX_ENTRY);
}
pool._handlesToRefs.put(handle, result);
}
}
int readShort()
{
try
{
return _input.readUnsignedShort();
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
void writeShort(int s)
{
if (s >= MAX_UNSIGNED_SHORT || s < -1)
throw new SchemaTypeLoaderException("Value " + s + " out of range: must fit in a 16-bit unsigned short.", _name, _handle, SchemaTypeLoaderException.INT_TOO_LARGE);
if (_output != null)
{
try
{
_output.writeShort(s);
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
}
int readInt()
{
try
{
return _input.readInt();
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
void writeInt(int i)
{
if (_output != null)
{
try
{
_output.writeInt(i);
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
}
String readString()
{
return _stringPool.stringForCode(readShort());
}
void writeString(String str)
{
int code = _stringPool.codeForString(str);
writeShort(code);
}
QName readQName()
{
String namespace = readString();
String localname = readString();
if (localname == null)
return null;
return new QName(namespace, localname);
}
void writeQName(QName qname)
{
if (qname == null)
{
writeString(null);
writeString(null);
return;
}
writeString(qname.getNamespaceURI());
writeString(qname.getLocalPart());
}
SOAPArrayType readSOAPArrayType()
{
QName qName = readQName();
String dimensions = readString();
if (qName == null)
return null;
return new SOAPArrayType(qName, dimensions);
}
void writeSOAPArrayType(SOAPArrayType arrayType)
{
if (arrayType == null)
{
writeQName(null);
writeString(null);
}
else
{
writeQName(arrayType.getQName());
writeString(arrayType.soap11DimensionString());
}
}
void writeAnnotation(SchemaAnnotation a)
{
// Write attributes
if (a == null)
{
writeInt(-1);
return;
}
SchemaAnnotation.Attribute[] attributes = a.getAttributes();
writeInt(attributes.length);
for (int i = 0; i < attributes.length; i++)
{
QName name = attributes[i].getName();
String value = attributes[i].getValue();
String valueURI = attributes[i].getValueUri();
writeQName(name);
writeString(value);
writeString(valueURI);
}
// Write documentation items
XmlObject[] documentationItems = a.getUserInformation();
writeInt(documentationItems.length);
XmlOptions opt = new XmlOptions().setSaveOuter().
setSaveAggressiveNamespaces();
for (int i = 0; i < documentationItems.length; i++)
{
XmlObject doc = documentationItems[i];
writeString(doc.xmlText(opt));
}
// Write application info items
XmlObject[] appInfoItems = a.getApplicationInformation();
writeInt(appInfoItems.length);
for (int i = 0; i < appInfoItems.length; i++)
{
XmlObject doc = appInfoItems[i];
writeString(doc.xmlText(opt));
}
}
SchemaAnnotation readAnnotation(SchemaContainer c)
{
if (!atLeast(2, 19, 0))
return null; // no annotations for this version of the file
// Read attributes
int n = readInt();
if (n == -1)
return null;
SchemaAnnotation.Attribute[] attributes =
new SchemaAnnotation.Attribute[n];
for (int i = 0; i < n; i++)
{
QName name = readQName();
String value = readString();
String valueUri = null;
if (atLeast(2, 24, 0))
valueUri = readString();
attributes[i] = new SchemaAnnotationImpl.AttributeImpl(name, value, valueUri);
}
// Read documentation items
n = readInt();
String[] docStrings = new String[n];
for (int i = 0; i < n; i++)
{
docStrings[i] = readString();
}
// Read application info items
n = readInt();
String[] appInfoStrings = new String[n];
for (int i = 0; i < n; i++)
{
appInfoStrings[i] = readString();
}
return new SchemaAnnotationImpl(c, appInfoStrings,
docStrings, attributes);
}
void writeAnnotations(SchemaAnnotation[] anns)
{
writeInt(anns.length);
for (int i = 0; i < anns.length; i++)
writeAnnotation(anns[i]);
}
List readAnnotations()
{
int n = readInt();
List result = new ArrayList(n);
// BUGBUG(radup)
SchemaContainer container = getContainerNonNull("");
for (int i = 0; i < n; i++)
result.add(readAnnotation(container));
return result;
}
SchemaComponent.Ref readHandle()
{
String handle = readString();
if (handle == null)
return null;
if (handle.charAt(0) != '_')
return _localHandles.refForHandle(handle);
switch (handle.charAt(2))
{
case 'I': // _BI_ - built-in schema type system
SchemaType st = (SchemaType) BuiltinSchemaTypeSystem.get().resolveHandle(handle);
if (st != null)
return st.getRef();
st = (SchemaType) XQuerySchemaTypeSystem.get().resolveHandle(handle);
return st.getRef();
case 'T': // _XT_ - external type
return _linker.findTypeRef(QNameHelper.forPretty(handle, 4));
case 'E': // _XE_ - external element
return _linker.findElementRef(QNameHelper.forPretty(handle, 4));
case 'A': // _XA_ - external attribute
return _linker.findAttributeRef(QNameHelper.forPretty(handle, 4));
case 'M': // _XM_ - external model group
return _linker.findModelGroupRef(QNameHelper.forPretty(handle, 4));
case 'N': // _XN_ - external attribute group
return _linker.findAttributeGroupRef(QNameHelper.forPretty(handle, 4));
case 'D': // _XD_ - external identity constraint
return _linker.findIdentityConstraintRef(QNameHelper.forPretty(handle, 4));
case 'R': // _XR_ - external ref to attribute's type
// deprecated: replaced by _XY_
SchemaGlobalAttribute attr = _linker.findAttribute(QNameHelper.forPretty(handle, 4));
if (attr == null)
throw new SchemaTypeLoaderException("Cannot resolve attribute for handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
return attr.getType().getRef();
case 'S': // _XS_ - external ref to element's type
// deprecated: replaced by _XY_
SchemaGlobalElement elem = _linker.findElement(QNameHelper.forPretty(handle, 4));
if (elem == null)
throw new SchemaTypeLoaderException("Cannot resolve element for handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
return elem.getType().getRef();
case 'O': // _XO_ - external ref to document type
return _linker.findDocumentTypeRef(QNameHelper.forPretty(handle, 4));
case 'Y': // _XY_ - external ref to any possible type
SchemaType type = _linker.typeForSignature(handle.substring(4));
if (type == null)
throw new SchemaTypeLoaderException("Cannot resolve type for handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
return type.getRef();
default:
throw new SchemaTypeLoaderException("Cannot resolve handle " + handle, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
}
}
void writeHandle(SchemaComponent comp)
{
if (comp == null || comp.getTypeSystem() == getTypeSystem())
{
writeString(_localHandles.handleForComponent(comp));
return;
}
switch (comp.getComponentType())
{
case SchemaComponent.ATTRIBUTE:
writeString("_XA_" + QNameHelper.pretty(comp.getName()));
return;
case SchemaComponent.MODEL_GROUP:
writeString("_XM_" + QNameHelper.pretty(comp.getName()));
return;
case SchemaComponent.ATTRIBUTE_GROUP:
writeString("_XN_" + QNameHelper.pretty(comp.getName()));
return;
case SchemaComponent.ELEMENT:
writeString("_XE_" + QNameHelper.pretty(comp.getName()));
return;
case SchemaComponent.IDENTITY_CONSTRAINT:
writeString("_XD_" + QNameHelper.pretty(comp.getName()));
return;
case SchemaComponent.TYPE:
SchemaType type = (SchemaType)comp;
if (type.isBuiltinType())
{
writeString("_BI_" + type.getName().getLocalPart());
return;
}
// fix for CR120759 - added output of types _XR_ & _XS_
// when an attribute (_XR_) or element (_XS_) declaration
// uses ref to refer to an attribute or element in another
// schema and the type of that attribute or element
// is an anonymous (local) type
// kkrouse 02/1/2005: _XR_ and _XS_ refs are replaced by _XY_
if (type.getName() != null)
{
writeString("_XT_" + QNameHelper.pretty(type.getName()));
}
else if (type.isDocumentType())
{
// Substitution groups will create document types that
// extend from other document types, possibly in
// different jars
writeString("_XO_" + QNameHelper.pretty(type.getDocumentElementName()));
}
else
{
// fix for XMLBEANS-105:
// save out the external type reference using the type's signature.
writeString("_XY_" + type.toString());
}
return;
default:
assert(false);
throw new SchemaTypeLoaderException("Cannot write handle for component " + comp, _name, _handle, SchemaTypeLoaderException.BAD_HANDLE);
}
}
SchemaType.Ref readTypeRef()
{
return (SchemaType.Ref)readHandle();
}
void writeType(SchemaType type)
{
writeHandle(type);
}
Map readQNameRefMap()
{
Map result = new HashMap();
int size = readShort();
for (int i = 0; i < size; i++)
{
QName name = readQName();
SchemaComponent.Ref obj = readHandle();
result.put(name, obj);
}
return result;
}
List readQNameRefMapAsList(List names)
{
int size = readShort();
List result = new ArrayList(size);
for (int i = 0; i < size; i++)
{
QName name = readQName();
SchemaComponent.Ref obj = readHandle();
result.add(obj);
names.add(name);
}
return result;
}
void writeQNameMap(SchemaComponent[] components)
{
writeShort(components.length);
for (int i = 0; i < components.length; i++)
{
writeQName(components[i].getName());
writeHandle(components[i]);
}
}
void writeDocumentTypeMap(SchemaType[] doctypes)
{
writeShort(doctypes.length);
for (int i = 0; i < doctypes.length; i++)
{
writeQName(doctypes[i].getDocumentElementName());
writeHandle(doctypes[i]);
}
}
void writeAttributeTypeMap(SchemaType[] attrtypes)
{
writeShort(attrtypes.length);
for (int i = 0; i < attrtypes.length; i++)
{
writeQName(attrtypes[i].getAttributeTypeAttributeName());
writeHandle(attrtypes[i]);
}
}
SchemaType.Ref[] readTypeRefArray()
{
int size = readShort();
SchemaType.Ref[] result = new SchemaType.Ref[size];
for (int i = 0; i < size; i++)
{
result[i] = readTypeRef();
}
return result;
}
void writeTypeArray(SchemaType[] array)
{
writeShort(array.length);
for (int i = 0; i < array.length; i++)
{
writeHandle(array[i]);
}
}
Map readClassnameRefMap()
{
Map result = new HashMap();
int size = readShort();
for (int i = 0; i < size; i++)
{
String name = readString();
SchemaComponent.Ref obj = readHandle();
result.put(name, obj);
}
return result;
}
void writeClassnameMap(Map typesByClass)
{
writeShort(typesByClass.size());
for (Iterator i = typesByClass.keySet().iterator(); i.hasNext(); )
{
String className = (String)i.next();
writeString(className);
writeHandle(((SchemaType.Ref)typesByClass.get(className)).get());
}
}
Set readNamespaces()
{
Set result = new HashSet();
int size = readShort();
for (int i = 0; i < size; i++)
{
String ns = readString();
result.add(ns);
}
return result;
}
void writeNamespaces(Set namespaces)
{
writeShort(namespaces.size());
for (Iterator i = namespaces.iterator(); i.hasNext(); )
{
String ns = (String)i.next();
writeString(ns);
}
}
OutputStream getSaverStream(String name)
{
try
{
return _filer.createBinaryFile(name);
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
InputStream getLoaderStream(String resourcename)
{
return _resourceLoader.getResourceAsStream(resourcename);
}
void checkContainerNotNull(SchemaContainer container, QName name)
{
if (container == null)
{
throw new LinkageError("Loading of resource " + _name + '.' + _handle +
"failed, information from " + _name + ".index.xsb is " +
" out of sync (or conflicting index files found)");
}
}
/**
* Finishes loading an element after the header has already been loaded.
*/
public SchemaGlobalElement finishLoadingElement()
{
String handle = null;
try
{
int particleType = readShort();
if (particleType != SchemaParticle.ELEMENT)
throw new SchemaTypeLoaderException("Wrong particle type ", _name, _handle, SchemaTypeLoaderException.BAD_PARTICLE_TYPE);
int particleFlags = readShort();
BigInteger minOccurs = readBigInteger();
BigInteger maxOccurs = readBigInteger();
QNameSet transitionRules = readQNameSet();
QName name = readQName();
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
SchemaGlobalElementImpl impl = new SchemaGlobalElementImpl(container);
impl.setParticleType(particleType);
impl.setMinOccurs(minOccurs);
impl.setMaxOccurs(maxOccurs);
impl.setTransitionRules(transitionRules,
(particleFlags & FLAG_PART_SKIPPABLE) != 0);
impl.setNameAndTypeRef(name, readTypeRef());
impl.setDefault(readString(), (particleFlags & FLAG_PART_FIXED) != 0, null);
if (atLeast(2, 16, 0))
impl.setDefaultValue(readXmlValueObject());
impl.setNillable((particleFlags & FLAG_PART_NILLABLE) != 0);
impl.setBlock((particleFlags & FLAG_PART_BLOCKEXT) != 0,
(particleFlags & FLAG_PART_BLOCKREST) != 0,
(particleFlags & FLAG_PART_BLOCKSUBST) != 0);
impl.setWsdlArrayType(readSOAPArrayType());
impl.setAbstract((particleFlags & FLAG_PART_ABSTRACT) != 0);
impl.setAnnotation(readAnnotation(container));
impl.setFinal(
(particleFlags & FLAG_PART_FINALEXT) != 0,
(particleFlags & FLAG_PART_FINALREST) != 0);
if (atLeast(2, 17, 0))
impl.setSubstitutionGroup((SchemaGlobalElement.Ref)readHandle());
int substGroupCount = readShort();
for (int i = 0; i < substGroupCount; i++)
{
impl.addSubstitutionGroupMember(readQName());
}
SchemaIdentityConstraint.Ref[] idcs = new SchemaIdentityConstraint.Ref[readShort()];
for (int i = 0 ; i < idcs.length ; i++)
idcs[i] = (SchemaIdentityConstraint.Ref)readHandle();
impl.setIdentityConstraints(idcs);
impl.setFilename(readString());
return impl;
}
catch (SchemaTypeLoaderException e)
{
throw e;
}
catch (Exception e)
{
throw new SchemaTypeLoaderException("Cannot load type from typesystem", _name, handle, SchemaTypeLoaderException.NESTED_EXCEPTION, e);
}
finally
{
readEnd();
}
}
public SchemaGlobalAttribute finishLoadingAttribute()
{
try
{
QName name = readQName();
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
SchemaGlobalAttributeImpl impl = new SchemaGlobalAttributeImpl(container);
loadAttribute(impl, name, container);
impl.setFilename(readString());
return impl;
}
catch (SchemaTypeLoaderException e)
{
throw e;
}
catch (Exception e)
{
throw new SchemaTypeLoaderException("Cannot load type from typesystem", _name, _handle, SchemaTypeLoaderException.NESTED_EXCEPTION, e);
}
finally
{
readEnd();
}
}
SchemaModelGroup finishLoadingModelGroup()
{
QName name = readQName();
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
SchemaModelGroupImpl impl = new SchemaModelGroupImpl(container);
try
{
impl.init(name, readString(), readShort() == 1,
atLeast(2, 22, 0) ? readString() : null,
atLeast(2, 22, 0) ? readString() : null,
atLeast(2, 15, 0) ? readShort() == 1 : false,
GroupDocument.Factory.parse( readString() ).getGroup(), readAnnotation(container), null);
if (atLeast(2, 21, 0))
impl.setFilename(readString());
return impl;
}
catch (SchemaTypeLoaderException e)
{
throw e;
}
catch (Exception e)
{
throw new SchemaTypeLoaderException("Cannot load type from typesystem", _name, _handle, SchemaTypeLoaderException.NESTED_EXCEPTION, e);
}
finally
{
readEnd();
}
}
SchemaIdentityConstraint finishLoadingIdentityConstraint()
{
try {
QName name = readQName();
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
SchemaIdentityConstraintImpl impl = new SchemaIdentityConstraintImpl(container);
impl.setName(name);
impl.setConstraintCategory(readShort());
impl.setSelector(readString());
impl.setAnnotation(readAnnotation(container));
String[] fields = new String[readShort()];
for (int i = 0 ; i < fields.length ; i++)
fields[i] = readString();
impl.setFields(fields);
if (impl.getConstraintCategory() == SchemaIdentityConstraint.CC_KEYREF)
impl.setReferencedKey((SchemaIdentityConstraint.Ref)readHandle());
int mapCount = readShort();
Map nsMappings = new HashMap();
for (int i = 0 ; i < mapCount ; i++)
{
String prefix = readString();
String uri = readString();
nsMappings.put(prefix, uri);
}
impl.setNSMap(nsMappings);
if (atLeast(2, 21, 0))
impl.setFilename(readString());
return impl;
}
catch (SchemaTypeLoaderException e)
{
throw e;
}
catch (Exception e)
{
throw new SchemaTypeLoaderException("Cannot load type from typesystem", _name, _handle, SchemaTypeLoaderException.NESTED_EXCEPTION, e);
}
finally
{
readEnd();
}
}
SchemaAttributeGroup finishLoadingAttributeGroup()
{
QName name = readQName();
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
SchemaAttributeGroupImpl impl = new SchemaAttributeGroupImpl(container);
try
{
impl.init( name, readString(), readShort() == 1,
atLeast(2, 22, 0) ? readString() : null,
atLeast(2, 15, 0) ? readShort() == 1 : false,
AttributeGroupDocument.Factory.parse( readString() ).getAttributeGroup(),
readAnnotation(container), null);
if (atLeast(2, 21, 0))
impl.setFilename(readString());
return impl;
}
catch (SchemaTypeLoaderException e)
{
throw e;
}
catch (Exception e)
{
throw new SchemaTypeLoaderException("Cannot load type from typesystem", _name, _handle, SchemaTypeLoaderException.NESTED_EXCEPTION, e);
}
finally
{
readEnd();
}
}
public SchemaType finishLoadingType()
{
try
{
SchemaContainer cNonNull = getContainerNonNull(""); //HACKHACK
SchemaTypeImpl impl = new SchemaTypeImpl(cNonNull, true);
impl.setName(readQName());
impl.setOuterSchemaTypeRef(readTypeRef());
impl.setBaseDepth(readShort());
impl.setBaseTypeRef(readTypeRef());
impl.setDerivationType(readShort());
impl.setAnnotation(readAnnotation(null));
switch (readShort())
{
case FIELD_GLOBAL:
impl.setContainerFieldRef(readHandle());
break;
case FIELD_LOCALATTR:
impl.setContainerFieldIndex((short)1, readShort());
break;
case FIELD_LOCALELT:
impl.setContainerFieldIndex((short)2, readShort());
break;
}
// TODO (radup) find the right solution here
String jn = readString();
impl.setFullJavaName(jn == null ? "" : jn);
jn = readString();
impl.setFullJavaImplName(jn == null? "" : jn);
impl.setAnonymousTypeRefs(readTypeRefArray());
impl.setAnonymousUnionMemberOrdinal(readShort());
int flags;
flags = readInt();
boolean isComplexType = ((flags & FLAG_SIMPLE_TYPE) == 0);
impl.setCompiled((flags & FLAG_COMPILED) != 0);
impl.setDocumentType((flags & FLAG_DOCUMENT_TYPE) != 0);
impl.setAttributeType((flags & FLAG_ATTRIBUTE_TYPE) != 0);
impl.setSimpleType(!isComplexType);
int complexVariety = SchemaType.NOT_COMPLEX_TYPE;
if (isComplexType)
{
impl.setAbstractFinal((flags & FLAG_ABSTRACT) != 0,
(flags & FLAG_FINAL_EXT) != 0,
(flags & FLAG_FINAL_REST) != 0,
(flags & FLAG_FINAL_LIST) != 0,
(flags & FLAG_FINAL_UNION) != 0);
impl.setBlock((flags & FLAG_BLOCK_EXT) != 0,
(flags & FLAG_BLOCK_REST) != 0);
impl.setOrderSensitive((flags & FLAG_ORDER_SENSITIVE) != 0);
complexVariety = readShort();
impl.setComplexTypeVariety(complexVariety);
if (atLeast(2, 23, 0))
impl.setContentBasedOnTypeRef(readTypeRef());
// Attribute Model Table
SchemaAttributeModelImpl attrModel = new SchemaAttributeModelImpl();
int attrCount = readShort();
for (int i = 0; i < attrCount; i++)
attrModel.addAttribute(readAttributeData());
attrModel.setWildcardSet(readQNameSet());
attrModel.setWildcardProcess(readShort());
// Attribute Property Table
Map attrProperties = new LinkedHashMap();
int attrPropCount = readShort();
for (int i = 0; i < attrPropCount; i++)
{
SchemaProperty prop = readPropertyData();
if (!prop.isAttribute())
throw new SchemaTypeLoaderException("Attribute property " + i + " is not an attribute", _name, _handle, SchemaTypeLoaderException.WRONG_PROPERTY_TYPE);
attrProperties.put(prop.getName(), prop);
}
SchemaParticle contentModel = null;
Map elemProperties = null;
int isAll = 0;
if (complexVariety == SchemaType.ELEMENT_CONTENT || complexVariety == SchemaType.MIXED_CONTENT)
{
// Content Model Tree
isAll = readShort();
SchemaParticle[] parts = readParticleArray();
if (parts.length == 1)
contentModel = parts[0];
else if (parts.length == 0)
contentModel = null;
else
throw new SchemaTypeLoaderException("Content model not well-formed", _name, _handle, SchemaTypeLoaderException.MALFORMED_CONTENT_MODEL);
// Element Property Table
elemProperties = new LinkedHashMap();
int elemPropCount = readShort();
for (int i = 0; i < elemPropCount; i++)
{
SchemaProperty prop = readPropertyData();
if (prop.isAttribute())
throw new SchemaTypeLoaderException("Element property " + i + " is not an element", _name, _handle, SchemaTypeLoaderException.WRONG_PROPERTY_TYPE);
elemProperties.put(prop.getName(), prop);
}
}
impl.setContentModel(contentModel, attrModel, elemProperties, attrProperties, isAll == 1);
StscComplexTypeResolver.WildcardResult wcElt = StscComplexTypeResolver.summarizeEltWildcards(contentModel);
StscComplexTypeResolver.WildcardResult wcAttr = StscComplexTypeResolver.summarizeAttrWildcards(attrModel);
impl.setWildcardSummary(wcElt.typedWildcards, wcElt.hasWildcards, wcAttr.typedWildcards, wcAttr.hasWildcards);
}
if (!isComplexType || complexVariety == SchemaType.SIMPLE_CONTENT)
{
int simpleVariety = readShort();
impl.setSimpleTypeVariety(simpleVariety);
boolean isStringEnum = ((flags & FLAG_STRINGENUM) != 0);
impl.setOrdered((flags & FLAG_ORDERED) != 0 ? SchemaType.UNORDERED : ((flags & FLAG_TOTAL_ORDER) != 0 ? SchemaType.TOTAL_ORDER : SchemaType.PARTIAL_ORDER));
impl.setBounded((flags & FLAG_BOUNDED) != 0);
impl.setFinite((flags & FLAG_FINITE) != 0);
impl.setNumeric((flags & FLAG_NUMERIC) != 0);
impl.setUnionOfLists((flags & FLAG_UNION_OF_LISTS) != 0);
impl.setSimpleFinal((flags & FLAG_FINAL_REST) != 0,
(flags & FLAG_FINAL_LIST) != 0,
(flags & FLAG_FINAL_UNION) != 0);
XmlValueRef[] facets = new XmlValueRef[SchemaType.LAST_FACET + 1];
boolean[] fixedFacets = new boolean[SchemaType.LAST_FACET + 1];
int facetCount = readShort();
for (int i = 0; i < facetCount; i++)
{
int facetCode = readShort();
facets[facetCode] = readXmlValueObject();
fixedFacets[facetCode] = (readShort() == 1);
}
impl.setBasicFacets(facets, fixedFacets);
impl.setWhiteSpaceRule(readShort());
impl.setPatternFacet((flags & FLAG_HAS_PATTERN) != 0);
int patternCount = readShort();
org.apache.xmlbeans.impl.regex.RegularExpression[] patterns = new org.apache.xmlbeans.impl.regex.RegularExpression[patternCount];
for (int i = 0; i < patternCount; i++)
{
patterns[i] = new org.apache.xmlbeans.impl.regex.RegularExpression(readString(), "X");
}
impl.setPatterns(patterns);
int enumCount = readShort();
XmlValueRef[] enumValues = new XmlValueRef[enumCount];
for (int i = 0; i < enumCount; i++)
{
enumValues[i] = readXmlValueObject();
}
impl.setEnumerationValues(enumCount == 0 ? null : enumValues);
impl.setBaseEnumTypeRef(readTypeRef());
if (isStringEnum)
{
int seCount = readShort();
SchemaStringEnumEntry[] entries = new SchemaStringEnumEntry[seCount];
for (int i = 0; i < seCount; i++)
{
entries[i] = new SchemaStringEnumEntryImpl(readString(), readShort(), readString());
}
impl.setStringEnumEntries(entries);
}
switch (simpleVariety)
{
case SchemaType.ATOMIC:
impl.setPrimitiveTypeRef(readTypeRef());
impl.setDecimalSize(readInt());
break;
case SchemaType.LIST:
impl.setPrimitiveTypeRef(BuiltinSchemaTypeSystem.ST_ANY_SIMPLE.getRef());
impl.setListItemTypeRef(readTypeRef());
break;
case SchemaType.UNION:
impl.setPrimitiveTypeRef(BuiltinSchemaTypeSystem.ST_ANY_SIMPLE.getRef());
impl.setUnionMemberTypeRefs(readTypeRefArray());
break;
default:
throw new SchemaTypeLoaderException("Simple type does not have a recognized variety", _name, _handle, SchemaTypeLoaderException.WRONG_SIMPLE_VARIETY);
}
}
impl.setFilename(readString());
// Set the container for global, attribute or document types
if (impl.getName() != null)
{
SchemaContainer container = getContainer(impl.getName().getNamespaceURI());
checkContainerNotNull(container, impl.getName());
impl.setContainer(container);
}
else if (impl.isDocumentType())
{
QName name = impl.getDocumentElementName();
if (name != null)
{
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
impl.setContainer(container);
}
}
else if (impl.isAttributeType())
{
QName name = impl.getAttributeTypeAttributeName();
if (name != null)
{
SchemaContainer container = getContainer(name.getNamespaceURI());
checkContainerNotNull(container, name);
impl.setContainer(container);
}
}
return impl;
}
catch (SchemaTypeLoaderException e)
{
throw e;
}
catch (Exception e)
{
throw new SchemaTypeLoaderException("Cannot load type from typesystem", _name, _handle, SchemaTypeLoaderException.NESTED_EXCEPTION, e);
}
finally
{
readEnd();
}
}
void writeTypeData(SchemaType type)
{
writeQName(type.getName());
writeType(type.getOuterType());
writeShort(((SchemaTypeImpl)type).getBaseDepth());
writeType(type.getBaseType());
writeShort(type.getDerivationType());
writeAnnotation(type.getAnnotation());
if (type.getContainerField() == null)
{
writeShort(FIELD_NONE);
}
else if (type.getOuterType().isAttributeType() || type.getOuterType().isDocumentType())
{
writeShort(FIELD_GLOBAL);
writeHandle((SchemaComponent)type.getContainerField());
}
else if (type.getContainerField().isAttribute())
{
writeShort(FIELD_LOCALATTR);
writeShort(((SchemaTypeImpl)type.getOuterType()).getIndexForLocalAttribute((SchemaLocalAttribute)type.getContainerField()));
}
else
{
writeShort(FIELD_LOCALELT);
writeShort(((SchemaTypeImpl)type.getOuterType()).getIndexForLocalElement((SchemaLocalElement)type.getContainerField()));
}
writeString(type.getFullJavaName());
writeString(type.getFullJavaImplName());
writeTypeArray(type.getAnonymousTypes());
writeShort(type.getAnonymousUnionMemberOrdinal());
int flags = 0;
if (type.isSimpleType())
flags |= FLAG_SIMPLE_TYPE;
if (type.isDocumentType())
flags |= FLAG_DOCUMENT_TYPE;
if (type.isAttributeType())
flags |= FLAG_ATTRIBUTE_TYPE;
if (type.ordered() != SchemaType.UNORDERED)
flags |= FLAG_ORDERED;
if (type.ordered() == SchemaType.TOTAL_ORDER)
flags |= FLAG_TOTAL_ORDER;
if (type.isBounded())
flags |= FLAG_BOUNDED;
if (type.isFinite())
flags |= FLAG_FINITE;
if (type.isNumeric())
flags |= FLAG_NUMERIC;
if (type.hasStringEnumValues())
flags |= FLAG_STRINGENUM;
if (((SchemaTypeImpl)type).isUnionOfLists())
flags |= FLAG_UNION_OF_LISTS;
if (type.hasPatternFacet())
flags |= FLAG_HAS_PATTERN;
if (type.isOrderSensitive())
flags |= FLAG_ORDER_SENSITIVE;
if (type.blockExtension())
flags |= FLAG_BLOCK_EXT;
if (type.blockRestriction())
flags |= FLAG_BLOCK_REST;
if (type.finalExtension())
flags |= FLAG_FINAL_EXT;
if (type.finalRestriction())
flags |= FLAG_FINAL_EXT;
if (type.finalList())
flags |= FLAG_FINAL_LIST;
if (type.finalUnion())
flags |= FLAG_FINAL_UNION;
if (type.isAbstract())
flags |= FLAG_ABSTRACT;
writeInt(flags);
if (!type.isSimpleType())
{
writeShort(type.getContentType());
writeType(type.getContentBasedOnType());
// Attribute Model Table
SchemaAttributeModel attrModel = type.getAttributeModel();
SchemaLocalAttribute[] attrs = attrModel.getAttributes();
writeShort(attrs.length);
for (int i = 0; i < attrs.length; i++)
writeAttributeData(attrs[i]);
writeQNameSet(attrModel.getWildcardSet());
writeShort(attrModel.getWildcardProcess());
// Attribute Property Table
SchemaProperty[] attrProperties = type.getAttributeProperties();
writeShort(attrProperties.length);
for (int i = 0; i < attrProperties.length; i++)
writePropertyData(attrProperties[i]);
if (type.getContentType() == SchemaType.ELEMENT_CONTENT ||
type.getContentType() == SchemaType.MIXED_CONTENT)
{
// Content Model Tree
writeShort(type.hasAllContent() ? 1 : 0);
SchemaParticle[] parts;
if (type.getContentModel() != null)
parts = new SchemaParticle[] { type.getContentModel() };
else
parts = new SchemaParticle[0];
writeParticleArray(parts);
// Element Property Table
SchemaProperty[] eltProperties = type.getElementProperties();
writeShort(eltProperties.length);
for (int i = 0; i < eltProperties.length; i++)
writePropertyData(eltProperties[i]);
}
}
if (type.isSimpleType() || type.getContentType() == SchemaType.SIMPLE_CONTENT)
{
writeShort(type.getSimpleVariety());
int facetCount = 0;
for (int i = 0; i <= SchemaType.LAST_FACET; i++)
if (type.getFacet(i) != null)
facetCount++;
writeShort(facetCount);
for (int i = 0; i <= SchemaType.LAST_FACET; i++)
{
XmlAnySimpleType facet = type.getFacet(i);
if (facet != null)
{
writeShort(i);
writeXmlValueObject(facet);
writeShort(type.isFacetFixed(i) ? 1 : 0);
}
}
writeShort(type.getWhiteSpaceRule());
org.apache.xmlbeans.impl.regex.RegularExpression[] patterns = ((SchemaTypeImpl)type).getPatternExpressions();
writeShort(patterns.length);
for (int i = 0; i < patterns.length; i++)
writeString(patterns[i].getPattern());
XmlAnySimpleType[] enumValues = type.getEnumerationValues();
if (enumValues == null)
writeShort(0);
else
{
writeShort(enumValues.length);
for (int i = 0; i < enumValues.length; i++)
writeXmlValueObject(enumValues[i]);
}
// new for version 2.3
writeType(type.getBaseEnumType());
if (type.hasStringEnumValues())
{
SchemaStringEnumEntry[] entries = type.getStringEnumEntries();
writeShort(entries.length);
for (int i = 0; i < entries.length; i++)
{
writeString(entries[i].getString());
writeShort(entries[i].getIntValue());
writeString(entries[i].getEnumName());
}
}
switch (type.getSimpleVariety())
{
case SchemaType.ATOMIC:
writeType(type.getPrimitiveType());
writeInt(type.getDecimalSize());
break;
case SchemaType.LIST:
writeType(type.getListItemType());
break;
case SchemaType.UNION:
writeTypeArray(type.getUnionMemberTypes());
break;
}
}
writeString(type.getSourceName());
}
void readExtensionsList()
{
int count = readShort();
assert count == 0;
for (int i = 0; i < count; i++)
{
readString();
readString();
readString();
}
}
SchemaLocalAttribute readAttributeData()
{
SchemaLocalAttributeImpl result = new SchemaLocalAttributeImpl();
loadAttribute(result, readQName(), null);
return result;
}
void loadAttribute(SchemaLocalAttributeImpl result, QName name, SchemaContainer container)
{
// name, type, use, deftext, defval, fixed, soaparraytype, annotation
result.init(name, readTypeRef(), readShort(), readString(), null, atLeast(2, 16, 0) ? readXmlValueObject() : null, readShort() == 1, readSOAPArrayType(), readAnnotation(container), null);
}
void writeAttributeData(SchemaLocalAttribute attr)
{
writeQName(attr.getName());
writeType(attr.getType());
writeShort(attr.getUse());
writeString(attr.getDefaultText());
writeXmlValueObject(attr.getDefaultValue());
writeShort(attr.isFixed() ? 1 : 0);
writeSOAPArrayType(((SchemaWSDLArrayType)attr).getWSDLArrayType());
writeAnnotation(attr.getAnnotation());
}
void writeIdConstraintData(SchemaIdentityConstraint idc)
{
writeQName(idc.getName());
writeShort(idc.getConstraintCategory());
writeString(idc.getSelector());
writeAnnotation(idc.getAnnotation());
String[] fields = idc.getFields();
writeShort(fields.length);
for (int i = 0 ; i < fields.length ; i++)
writeString(fields[i]);
if (idc.getConstraintCategory() == SchemaIdentityConstraint.CC_KEYREF)
writeHandle(idc.getReferencedKey());
Set mappings = idc.getNSMap().entrySet();
writeShort(mappings.size());
for (Iterator it = mappings.iterator() ; it.hasNext() ; ) {
Map.Entry e = (Map.Entry)it.next();
String prefix = (String)e.getKey();
String uri = (String)e.getValue();
writeString(prefix);
writeString(uri);
}
writeString(idc.getSourceName());
}
SchemaParticle[] readParticleArray()
{
SchemaParticle[] result = new SchemaParticle[readShort()];
for (int i = 0; i < result.length; i++)
result[i] = readParticleData();
return result;
}
void writeParticleArray(SchemaParticle[] spa)
{
writeShort(spa.length);
for (int i = 0; i < spa.length; i++)
writeParticleData(spa[i]);
}
SchemaParticle readParticleData()
{
int particleType = readShort();
SchemaParticleImpl result;
if (particleType != SchemaParticle.ELEMENT)
result = new SchemaParticleImpl();
else
result = new SchemaLocalElementImpl();
loadParticle(result, particleType);
return result;
}
void loadParticle(SchemaParticleImpl result, int particleType)
{
int particleFlags = readShort();
result.setParticleType(particleType);
result.setMinOccurs(readBigInteger());
result.setMaxOccurs(readBigInteger());
result.setTransitionRules(readQNameSet(),
(particleFlags & FLAG_PART_SKIPPABLE) != 0);
switch (particleType)
{
case SchemaParticle.WILDCARD:
result.setWildcardSet(readQNameSet());
result.setWildcardProcess(readShort());
break;
case SchemaParticle.ELEMENT:
SchemaLocalElementImpl lresult = (SchemaLocalElementImpl)result;
lresult.setNameAndTypeRef(readQName(), readTypeRef());
lresult.setDefault(readString(), (particleFlags & FLAG_PART_FIXED) != 0, null);
if (atLeast(2, 16, 0))
lresult.setDefaultValue(readXmlValueObject());
lresult.setNillable((particleFlags & FLAG_PART_NILLABLE) != 0);
lresult.setBlock((particleFlags & FLAG_PART_BLOCKEXT) != 0,
(particleFlags & FLAG_PART_BLOCKREST) != 0,
(particleFlags & FLAG_PART_BLOCKSUBST) != 0);
lresult.setWsdlArrayType(readSOAPArrayType());
lresult.setAbstract((particleFlags & FLAG_PART_ABSTRACT) != 0);
lresult.setAnnotation(readAnnotation(null));
SchemaIdentityConstraint.Ref[] idcs = new SchemaIdentityConstraint.Ref[readShort()];
for (int i = 0 ; i < idcs.length ; i++)
idcs[i] = (SchemaIdentityConstraint.Ref)readHandle();
lresult.setIdentityConstraints(idcs);
break;
case SchemaParticle.ALL:
case SchemaParticle.SEQUENCE:
case SchemaParticle.CHOICE:
result.setParticleChildren(readParticleArray());
break;
default:
throw new SchemaTypeLoaderException("Unrecognized particle type ", _name, _handle, SchemaTypeLoaderException.BAD_PARTICLE_TYPE);
}
}
void writeParticleData(SchemaParticle part)
{
writeShort(part.getParticleType());
short flags = 0;
if (part.isSkippable())
flags |= FLAG_PART_SKIPPABLE;
if (part.getParticleType() == SchemaParticle.ELEMENT)
{
SchemaLocalElement lpart = (SchemaLocalElement)part;
if (lpart.isFixed())
flags |= FLAG_PART_FIXED;
if (lpart.isNillable())
flags |= FLAG_PART_NILLABLE;
if (lpart.blockExtension())
flags |= FLAG_PART_BLOCKEXT;
if (lpart.blockRestriction())
flags |= FLAG_PART_BLOCKREST;
if (lpart.blockSubstitution())
flags |= FLAG_PART_BLOCKSUBST;
if (lpart.isAbstract())
flags |= FLAG_PART_ABSTRACT;
if (lpart instanceof SchemaGlobalElement)
{
SchemaGlobalElement gpart = (SchemaGlobalElement)lpart;
if (gpart.finalExtension())
flags |= FLAG_PART_FINALEXT;
if (gpart.finalRestriction())
flags |= FLAG_PART_FINALREST;
}
}
writeShort(flags);
writeBigInteger(part.getMinOccurs());
writeBigInteger(part.getMaxOccurs());
writeQNameSet(part.acceptedStartNames());
switch (part.getParticleType())
{
case SchemaParticle.WILDCARD:
writeQNameSet(part.getWildcardSet());
writeShort(part.getWildcardProcess());
break;
case SchemaParticle.ELEMENT:
SchemaLocalElement lpart = (SchemaLocalElement)part;
writeQName(lpart.getName());
writeType(lpart.getType());
writeString(lpart.getDefaultText());
writeXmlValueObject(lpart.getDefaultValue());
writeSOAPArrayType(((SchemaWSDLArrayType)lpart).getWSDLArrayType());
writeAnnotation(lpart.getAnnotation());
if (lpart instanceof SchemaGlobalElement)
{
SchemaGlobalElement gpart = (SchemaGlobalElement)lpart;
writeHandle(gpart.substitutionGroup());
QName[] substGroupMembers = gpart.substitutionGroupMembers();
writeShort(substGroupMembers.length);
for (int i = 0; i < substGroupMembers.length; i++)
writeQName(substGroupMembers[i]);
}
SchemaIdentityConstraint[] idcs = lpart.getIdentityConstraints();
writeShort(idcs.length);
for (int i = 0 ; i < idcs.length ; i++)
writeHandle(idcs[i]);
break;
case SchemaParticle.ALL:
case SchemaParticle.SEQUENCE:
case SchemaParticle.CHOICE:
writeParticleArray(part.getParticleChildren());
break;
default:
throw new SchemaTypeLoaderException("Unrecognized particle type ", _name, _handle, SchemaTypeLoaderException.BAD_PARTICLE_TYPE);
}
}
SchemaProperty readPropertyData()
{
SchemaPropertyImpl prop = new SchemaPropertyImpl();
prop.setName(readQName());
prop.setTypeRef(readTypeRef());
int propflags = readShort();
prop.setAttribute((propflags & FLAG_PROP_ISATTR) != 0);
prop.setContainerTypeRef(readTypeRef());
prop.setMinOccurs(readBigInteger());
prop.setMaxOccurs(readBigInteger());
prop.setNillable(readShort());
prop.setDefault(readShort());
prop.setFixed(readShort());
prop.setDefaultText(readString());
prop.setJavaPropertyName(readString());
prop.setJavaTypeCode(readShort());
prop.setExtendsJava(readTypeRef(),
(propflags & FLAG_PROP_JAVASINGLETON) != 0,
(propflags & FLAG_PROP_JAVAOPTIONAL) != 0,
(propflags & FLAG_PROP_JAVAARRAY) != 0);
if (atMost(2, 19, 0))
prop.setJavaSetterDelimiter(readQNameSet());
if (atLeast(2, 16, 0))
prop.setDefaultValue(readXmlValueObject());
if (!prop.isAttribute() && atLeast(2, 17, 0))
{
int size = readShort();
LinkedHashSet qnames = new LinkedHashSet(size);
for (int i = 0 ; i < size ; i++)
qnames.add(readQName());
prop.setAcceptedNames(qnames);
}
prop.setImmutable();
return prop;
}
void writePropertyData(SchemaProperty prop)
{
writeQName(prop.getName());
writeType(prop.getType());
writeShort((prop.isAttribute() ? FLAG_PROP_ISATTR : 0) |
(prop.extendsJavaSingleton() ? FLAG_PROP_JAVASINGLETON : 0) |
(prop.extendsJavaOption() ? FLAG_PROP_JAVAOPTIONAL : 0) |
(prop.extendsJavaArray() ? FLAG_PROP_JAVAARRAY : 0));
writeType(prop.getContainerType());
writeBigInteger(prop.getMinOccurs());
writeBigInteger(prop.getMaxOccurs());
writeShort(prop.hasNillable());
writeShort(prop.hasDefault());
writeShort(prop.hasFixed());
writeString(prop.getDefaultText());
writeString(prop.getJavaPropertyName());
writeShort(prop.getJavaTypeCode());
writeType(prop.javaBasedOnType());
writeXmlValueObject(prop.getDefaultValue());
if (! prop.isAttribute())
{
QName[] names = prop.acceptedNames();
writeShort(names.length);
for (int i = 0 ; i < names.length ; i++)
writeQName(names[i]);
}
}
void writeModelGroupData(SchemaModelGroup grp)
{
SchemaModelGroupImpl impl = (SchemaModelGroupImpl)grp;
writeQName(impl.getName());
writeString(impl.getTargetNamespace());
writeShort(impl.getChameleonNamespace() != null ? 1 : 0);
writeString(impl.getElemFormDefault()); // new for version 2.22
writeString(impl.getAttFormDefault()); // new for version 2.22
writeShort(impl.isRedefinition() ? 1 : 0); // new for version 2.15
writeString(impl.getParseObject().xmlText(new XmlOptions().setSaveOuter()));
writeAnnotation(impl.getAnnotation());
writeString(impl.getSourceName());
}
void writeAttributeGroupData(SchemaAttributeGroup grp)
{
SchemaAttributeGroupImpl impl = (SchemaAttributeGroupImpl)grp;
writeQName(impl.getName());
writeString(impl.getTargetNamespace());
writeShort(impl.getChameleonNamespace() != null ? 1 : 0);
writeString(impl.getFormDefault()); // new for version 2.22
writeShort(impl.isRedefinition() ? 1 : 0); // new for version 2.15
writeString(impl.getParseObject().xmlText(new XmlOptions().setSaveOuter()));
writeAnnotation(impl.getAnnotation());
writeString(impl.getSourceName());
}
XmlValueRef readXmlValueObject()
{
SchemaType.Ref typeref = readTypeRef();
if (typeref == null)
return null;
int btc = readShort();
switch (btc)
{
default:
assert(false);
case 0:
return new XmlValueRef(typeref, null);
case 0xFFFF:
{
int size = readShort();
List values = new ArrayList();
writeShort(values.size());
for (int i = 0; i < size; i++)
{
values.add(readXmlValueObject());
}
return new XmlValueRef(typeref, values);
}
case SchemaType.BTC_ANY_SIMPLE:
case SchemaType.BTC_ANY_URI:
case SchemaType.BTC_STRING:
case SchemaType.BTC_DURATION:
case SchemaType.BTC_DATE_TIME:
case SchemaType.BTC_TIME:
case SchemaType.BTC_DATE:
case SchemaType.BTC_G_YEAR_MONTH:
case SchemaType.BTC_G_YEAR:
case SchemaType.BTC_G_MONTH_DAY:
case SchemaType.BTC_G_DAY:
case SchemaType.BTC_G_MONTH:
case SchemaType.BTC_DECIMAL:
case SchemaType.BTC_BOOLEAN:
return new XmlValueRef(typeref, readString());
case SchemaType.BTC_BASE_64_BINARY:
case SchemaType.BTC_HEX_BINARY:
return new XmlValueRef(typeref, readByteArray());
case SchemaType.BTC_QNAME:
case SchemaType.BTC_NOTATION:
return new XmlValueRef(typeref, readQName());
case SchemaType.BTC_FLOAT:
case SchemaType.BTC_DOUBLE:
return new XmlValueRef(typeref, new Double(readDouble()));
}
}
void writeXmlValueObject(XmlAnySimpleType value)
{
SchemaType type = value == null ? null : value.schemaType();
writeType(type);
if (type == null)
return;
SchemaType iType = ((SimpleValue)value).instanceType();
if (iType == null)
{
writeShort(0);
}
else if (iType.getSimpleVariety() == SchemaType.LIST)
{
writeShort(-1);
List values = ((XmlObjectBase)value).xgetListValue();
writeShort(values.size());
for (Iterator i = values.iterator(); i.hasNext(); )
{
writeXmlValueObject((XmlAnySimpleType)i.next());
}
}
else
{
int btc = iType.getPrimitiveType().getBuiltinTypeCode();
writeShort(btc);
switch (btc)
{
case SchemaType.BTC_ANY_SIMPLE:
case SchemaType.BTC_ANY_URI:
case SchemaType.BTC_STRING:
case SchemaType.BTC_DURATION:
case SchemaType.BTC_DATE_TIME:
case SchemaType.BTC_TIME:
case SchemaType.BTC_DATE:
case SchemaType.BTC_G_YEAR_MONTH:
case SchemaType.BTC_G_YEAR:
case SchemaType.BTC_G_MONTH_DAY:
case SchemaType.BTC_G_DAY:
case SchemaType.BTC_G_MONTH:
case SchemaType.BTC_DECIMAL:
case SchemaType.BTC_BOOLEAN:
writeString(value.getStringValue());
break;
case SchemaType.BTC_BASE_64_BINARY:
case SchemaType.BTC_HEX_BINARY:
writeByteArray(((SimpleValue)value).getByteArrayValue());
break;
case SchemaType.BTC_QNAME:
case SchemaType.BTC_NOTATION:
writeQName(((SimpleValue)value).getQNameValue());
break;
case SchemaType.BTC_FLOAT:
writeDouble(((SimpleValue)value).getFloatValue());
break;
case SchemaType.BTC_DOUBLE:
writeDouble(((SimpleValue)value).getDoubleValue());
break;
}
}
}
double readDouble()
{
try
{
return _input.readDouble();
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
void writeDouble(double d)
{
if (_output != null)
{
try
{
_output.writeDouble(d);
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
}
QNameSet readQNameSet()
{
int flag = readShort();
Set uriSet = new HashSet();
int uriCount = readShort();
for (int i = 0; i < uriCount; i++)
uriSet.add(readString());
Set qnameSet1 = new HashSet();
int qncount1 = readShort();
for (int i = 0; i < qncount1; i++)
qnameSet1.add(readQName());
Set qnameSet2 = new HashSet();
int qncount2 = readShort();
for (int i = 0; i < qncount2; i++)
qnameSet2.add(readQName());
if (flag == 1)
return QNameSet.forSets(uriSet, null, qnameSet1, qnameSet2);
else
return QNameSet.forSets(null, uriSet, qnameSet2, qnameSet1);
}
void writeQNameSet(QNameSet set)
{
boolean invert = (set.excludedURIs() != null);
writeShort(invert ? 1 : 0);
Set uriSet = invert ? set.excludedURIs() : set.includedURIs();
writeShort(uriSet.size());
for (Iterator i = uriSet.iterator(); i.hasNext(); )
writeString((String)i.next());
Set qnameSet1 = invert ? set.excludedQNamesInIncludedURIs() : set.includedQNamesInExcludedURIs();
writeShort(qnameSet1.size());
for (Iterator i = qnameSet1.iterator(); i.hasNext(); )
writeQName((QName)i.next());
Set qnameSet2 = invert ? set.includedQNamesInExcludedURIs() : set.excludedQNamesInIncludedURIs();
writeShort(qnameSet2.size());
for (Iterator i = qnameSet2.iterator(); i.hasNext(); )
writeQName((QName)i.next());
}
byte[] readByteArray()
{
try
{
int len = _input.readShort();
byte[] result = new byte[len];
_input.readFully(result);
return result;
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
void writeByteArray(byte[] ba)
{
try
{
writeShort(ba.length);
if (_output != null)
_output.write(ba);
}
catch (IOException e)
{
throw new SchemaTypeLoaderException(e.getMessage(), _name, _handle, SchemaTypeLoaderException.IO_EXCEPTION);
}
}
BigInteger readBigInteger()
{
byte[] result = readByteArray();
if (result.length == 0)
return null;
if (result.length == 1 && result[0] == 0)
return BigInteger.ZERO;
if (result.length == 1 && result[0] == 1)
return BigInteger.ONE;
return new BigInteger(result);
}
void writeBigInteger(BigInteger bi)
{
if (bi == null)
{
writeShort(0);
}
else if (bi.signum() == 0)
{
writeByteArray(SINGLE_ZERO_BYTE);
}
else
{
writeByteArray(bi.toByteArray());
}
}
}
static final byte[] SINGLE_ZERO_BYTE = new byte[] { (byte)0 };
public SchemaType typeForHandle(String handle)
{
synchronized (_resolvedHandles)
{
return (SchemaType)_resolvedHandles.get(handle);
}
}
public SchemaType typeForClassname(String classname)
{
SchemaType.Ref ref = (SchemaType.Ref)_typeRefsByClassname.get(classname);
return (ref != null) ? ref.get() : null;
}
public SchemaComponent resolveHandle(String handle)
{
SchemaComponent result;
synchronized (_resolvedHandles)
{
result = (SchemaComponent)_resolvedHandles.get(handle);
}
if (result == null)
{
XsbReader reader = new XsbReader(handle, 0xFFFF);
int filetype = reader.getActualFiletype();
switch (filetype)
{
case FILETYPE_SCHEMATYPE:
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving type for handle " + handle, 0);
result = reader.finishLoadingType();
break;
case FILETYPE_SCHEMAELEMENT:
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving element for handle " + handle, 0);
result = reader.finishLoadingElement();
break;
case FILETYPE_SCHEMAATTRIBUTE:
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving attribute for handle " + handle, 0);
result = reader.finishLoadingAttribute();
break;
case FILETYPE_SCHEMAMODELGROUP:
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving model group for handle " + handle, 0);
result = reader.finishLoadingModelGroup();
break;
case FILETYPE_SCHEMAATTRIBUTEGROUP:
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving attribute group for handle " + handle, 0);
result = reader.finishLoadingAttributeGroup();
break;
case FILETYPE_SCHEMAIDENTITYCONSTRAINT:
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving id constraint for handle " + handle, 0);
result = reader.finishLoadingIdentityConstraint();
break;
default:
throw new IllegalStateException("Illegal handle type");
}
synchronized (_resolvedHandles)
{
if (!_resolvedHandles.containsKey(handle))
_resolvedHandles.put(handle, result);
else
result = (SchemaComponent)_resolvedHandles.get(handle);
}
}
return result;
}
private final Map _resolvedHandles = new HashMap();
private boolean _allNonGroupHandlesResolved = false;
public void resolve()
{
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolve called type system " + _name, 0);
if (_allNonGroupHandlesResolved)
return;
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Resolving all handles for type system " + _name, 1);
List refs = new ArrayList();
refs.addAll(_globalElements.values());
refs.addAll(_globalAttributes.values());
refs.addAll(_globalTypes.values());
refs.addAll(_documentTypes.values());
refs.addAll(_attributeTypes.values());
refs.addAll(_identityConstraints.values());
for (Iterator i = refs.iterator(); i.hasNext(); )
{
SchemaComponent.Ref ref = (SchemaComponent.Ref)i.next();
ref.getComponent(); // Forces ref to be resolved
}
XBeanDebug.trace(XBeanDebug.TRACE_SCHEMA_LOADING, "Finished resolving type system " + _name, -1);
_allNonGroupHandlesResolved = true;
}
public boolean isNamespaceDefined(String namespace)
{
return _namespaces.contains(namespace);
}
public SchemaType.Ref findTypeRef(QName name)
{
return (SchemaType.Ref)_globalTypes.get(name);
}
public SchemaType.Ref findDocumentTypeRef(QName name)
{
return (SchemaType.Ref)_documentTypes.get(name);
}
public SchemaType.Ref findAttributeTypeRef(QName name)
{
return (SchemaType.Ref)_attributeTypes.get(name);
}
public SchemaGlobalElement.Ref findElementRef(QName name)
{
return (SchemaGlobalElement.Ref)_globalElements.get(name);
}
public SchemaGlobalAttribute.Ref findAttributeRef(QName name)
{
return (SchemaGlobalAttribute.Ref)_globalAttributes.get(name);
}
public SchemaModelGroup.Ref findModelGroupRef(QName name)
{
return (SchemaModelGroup.Ref)_modelGroups.get(name);
}
public SchemaAttributeGroup.Ref findAttributeGroupRef(QName name)
{
return (SchemaAttributeGroup.Ref)_attributeGroups.get(name);
}
public SchemaIdentityConstraint.Ref findIdentityConstraintRef(QName name)
{
return (SchemaIdentityConstraint.Ref)_identityConstraints.get(name);
}
public SchemaType[] globalTypes()
{
if (_globalTypes.isEmpty())
return EMPTY_ST_ARRAY;
SchemaType[] result = new SchemaType[_globalTypes.size()];
int j = 0;
for (Iterator i = _globalTypes.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaType.Ref)i.next()).get();
return result;
}
public SchemaType[] redefinedGlobalTypes()
{
if (_redefinedGlobalTypes == null || _redefinedGlobalTypes.isEmpty())
return EMPTY_ST_ARRAY;
SchemaType[] result = new SchemaType[_redefinedGlobalTypes.size()];
int j = 0;
for (Iterator i = _redefinedGlobalTypes.iterator(); i.hasNext(); j++)
result[j] = ((SchemaType.Ref)i.next()).get();
return result;
}
public InputStream getSourceAsStream(String sourceName)
{
if (!sourceName.startsWith("/"))
sourceName = "/" + sourceName;
return _resourceLoader.getResourceAsStream(getMetadataPath() + "/src" + sourceName);
}
SchemaContainer[] containers()
{
SchemaContainer[] result = new SchemaContainer[_containers.size()];
int j = 0;
for (Iterator i = _containers.values().iterator(); i.hasNext(); j++)
result[j] = (SchemaContainer) i.next();
return result;
}
public SchemaType[] documentTypes()
{
if (_documentTypes.isEmpty())
return EMPTY_ST_ARRAY;
SchemaType[] result = new SchemaType[_documentTypes.size()];
int j = 0;
for (Iterator i = _documentTypes.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaType.Ref)i.next()).get();
return result;
}
public SchemaType[] attributeTypes()
{
if (_attributeTypes.isEmpty())
return EMPTY_ST_ARRAY;
SchemaType[] result = new SchemaType[_attributeTypes.size()];
int j = 0;
for (Iterator i = _attributeTypes.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaType.Ref)i.next()).get();
return result;
}
public SchemaGlobalElement[] globalElements()
{
if (_globalElements.isEmpty())
return EMPTY_GE_ARRAY;
SchemaGlobalElement[] result = new SchemaGlobalElement[_globalElements.size()];
int j = 0;
for (Iterator i = _globalElements.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaGlobalElement.Ref)i.next()).get();
return result;
}
public SchemaGlobalAttribute[] globalAttributes()
{
if (_globalAttributes.isEmpty())
return EMPTY_GA_ARRAY;
SchemaGlobalAttribute[] result = new SchemaGlobalAttribute[_globalAttributes.size()];
int j = 0;
for (Iterator i = _globalAttributes.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaGlobalAttribute.Ref)i.next()).get();
return result;
}
public SchemaModelGroup[] modelGroups()
{
if (_modelGroups.isEmpty())
return EMPTY_MG_ARRAY;
SchemaModelGroup[] result = new SchemaModelGroup[_modelGroups.size()];
int j = 0;
for (Iterator i = _modelGroups.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaModelGroup.Ref)i.next()).get();
return result;
}
public SchemaModelGroup[] redefinedModelGroups()
{
if (_redefinedModelGroups == null || _redefinedModelGroups.isEmpty())
return EMPTY_MG_ARRAY;
SchemaModelGroup[] result = new SchemaModelGroup[_redefinedModelGroups.size()];
int j = 0;
for (Iterator i = _redefinedModelGroups.iterator(); i.hasNext(); j++)
result[j] = ((SchemaModelGroup.Ref)i.next()).get();
return result;
}
public SchemaAttributeGroup[] attributeGroups()
{
if (_attributeGroups.isEmpty())
return EMPTY_AG_ARRAY;
SchemaAttributeGroup[] result = new SchemaAttributeGroup[_attributeGroups.size()];
int j = 0;
for (Iterator i = _attributeGroups.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaAttributeGroup.Ref)i.next()).get();
return result;
}
public SchemaAttributeGroup[] redefinedAttributeGroups()
{
if (_redefinedAttributeGroups == null || _redefinedAttributeGroups.isEmpty())
return EMPTY_AG_ARRAY;
SchemaAttributeGroup[] result = new SchemaAttributeGroup[_redefinedAttributeGroups.size()];
int j = 0;
for (Iterator i = _redefinedAttributeGroups.iterator(); i.hasNext(); j++)
result[j] = ((SchemaAttributeGroup.Ref)i.next()).get();
return result;
}
public SchemaAnnotation[] annotations()
{
if (_annotations == null || _annotations.isEmpty())
return EMPTY_ANN_ARRAY;
SchemaAnnotation[] result = new SchemaAnnotation[_annotations.size()];
result = (SchemaAnnotation[]) _annotations.toArray(result);
return result;
}
public SchemaIdentityConstraint[] identityConstraints()
{
if (_identityConstraints.isEmpty())
return EMPTY_IC_ARRAY;
SchemaIdentityConstraint[] result = new SchemaIdentityConstraint[_identityConstraints.size()];
int j = 0;
for (Iterator i = _identityConstraints.values().iterator(); i.hasNext(); j++)
result[j] = ((SchemaIdentityConstraint.Ref)i.next()).get();
return result;
}
public ClassLoader getClassLoader()
{
return _classloader;
}
/**
* Used INTERNALLY ONLY by the code output AFTER the type system has
* been saved and a handle has been established for each type.
*/
public String handleForType(SchemaType type)
{
return _localHandles.handleForType(type);
}
public String getName()
{
return _name;
}
public SchemaTypeSystem typeSystemForName(String name)
{
if (_name != null && name.equals(_name))
return this;
return null;
}
/**
* Provide method to be overriden by user typesystems using a different metadata path
*
* @return the metadata directory
*
* @since XmlBeans 3.0.3
*/
protected String getMetadataPath() {
return "schema" + METADATA_PACKAGE_GEN;
}
}