| /* 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.*; |
| import org.apache.xmlbeans.impl.common.QNameHelper; |
| import org.apache.xmlbeans.impl.common.ResolverUtil; |
| import org.apache.xmlbeans.impl.util.HexBin; |
| import org.apache.xmlbeans.impl.values.XmlStringImpl; |
| import org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException; |
| import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument; |
| import org.xml.sax.EntityResolver; |
| |
| import javax.xml.namespace.QName; |
| import java.io.File; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.nio.charset.StandardCharsets; |
| import java.util.*; |
| import java.util.function.Consumer; |
| |
| /** |
| * This class represents the state of the SchemaTypeSystemCompiler as it's |
| * going. |
| */ |
| public class StscState { |
| private final static XmlValueRef XMLSTR_PRESERVE = buildString("preserve"); |
| private final static XmlValueRef XMLSTR_REPLACE = buildString("preserve"); |
| private final static XmlValueRef XMLSTR_COLLAPSE = buildString("preserve"); |
| |
| static final SchemaType[] EMPTY_ST_ARRAY = new SchemaType[0]; |
| |
| private static final XmlValueRef[] FACETS_NONE = new XmlValueRef[12]; |
| private static final boolean[] FIXED_FACETS_NONE = new boolean[12]; |
| private static final boolean[] FIXED_FACETS_WS = new boolean[12]; |
| |
| private static final XmlValueRef[] FACETS_WS_COLLAPSE = { |
| null, null, null, null, null, null, null, null, null, |
| build_wsstring(SchemaType.WS_COLLAPSE), null, null |
| }; |
| |
| |
| final static XmlValueRef[] FACETS_UNION = FACETS_NONE; |
| final static boolean[] FIXED_FACETS_UNION = FIXED_FACETS_NONE; |
| final static XmlValueRef[] FACETS_LIST = FACETS_WS_COLLAPSE; |
| final static boolean[] FIXED_FACETS_LIST = FIXED_FACETS_WS; |
| |
| private static final ThreadLocal<StscStack> tl_stscStack = new ThreadLocal<>(); |
| |
| private final static String PROJECT_URL_PREFIX = "project://local"; |
| |
| |
| private String _givenStsName; |
| private Collection<XmlError> _errorListener; |
| private SchemaTypeSystemImpl _target; |
| private BindingConfig _config; |
| private Map<QName, QName> _compatMap; |
| private boolean _doingDownloads; |
| private byte[] _digest = null; |
| private boolean _noDigest = false; |
| |
| // EXPERIMENTAL: recovery from compilation errors and partial type systems |
| private boolean _allowPartial = false; |
| private int _recoveredErrors = 0; |
| |
| private SchemaTypeLoader _importingLoader; |
| |
| private final Map<String, SchemaContainer> _containers = new LinkedHashMap<>(); |
| private SchemaDependencies _dependencies; |
| |
| private Map _redefinedGlobalTypes = new LinkedHashMap(); |
| private Map _redefinedModelGroups = new LinkedHashMap(); |
| private Map _redefinedAttributeGroups = new LinkedHashMap(); |
| |
| private final Map<QName, SchemaType> _globalTypes = new LinkedHashMap<>(); |
| private final Map<QName, SchemaGlobalElement> _globalElements = new LinkedHashMap<>(); |
| private final Map<QName, SchemaGlobalAttribute> _globalAttributes = new LinkedHashMap<>(); |
| private final Map<QName, SchemaModelGroup> _modelGroups = new LinkedHashMap<>(); |
| private final Map<QName, SchemaAttributeGroup> _attributeGroups = new LinkedHashMap<>(); |
| private final Map<QName, SchemaType> _documentTypes = new LinkedHashMap<>(); |
| private final Map<QName, SchemaType> _attributeTypes = new LinkedHashMap<>(); |
| private final Map<String, SchemaType> _typesByClassname = new LinkedHashMap<>(); |
| private final Map<String, SchemaComponent> _misspelledNames = new HashMap<>(); |
| private final Set<SchemaComponent> _processingGroups = new LinkedHashSet<>(); |
| private final Map<QName, SchemaIdentityConstraint> _idConstraints = new LinkedHashMap<>(); |
| private final Set<String> _namespaces = new HashSet<>(); |
| private final List<SchemaAnnotation> _annotations = new ArrayList<>(); |
| private boolean _noUpa; |
| private boolean _noPvr; |
| private boolean _noAnn; |
| private boolean _mdefAll; |
| private final Set<String> _mdefNamespaces = buildDefaultMdefNamespaces(); |
| private EntityResolver _entityResolver; |
| private File _schemasDir; |
| |
| |
| private final Map<String, String> _sourceForUri = new HashMap<>(); |
| private URI _baseURI = URI.create(PROJECT_URL_PREFIX + "/"); |
| private final SchemaTypeLoader _s4sloader = XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader()); |
| |
| |
| private static Set<String> buildDefaultMdefNamespaces() { |
| // namespaces which are known to appear in WSDLs redundantly |
| return new HashSet<>( |
| Collections.singletonList("http://www.openuri.org/2002/04/soap/conversation/")); |
| } |
| |
| /** |
| * Only constructed via StscState.start(). |
| */ |
| private StscState() { |
| } |
| |
| /** |
| * Initializer for incremental compilation |
| */ |
| public void initFromTypeSystem(SchemaTypeSystemImpl system, Set<String> newNamespaces) { |
| // setGivenTypeSystemName(system.getName().substring(14)); |
| |
| SchemaContainer[] containers = system.containers(); |
| for (SchemaContainer container : containers) { |
| if (!newNamespaces.contains(container.getNamespace())) { |
| // Copy data from the given container |
| addContainer(container); |
| } |
| } |
| } |
| |
| |
| /* CONTAINERS ================================================================*/ |
| |
| void addNewContainer(String namespace) { |
| if (_containers.containsKey(namespace)) { |
| return; |
| } |
| |
| SchemaContainer container = new SchemaContainer(namespace); |
| container.setTypeSystem(sts()); |
| addNamespace(namespace); |
| _containers.put(namespace, container); |
| } |
| |
| private void addContainer(SchemaContainer container) { |
| _containers.put(container.getNamespace(), container); |
| List redefModelGroups = container.redefinedModelGroups(); |
| for (int i = 0; i < redefModelGroups.size(); i++) { |
| QName name = ((SchemaModelGroup) redefModelGroups.get(i)).getName(); |
| _redefinedModelGroups.put(name, redefModelGroups.get(i)); |
| } |
| |
| List redefAttrGroups = container.redefinedAttributeGroups(); |
| for (int i = 0; i < redefAttrGroups.size(); i++) { |
| QName name = ((SchemaAttributeGroup) redefAttrGroups.get(i)).getName(); |
| _redefinedAttributeGroups.put(name, redefAttrGroups.get(i)); |
| } |
| |
| List redefTypes = container.redefinedGlobalTypes(); |
| for (int i = 0; i < redefTypes.size(); i++) { |
| QName name = ((SchemaType) redefTypes.get(i)).getName(); |
| _redefinedGlobalTypes.put(name, redefTypes.get(i)); |
| } |
| |
| container.globalElements().forEach(g -> _globalElements.put(g.getName(), g)); |
| container.globalAttributes().forEach(g -> _globalAttributes.put(g.getName(), g)); |
| container.modelGroups().forEach(g -> _modelGroups.put(g.getName(), g)); |
| container.attributeGroups().forEach(g -> _attributeGroups.put(g.getName(), g)); |
| |
| container.globalTypes().forEach(mapTypes(_globalTypes, false)); |
| container.documentTypes().forEach(mapTypes(_documentTypes, true)); |
| container.attributeTypes().forEach(mapTypes(_attributeTypes, true)); |
| |
| container.identityConstraints().forEach(g -> _idConstraints.put(g.getName(), g)); |
| |
| _annotations.addAll(container.annotations()); |
| _namespaces.add(container.getNamespace()); |
| container.unsetImmutable(); |
| } |
| |
| private Consumer<SchemaType> mapTypes(Map<QName, SchemaType> map, boolean useProperties) { |
| return (t) -> { |
| QName name = useProperties ? t.getProperties()[0].getName() : t.getName(); |
| map.put(name, t); |
| if (t.getFullJavaName() != null) { |
| addClassname(t.getFullJavaName(), t); |
| } |
| }; |
| } |
| |
| SchemaContainer getContainer(String namespace) { |
| return _containers.get(namespace); |
| } |
| |
| Map<String, SchemaContainer> getContainerMap() { |
| return Collections.unmodifiableMap(_containers); |
| } |
| |
| /* DEPENDENCIES ================================================================*/ |
| |
| void registerDependency(String sourceNs, String targetNs) { |
| _dependencies.registerDependency(sourceNs, targetNs); |
| } |
| |
| void registerContribution(String ns, String fileUrl) { |
| _dependencies.registerContribution(ns, fileUrl); |
| } |
| |
| SchemaDependencies getDependencies() { |
| return _dependencies; |
| } |
| |
| void setDependencies(SchemaDependencies deps) { |
| _dependencies = deps; |
| } |
| |
| boolean isFileProcessed(String url) { |
| return _dependencies.isFileRepresented(url); |
| } |
| |
| |
| /** |
| * Initializer for schematypepath |
| */ |
| public void setImportingTypeLoader(SchemaTypeLoader loader) { |
| _importingLoader = loader; |
| } |
| |
| /** |
| * Initializer for error handling. |
| */ |
| public void setErrorListener(Collection<XmlError> errorListener) { |
| _errorListener = errorListener; |
| } |
| |
| /** |
| * Passes an error on to the current error listener. |
| * KHK: remove this |
| */ |
| public void error(String message, int code, XmlObject loc) { |
| addError(_errorListener, message, code, loc); |
| } |
| |
| /** |
| * Passes an error on to the current error listener. |
| */ |
| public void error(String code, Object[] args, XmlObject loc) { |
| addError(_errorListener, code, args, loc); |
| } |
| |
| /** |
| * Passes a recovered error on to the current error listener. |
| */ |
| public void recover(String code, Object[] args, XmlObject loc) { |
| addError(_errorListener, code, args, loc); |
| _recoveredErrors++; |
| } |
| |
| /** |
| * Passes an error on to the current error listener. |
| */ |
| public void warning(String message, int code, XmlObject loc) { |
| addWarning(_errorListener, message, code, loc); |
| } |
| |
| /** |
| * Passes an error on to the current error listener. |
| */ |
| public void warning(String code, Object[] args, XmlObject loc) { |
| // it's OK for XMLSchema.xsd itself to have reserved type names |
| if (code == XmlErrorCodes.RESERVED_TYPE_NAME && |
| loc.documentProperties().getSourceName() != null && |
| loc.documentProperties().getSourceName().indexOf("XMLSchema.xsd") > 0) { |
| return; |
| } |
| |
| addWarning(_errorListener, code, args, loc); |
| } |
| |
| /** |
| * Passes a warning on to the current error listener. |
| */ |
| public void info(String message) { |
| addInfo(_errorListener, message); |
| } |
| |
| /** |
| * Passes a warning on to the current error listener. |
| */ |
| public void info(String code, Object[] args) { |
| addInfo(_errorListener, code, args); |
| } |
| |
| // KHK: remove this |
| public static void addError(Collection<XmlError> errorListener, String message, int code, XmlObject location) { |
| XmlError err = |
| XmlError.forObject( |
| message, |
| XmlError.SEVERITY_ERROR, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addError(Collection<XmlError> errorListener, String code, Object[] args, XmlObject location) { |
| XmlError err = |
| XmlError.forObject( |
| code, |
| args, |
| XmlError.SEVERITY_ERROR, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addError(Collection<XmlError> errorListener, String code, Object[] args, File location) { |
| XmlError err = |
| XmlError.forLocation( |
| code, |
| args, |
| XmlError.SEVERITY_ERROR, |
| location.toURI().toString(), 0, 0, 0); |
| errorListener.add(err); |
| } |
| |
| public static void addError(Collection<XmlError> errorListener, String code, Object[] args, URL location) { |
| XmlError err = |
| XmlError.forLocation( |
| code, |
| args, |
| XmlError.SEVERITY_ERROR, |
| location.toString(), 0, 0, 0); |
| errorListener.add(err); |
| } |
| |
| // KHK: remove this |
| public static void addWarning(Collection<XmlError> errorListener, String message, int code, XmlObject location) { |
| XmlError err = |
| XmlError.forObject( |
| message, |
| XmlError.SEVERITY_WARNING, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addWarning(Collection<XmlError> errorListener, String code, Object[] args, XmlObject location) { |
| XmlError err = |
| XmlError.forObject( |
| code, |
| args, |
| XmlError.SEVERITY_WARNING, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addInfo(Collection<XmlError> errorListener, String message) { |
| XmlError err = XmlError.forMessage(message, XmlError.SEVERITY_INFO); |
| errorListener.add(err); |
| } |
| |
| public static void addInfo(Collection<XmlError> errorListener, String code, Object[] args) { |
| XmlError err = XmlError.forMessage(code, args, XmlError.SEVERITY_INFO); |
| errorListener.add(err); |
| } |
| |
| public void setGivenTypeSystemName(String name) { |
| _givenStsName = name; |
| } |
| |
| /** |
| * Initializer for references to the SchemaTypeLoader |
| */ |
| public void setTargetSchemaTypeSystem(SchemaTypeSystemImpl target) { |
| _target = target; |
| } |
| |
| /** |
| * Accumulates a schema digest... |
| */ |
| public void addSchemaDigest(byte[] digest) { |
| if (_noDigest) { |
| return; |
| } |
| |
| if (digest == null) { |
| _noDigest = true; |
| _digest = null; |
| return; |
| } |
| |
| if (_digest == null) { |
| _digest = new byte[128 / 8]; // 128 bits. |
| } |
| int len = _digest.length; |
| if (digest.length < len) { |
| len = digest.length; |
| } |
| for (int i = 0; i < len; i++) { |
| _digest[i] ^= digest[i]; |
| } |
| } |
| |
| /** |
| * The SchemaTypeSystem which we're building types on behalf of. |
| */ |
| public SchemaTypeSystemImpl sts() { |
| if (_target != null) { |
| return _target; |
| } |
| |
| String name = _givenStsName; |
| if (name == null && _digest != null) { |
| name = "s" + new String(HexBin.encode(_digest), StandardCharsets.ISO_8859_1); |
| } |
| |
| _target = new SchemaTypeSystemImpl(name); |
| return _target; |
| } |
| |
| /** |
| * True if the given URI is a local file |
| */ |
| public boolean shouldDownloadURI(String uriString) { |
| if (_doingDownloads) { |
| return true; |
| } |
| |
| if (uriString == null) { |
| return false; |
| } |
| |
| try { |
| URI uri = new URI(uriString); |
| if (uri.getScheme().equalsIgnoreCase("jar") || |
| uri.getScheme().equalsIgnoreCase("zip")) { |
| // It may be local or not, depending on the embedded URI |
| String s = uri.getSchemeSpecificPart(); |
| int i = s.lastIndexOf('!'); |
| return shouldDownloadURI(i > 0 ? s.substring(0, i) : s); |
| } |
| return uri.getScheme().equalsIgnoreCase("file"); |
| } catch (Exception e) { |
| return false; |
| } |
| } |
| |
| /** |
| * Initializer for compatMap. |
| */ |
| public void setOptions(XmlOptions options) { |
| if (options == null) { |
| return; // defaults are all false. |
| } |
| |
| _allowPartial = options.hasOption("COMPILE_PARTIAL_TYPESYSTEM"); |
| |
| _compatMap = (Map) options.get(XmlOptions.COMPILE_SUBSTITUTE_NAMES); |
| _noUpa = options.hasOption(XmlOptions.COMPILE_NO_UPA_RULE) ? true : |
| !"true".equals(SystemProperties.getProperty("xmlbean.uniqueparticleattribution", "true")); |
| _noPvr = options.hasOption(XmlOptions.COMPILE_NO_PVR_RULE) ? true : |
| !"true".equals(SystemProperties.getProperty("xmlbean.particlerestriction", "true")); |
| _noAnn = options.hasOption(XmlOptions.COMPILE_NO_ANNOTATIONS) ? true : |
| !"true".equals(SystemProperties.getProperty("xmlbean.schemaannotations", "true")); |
| _doingDownloads = options.hasOption(XmlOptions.COMPILE_DOWNLOAD_URLS) ? true : |
| "true".equals(SystemProperties.getProperty("xmlbean.downloadurls", "false")); |
| _entityResolver = (EntityResolver) options.get(XmlOptions.ENTITY_RESOLVER); |
| |
| if (_entityResolver == null) { |
| _entityResolver = ResolverUtil.getGlobalEntityResolver(); |
| } |
| |
| if (_entityResolver != null) { |
| _doingDownloads = true; |
| } |
| |
| if (options.hasOption(XmlOptions.COMPILE_MDEF_NAMESPACES)) { |
| _mdefNamespaces.addAll((Collection) options.get(XmlOptions.COMPILE_MDEF_NAMESPACES)); |
| |
| String local = "##local"; |
| String any = "##any"; |
| |
| if (_mdefNamespaces.contains(local)) { |
| _mdefNamespaces.remove(local); |
| _mdefNamespaces.add(""); |
| } |
| if (_mdefNamespaces.contains(any)) { |
| _mdefNamespaces.remove(any); |
| _mdefAll = true; |
| } |
| } |
| } |
| |
| /** |
| * May return null if there is no custom entity resolver. |
| */ |
| public EntityResolver getEntityResolver() { |
| return _entityResolver; |
| } |
| |
| /** |
| * True if no unique particle attribution option is set |
| */ |
| public boolean noUpa() { |
| return _noUpa; |
| } |
| |
| /** |
| * True if no particle valid (restriciton) option is set |
| */ |
| public boolean noPvr() { |
| return _noPvr; |
| } |
| |
| /** |
| * True if annotations should be skipped |
| */ |
| public boolean noAnn() { |
| return _noAnn; |
| } |
| |
| /** |
| * True if a partial SchemaTypeSystem should be produced |
| */ |
| // EXPERIMENTAL |
| public boolean allowPartial() { |
| return _allowPartial; |
| } |
| |
| /** |
| * Get count of recovered errors. Not for public. |
| */ |
| // EXPERIMENTAL |
| public int getRecovered() { |
| return _recoveredErrors; |
| } |
| |
| /** |
| * Intercepts XML names and translates them |
| * through the compat map, if any. |
| * <p> |
| * Also looks for a default namespace for global definitions. |
| */ |
| private QName compatName(QName name, String chameleonNamespace) { |
| // first check for a chameleonNamespace namespace |
| if (name.getNamespaceURI().length() == 0 && chameleonNamespace != null && chameleonNamespace.length() > 0) { |
| name = new QName(chameleonNamespace, name.getLocalPart()); |
| } |
| |
| if (_compatMap == null) { |
| return name; |
| } |
| |
| QName subst = _compatMap.get(name); |
| if (subst == null) { |
| return name; |
| } |
| return subst; |
| } |
| |
| /** |
| * Initializer for the schema config object. |
| */ |
| public void setBindingConfig(BindingConfig config) |
| throws IllegalArgumentException { |
| _config = config; |
| } |
| |
| public BindingConfig getBindingConfig() |
| throws IllegalArgumentException { |
| return _config; |
| } |
| |
| /** |
| * Looks up package override for a namespace URI |
| */ |
| public String getPackageOverride(String namespace) { |
| if (_config == null) { |
| return null; |
| } |
| return _config.lookupPackageForNamespace(namespace); |
| } |
| |
| /** |
| * Looks up package override for a namespace URI |
| */ |
| public String getJavaPrefix(String namespace) { |
| if (_config == null) { |
| return null; |
| } |
| return _config.lookupPrefixForNamespace(namespace); |
| } |
| |
| /** |
| * Looks up package override for a namespace URI |
| */ |
| public String getJavaSuffix(String namespace) { |
| if (_config == null) { |
| return null; |
| } |
| return _config.lookupSuffixForNamespace(namespace); |
| } |
| |
| /** |
| * Looks up configured java name for the given qname. |
| */ |
| public String getJavaname(QName qname, int kind) { |
| if (_config == null) { |
| return null; |
| } |
| return _config.lookupJavanameForQName(qname, kind); |
| } |
| |
| /* SPELLINGS ======================================================*/ |
| |
| private static String crunchName(QName name) { |
| // lowercase, and drop namespace. |
| return name.getLocalPart().toLowerCase(); |
| } |
| |
| void addSpelling(QName name, SchemaComponent comp) { |
| _misspelledNames.put(crunchName(name), comp); |
| } |
| |
| SchemaComponent findSpelling(QName name) { |
| return _misspelledNames.get(crunchName(name)); |
| } |
| |
| /* NAMESPACES ======================================================*/ |
| |
| void addNamespace(String targetNamespace) { |
| _namespaces.add(targetNamespace); |
| } |
| |
| String[] getNamespaces() { |
| return _namespaces.toArray(new String[0]); |
| } |
| |
| boolean linkerDefinesNamespace(String namespace) { |
| return _importingLoader.isNamespaceDefined(namespace); |
| } |
| |
| /* TYPES ==========================================================*/ |
| |
| SchemaTypeImpl findGlobalType(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaTypeImpl result = (SchemaTypeImpl) _globalTypes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaTypeImpl) _importingLoader.findType(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| SchemaTypeImpl findRedefinedGlobalType(QName name, String chameleonNamespace, SchemaTypeImpl redefinedBy) { |
| QName redefinedName = redefinedBy.getName(); |
| name = compatName(name, chameleonNamespace); |
| if (name.equals(redefinedName)) { |
| return (SchemaTypeImpl) _redefinedGlobalTypes.get(redefinedBy); |
| // BUGBUG: should also link against _importingLoader.findRedefinedType |
| } |
| SchemaTypeImpl result = (SchemaTypeImpl) _globalTypes.get(name); |
| if (result == null) { |
| result = (SchemaTypeImpl) _importingLoader.findType(name); |
| } |
| // no dependency is needed here, necause it's intra-namespace |
| return result; |
| } |
| |
| void addGlobalType(SchemaTypeImpl type, SchemaTypeImpl redefined) { |
| if (type != null) { |
| QName name = type.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == type.getContainer(); |
| |
| if (redefined != null) { |
| if (_redefinedGlobalTypes.containsKey(redefined)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global type", QNameHelper.pretty(name), ((SchemaType) _redefinedGlobalTypes.get(redefined)).getSourceName()}, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global type", QNameHelper.pretty(name), ((SchemaType) _redefinedGlobalTypes.get(redefined)).getSourceName()}, |
| type.getParseObject()); |
| } |
| } |
| } else { |
| _redefinedGlobalTypes.put(redefined, type); |
| container.addRedefinedType(type.getRef()); |
| } |
| } else { |
| if (_globalTypes.containsKey(name)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global type", QNameHelper.pretty(name), _globalTypes.get(name).getSourceName()}, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global type", QNameHelper.pretty(name), _globalTypes.get(name).getSourceName()}, |
| type.getParseObject()); |
| } |
| } |
| } else { |
| _globalTypes.put(name, type); |
| container.addGlobalType(type.getRef()); |
| addSpelling(name, type); |
| } |
| } |
| } |
| } |
| |
| private boolean ignoreMdef(QName name) { |
| return _mdefNamespaces.contains(name.getNamespaceURI()); |
| } |
| |
| SchemaType[] globalTypes() { |
| return _globalTypes.values().toArray(new SchemaType[0]); |
| } |
| |
| SchemaType[] redefinedGlobalTypes() { |
| return (SchemaType[]) _redefinedGlobalTypes.values().toArray(new SchemaType[0]); |
| } |
| |
| /* DOCUMENT TYPES =================================================*/ |
| |
| SchemaTypeImpl findDocumentType(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaTypeImpl result = (SchemaTypeImpl) _documentTypes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaTypeImpl) _importingLoader.findDocumentType(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| void addDocumentType(SchemaTypeImpl type, QName name) { |
| if (_documentTypes.containsKey(name)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global element", QNameHelper.pretty(name), _documentTypes.get(name).getSourceName()}, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global element", QNameHelper.pretty(name), _documentTypes.get(name).getSourceName()}, |
| type.getParseObject()); |
| } |
| } |
| } else { |
| _documentTypes.put(name, type); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == type.getContainer(); |
| container.addDocumentType(type.getRef()); |
| } |
| } |
| |
| SchemaType[] documentTypes() { |
| return _documentTypes.values().toArray(new SchemaType[0]); |
| } |
| |
| /* ATTRIBUTE TYPES =================================================*/ |
| |
| SchemaTypeImpl findAttributeType(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaTypeImpl result = (SchemaTypeImpl) _attributeTypes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaTypeImpl) _importingLoader.findAttributeType(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| void addAttributeType(SchemaTypeImpl type, QName name) { |
| if (_attributeTypes.containsKey(name)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global attribute", QNameHelper.pretty(name), _attributeTypes.get(name).getSourceName()}, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"global attribute", QNameHelper.pretty(name), _attributeTypes.get(name).getSourceName()}, |
| type.getParseObject()); |
| } |
| } |
| } else { |
| _attributeTypes.put(name, type); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == type.getContainer(); |
| container.addAttributeType(type.getRef()); |
| } |
| } |
| |
| SchemaType[] attributeTypes() { |
| return _attributeTypes.values().toArray(new SchemaType[0]); |
| } |
| |
| /* ATTRIBUTES =====================================================*/ |
| |
| SchemaGlobalAttributeImpl findGlobalAttribute(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaGlobalAttributeImpl result = (SchemaGlobalAttributeImpl) _globalAttributes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaGlobalAttributeImpl) _importingLoader.findAttribute(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| void addGlobalAttribute(SchemaGlobalAttributeImpl attribute) { |
| if (attribute != null) { |
| QName name = attribute.getName(); |
| _globalAttributes.put(name, attribute); |
| addSpelling(name, attribute); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == attribute.getContainer(); |
| container.addGlobalAttribute(attribute.getRef()); |
| } |
| } |
| |
| SchemaGlobalAttribute[] globalAttributes() { |
| return _globalAttributes.values().toArray(new SchemaGlobalAttribute[0]); |
| } |
| |
| /* ELEMENTS =======================================================*/ |
| |
| SchemaGlobalElementImpl findGlobalElement(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaGlobalElementImpl result = (SchemaGlobalElementImpl) _globalElements.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaGlobalElementImpl) _importingLoader.findElement(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| void addGlobalElement(SchemaGlobalElementImpl element) { |
| if (element != null) { |
| QName name = element.getName(); |
| _globalElements.put(name, element); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == element.getContainer(); |
| container.addGlobalElement(element.getRef()); |
| addSpelling(name, element); |
| } |
| } |
| |
| SchemaGlobalElement[] globalElements() { |
| return _globalElements.values().toArray(new SchemaGlobalElement[0]); |
| } |
| |
| /* ATTRIBUTE GROUPS ===============================================*/ |
| |
| SchemaAttributeGroupImpl findAttributeGroup(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaAttributeGroupImpl result = (SchemaAttributeGroupImpl) _attributeGroups.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaAttributeGroupImpl) _importingLoader.findAttributeGroup(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| SchemaAttributeGroupImpl findRedefinedAttributeGroup(QName name, String chameleonNamespace, SchemaAttributeGroupImpl redefinedBy) { |
| QName redefinitionFor = redefinedBy.getName(); |
| name = compatName(name, chameleonNamespace); |
| if (name.equals(redefinitionFor)) { |
| return (SchemaAttributeGroupImpl) _redefinedAttributeGroups.get(redefinedBy); |
| // BUGBUG: should also link against _importingLoader.findRedefinedAttributeGroup |
| } |
| SchemaAttributeGroupImpl result = (SchemaAttributeGroupImpl) _attributeGroups.get(name); |
| if (result == null) { |
| result = (SchemaAttributeGroupImpl) _importingLoader.findAttributeGroup(name); |
| } |
| return result; |
| } |
| |
| void addAttributeGroup(SchemaAttributeGroupImpl attributeGroup, SchemaAttributeGroupImpl redefined) { |
| if (attributeGroup != null) { |
| QName name = attributeGroup.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == attributeGroup.getContainer(); |
| if (redefined != null) { |
| if (_redefinedAttributeGroups.containsKey(redefined)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"attribute group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedAttributeGroups.get(redefined)).getSourceName()}, |
| attributeGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"attribute group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedAttributeGroups.get(redefined)).getSourceName()}, |
| attributeGroup.getParseObject()); |
| } |
| } |
| } else { |
| _redefinedAttributeGroups.put(redefined, attributeGroup); |
| container.addRedefinedAttributeGroup(attributeGroup.getRef()); |
| } |
| } else { |
| if (_attributeGroups.containsKey(name)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"attribute group", QNameHelper.pretty(name), _attributeGroups.get(name).getSourceName()}, |
| attributeGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"attribute group", QNameHelper.pretty(name), _attributeGroups.get(name).getSourceName()}, |
| attributeGroup.getParseObject()); |
| } |
| } |
| } else { |
| _attributeGroups.put(attributeGroup.getName(), attributeGroup); |
| addSpelling(attributeGroup.getName(), attributeGroup); |
| container.addAttributeGroup(attributeGroup.getRef()); |
| } |
| } |
| } |
| } |
| |
| SchemaAttributeGroup[] attributeGroups() { |
| return _attributeGroups.values().toArray(new SchemaAttributeGroup[0]); |
| } |
| |
| SchemaAttributeGroup[] redefinedAttributeGroups() { |
| return (SchemaAttributeGroup[]) _redefinedAttributeGroups.values().toArray(new SchemaAttributeGroup[0]); |
| } |
| |
| /* MODEL GROUPS ===================================================*/ |
| |
| SchemaModelGroupImpl findModelGroup(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| SchemaModelGroupImpl result = (SchemaModelGroupImpl) _modelGroups.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) { |
| result = (SchemaModelGroupImpl) _importingLoader.findModelGroup(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return result; |
| } |
| |
| SchemaModelGroupImpl findRedefinedModelGroup(QName name, String chameleonNamespace, SchemaModelGroupImpl redefinedBy) { |
| QName redefinitionFor = redefinedBy.getName(); |
| name = compatName(name, chameleonNamespace); |
| if (name.equals(redefinitionFor)) { |
| return (SchemaModelGroupImpl) _redefinedModelGroups.get(redefinedBy); |
| // BUGBUG: should also link against _importingLoader.findRedefinedModelGroup |
| } |
| SchemaModelGroupImpl result = (SchemaModelGroupImpl) _modelGroups.get(name); |
| if (result == null) { |
| result = (SchemaModelGroupImpl) _importingLoader.findModelGroup(name); |
| } |
| return result; |
| } |
| |
| void addModelGroup(SchemaModelGroupImpl modelGroup, SchemaModelGroupImpl redefined) { |
| if (modelGroup != null) { |
| QName name = modelGroup.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == modelGroup.getContainer(); |
| if (redefined != null) { |
| if (_redefinedModelGroups.containsKey(redefined)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"model group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedModelGroups.get(redefined)).getSourceName()}, |
| modelGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"model group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedModelGroups.get(redefined)).getSourceName()}, |
| modelGroup.getParseObject()); |
| } |
| } |
| } else { |
| _redefinedModelGroups.put(redefined, modelGroup); |
| container.addRedefinedModelGroup(modelGroup.getRef()); |
| } |
| } else { |
| if (_modelGroups.containsKey(name)) { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"model group", QNameHelper.pretty(name), _modelGroups.get(name).getSourceName()}, |
| modelGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"model group", QNameHelper.pretty(name), _modelGroups.get(name).getSourceName()}, |
| modelGroup.getParseObject()); |
| } |
| } |
| } else { |
| _modelGroups.put(modelGroup.getName(), modelGroup); |
| addSpelling(modelGroup.getName(), modelGroup); |
| container.addModelGroup(modelGroup.getRef()); |
| } |
| } |
| } |
| } |
| |
| SchemaModelGroup[] modelGroups() { |
| return _modelGroups.values().toArray(new SchemaModelGroup[0]); |
| } |
| |
| SchemaModelGroup[] redefinedModelGroups() { |
| return (SchemaModelGroup[]) _redefinedModelGroups.values().toArray(new SchemaModelGroup[0]); |
| } |
| |
| /* IDENTITY CONSTRAINTS ===========================================*/ |
| |
| SchemaIdentityConstraintImpl findIdConstraint(QName name, String chameleonNamespace, String sourceNamespace) { |
| name = compatName(name, chameleonNamespace); |
| if (sourceNamespace != null) { |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| } |
| return (SchemaIdentityConstraintImpl) _idConstraints.get(name); |
| } |
| |
| void addIdConstraint(SchemaIdentityConstraintImpl idc) { |
| if (idc != null) { |
| QName name = idc.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == idc.getContainer(); |
| if (_idConstraints.containsKey(name)) { |
| if (!ignoreMdef(name)) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[]{"identity constraint", QNameHelper.pretty(name), _idConstraints.get(name).getSourceName()}, |
| idc.getParseObject()); |
| } |
| } else { |
| _idConstraints.put(name, idc); |
| addSpelling(idc.getName(), idc); |
| container.addIdentityConstraint(idc.getRef()); |
| } |
| } |
| } |
| |
| SchemaIdentityConstraintImpl[] idConstraints() { |
| return _idConstraints.values().toArray(new SchemaIdentityConstraintImpl[0]); |
| } |
| |
| /* ANNOTATIONS ===========================================*/ |
| |
| void addAnnotation(SchemaAnnotationImpl ann, String targetNamespace) { |
| if (ann != null) { |
| SchemaContainer container = getContainer(targetNamespace); |
| assert container != null && container == ann.getContainer(); |
| _annotations.add(ann); |
| container.addAnnotation(ann); |
| } |
| } |
| |
| List<SchemaAnnotation> annotations() { |
| return _annotations; |
| } |
| |
| /* RECURSION AVOIDANCE ============================================*/ |
| boolean isProcessing(SchemaComponent obj) { |
| return _processingGroups.contains(obj); |
| } |
| |
| void startProcessing(SchemaComponent obj) { |
| assert (!_processingGroups.contains(obj)); |
| _processingGroups.add(obj); |
| } |
| |
| void finishProcessing(SchemaComponent obj) { |
| assert (_processingGroups.contains(obj)); |
| _processingGroups.remove(obj); |
| } |
| |
| SchemaComponent[] getCurrentProcessing() { |
| return _processingGroups.toArray(new SchemaComponent[0]); |
| } |
| |
| /* JAVAIZATION ====================================================*/ |
| |
| Map<String, SchemaType> typesByClassname() { |
| return Collections.unmodifiableMap(_typesByClassname); |
| } |
| |
| void addClassname(String classname, SchemaType type) { |
| _typesByClassname.put(classname, type); |
| } |
| |
| |
| /** |
| * Stack management if (heaven help us) we ever need to do |
| * nested compilation of schema type system. |
| */ |
| private static final class StscStack { |
| StscState current; |
| List<StscState> stack = new ArrayList<>(); |
| |
| final StscState push() { |
| stack.add(current); |
| current = new StscState(); |
| return current; |
| } |
| |
| final void pop() { |
| current = stack.get(stack.size() - 1); |
| stack.remove(stack.size() - 1); |
| } |
| } |
| |
| public static void clearThreadLocals() { |
| tl_stscStack.remove(); |
| } |
| |
| public static StscState start() { |
| StscStack stscStack = tl_stscStack.get(); |
| |
| if (stscStack == null) { |
| stscStack = new StscStack(); |
| tl_stscStack.set(stscStack); |
| } |
| return stscStack.push(); |
| } |
| |
| public static StscState get() { |
| return tl_stscStack.get().current; |
| } |
| |
| public static void end() { |
| StscStack stscStack = tl_stscStack.get(); |
| stscStack.pop(); |
| if (stscStack.stack.size() == 0) { |
| tl_stscStack.set(null); // this is required to release all the references in this classloader |
| } |
| // which will enable class unloading and avoid OOM in PermGen |
| } |
| |
| |
| static XmlValueRef build_wsstring(int wsr) { |
| switch (wsr) { |
| case SchemaType.WS_PRESERVE: |
| return XMLSTR_PRESERVE; |
| case SchemaType.WS_REPLACE: |
| return XMLSTR_REPLACE; |
| case SchemaType.WS_COLLAPSE: |
| return XMLSTR_COLLAPSE; |
| } |
| return null; |
| } |
| |
| static XmlValueRef buildString(String str) { |
| if (str == null) { |
| return null; |
| } |
| |
| try { |
| XmlStringImpl i = new XmlStringImpl(); |
| i.set(str); |
| i.setImmutable(); |
| return new XmlValueRef(i); |
| } catch (XmlValueOutOfRangeException e) { |
| return null; |
| } |
| } |
| |
| public void notFoundError(QName itemName, int code, XmlObject loc, boolean recovered) { |
| String expected; |
| String expectedName = QNameHelper.pretty(itemName); |
| String found = null; |
| String foundName = null; |
| String sourceName = null; |
| |
| if (recovered) { |
| _recoveredErrors++; |
| } |
| |
| switch (code) { |
| case SchemaType.TYPE: |
| expected = "type"; |
| break; |
| case SchemaType.ELEMENT: |
| expected = "element"; |
| break; |
| case SchemaType.ATTRIBUTE: |
| expected = "attribute"; |
| break; |
| case SchemaType.MODEL_GROUP: |
| expected = "model group"; |
| break; |
| case SchemaType.ATTRIBUTE_GROUP: |
| expected = "attribute group"; |
| break; |
| case SchemaType.IDENTITY_CONSTRAINT: |
| expected = "identity constraint"; |
| break; |
| default: |
| assert (false); |
| expected = "definition"; |
| break; |
| } |
| |
| SchemaComponent foundComponent = findSpelling(itemName); |
| QName name; |
| if (foundComponent != null) { |
| name = foundComponent.getName(); |
| if (name != null) { |
| switch (foundComponent.getComponentType()) { |
| case SchemaComponent.TYPE: |
| found = "type"; |
| sourceName = foundComponent.getSourceName(); |
| break; |
| case SchemaComponent.ELEMENT: |
| found = "element"; |
| sourceName = foundComponent.getSourceName(); |
| break; |
| case SchemaComponent.ATTRIBUTE: |
| found = "attribute"; |
| sourceName = foundComponent.getSourceName(); |
| break; |
| case SchemaComponent.ATTRIBUTE_GROUP: |
| found = "attribute group"; |
| break; |
| case SchemaComponent.MODEL_GROUP: |
| found = "model group"; |
| break; |
| } |
| |
| if (sourceName != null) { |
| sourceName = sourceName.substring(sourceName.lastIndexOf('/') + 1); |
| } |
| |
| if (!name.equals(itemName)) { |
| foundName = QNameHelper.pretty(name); |
| } |
| } |
| } |
| |
| if (found == null) { |
| // error with no help |
| error(XmlErrorCodes.SCHEMA_QNAME_RESOLVE, |
| new Object[]{expected, expectedName}, loc); |
| } else { |
| // error with help |
| error(XmlErrorCodes.SCHEMA_QNAME_RESOLVE$HELP, |
| new Object[]{ |
| expected, |
| expectedName, |
| found, |
| (foundName == null ? new Integer(0) : new Integer(1)), |
| foundName, |
| (sourceName == null ? new Integer(0) : new Integer(1)), |
| sourceName |
| }, |
| loc); |
| } |
| } |
| |
| |
| /** |
| * Produces the "sourceName" (to be used within the schema project |
| * source file copies) from the URI of the original source. |
| * <p> |
| * Returns null if none. |
| */ |
| public String sourceNameForUri(String uri) { |
| return _sourceForUri.get(uri); |
| } |
| |
| /** |
| * Returns the whole sourceCopyMap, mapping URI's that have |
| * been read to "sourceName" local names that have been used |
| * to tag the types. |
| */ |
| public Map<String, String> sourceCopyMap() { |
| return Collections.unmodifiableMap(_sourceForUri); |
| } |
| |
| /** |
| * The base URI to use for nice filenames when saving sources. |
| */ |
| public void setBaseUri(URI uri) { |
| _baseURI = uri; |
| } |
| |
| public String relativize(String uri) { |
| return relativize(uri, false); |
| } |
| |
| public String computeSavedFilename(String uri) { |
| return relativize(uri, true); |
| } |
| |
| private String relativize(String uri, boolean forSavedFilename) { |
| if (uri == null) { |
| return null; |
| } |
| |
| // deal with things that do not look like absolute uris |
| if (uri.startsWith("/")) { |
| uri = PROJECT_URL_PREFIX + uri.replace('\\', '/'); |
| } else { |
| // looks like a URL? |
| int colon = uri.indexOf(':'); |
| if (colon <= 1 || !uri.substring(0, colon).matches("^\\w+$")) { |
| uri = PROJECT_URL_PREFIX + "/" + uri.replace('\\', '/'); |
| } |
| } |
| |
| // now relativize against that... |
| if (_baseURI != null) { |
| try { |
| URI relative = _baseURI.relativize(new URI(uri)); |
| if (!relative.isAbsolute()) { |
| return relative.toString(); |
| } else { |
| uri = relative.toString(); |
| } |
| } catch (URISyntaxException e) { |
| } |
| } |
| |
| if (!forSavedFilename) { |
| return uri; |
| } |
| |
| int lastslash = uri.lastIndexOf('/'); |
| String dir = QNameHelper.hexsafe(lastslash == -1 ? "" : uri.substring(0, lastslash)); |
| |
| int question = uri.indexOf('?', lastslash + 1); |
| if (question == -1) { |
| return dir + "/" + uri.substring(lastslash + 1); |
| } |
| |
| String query = QNameHelper.hexsafe(uri.substring(question)); |
| |
| // if encoded query part is longer than 64 characters, just drop it |
| if (query.startsWith(QNameHelper.URI_SHA1_PREFIX)) { |
| return dir + "/" + uri.substring(lastslash + 1, question); |
| } else { |
| return dir + "/" + uri.substring(lastslash + 1, question) + query; |
| } |
| } |
| |
| /** |
| * Notes another URI that has been consumed during compilation |
| * (this is the URI that is in the document .NAME property) |
| */ |
| public void addSourceUri(String uri, String nameToUse) { |
| if (uri == null) { |
| return; |
| } |
| |
| if (nameToUse == null) { |
| nameToUse = computeSavedFilename(uri); |
| } |
| |
| _sourceForUri.put(uri, nameToUse); |
| } |
| |
| /** |
| * Returns the error listener being filled in during this compilation |
| */ |
| public Collection<XmlError> getErrorListener() { |
| return _errorListener; |
| } |
| |
| /** |
| * Returns the schema type loader to use for processing s4s |
| */ |
| public SchemaTypeLoader getS4SLoader() { |
| return _s4sloader; |
| } |
| |
| public File getSchemasDir() { |
| return _schemasDir; |
| } |
| |
| public void setSchemasDir(File _schemasDir) { |
| this._schemasDir = _schemasDir; |
| } |
| } |