|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package javax.xml.catalog; |
|
|
|
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; |
|
import java.io.IOException; |
|
import java.net.MalformedURLException; |
|
import java.net.URI; |
|
import java.net.URISyntaxException; |
|
import java.net.URL; |
|
import java.util.ArrayList; |
|
import java.util.HashMap; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.NoSuchElementException; |
|
import java.util.Spliterator; |
|
import java.util.Spliterators; |
|
import java.util.stream.Stream; |
|
import java.util.stream.StreamSupport; |
|
import static javax.xml.catalog.BaseEntry.CatalogEntryType; |
|
import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE; |
|
import javax.xml.catalog.CatalogFeatures.Feature; |
|
import static javax.xml.catalog.CatalogMessages.formatMessage; |
|
import javax.xml.parsers.ParserConfigurationException; |
|
import javax.xml.parsers.SAXParser; |
|
import javax.xml.parsers.SAXParserFactory; |
|
import org.xml.sax.SAXException; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
class CatalogImpl extends GroupEntry implements Catalog { |
|
|
|
|
|
int level = 0; |
|
|
|
|
|
boolean isDeferred = true; |
|
|
|
|
|
ResolveType resolveType = ResolveType.STRICT; |
|
|
|
|
|
boolean isEmpty; |
|
|
|
|
|
int current = 0; |
|
|
|
|
|
String systemId; |
|
|
|
|
|
|
|
|
|
*/ |
|
List<String> inputFiles; |
|
|
|
|
|
List<NextCatalog> nextCatalogs; |
|
|
|
|
|
SAXParser parser; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public CatalogImpl(CatalogFeatures f, URI... uris) throws CatalogException { |
|
this(null, f, uris); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public CatalogImpl(CatalogImpl parent, CatalogFeatures f, URI... uris) throws CatalogException { |
|
super(CatalogEntryType.CATALOG, parent); |
|
if (f == null) { |
|
throw new NullPointerException( |
|
formatMessage(CatalogMessages.ERR_NULL_ARGUMENT, new Object[]{"CatalogFeatures"})); |
|
} |
|
|
|
init(f); |
|
|
|
|
|
String[] catalogFile = null; |
|
if (level == 0 && uris.length == 0) { |
|
String files = features.get(Feature.FILES); |
|
if (files != null) { |
|
catalogFile = files.split(";"); |
|
} |
|
} else { |
|
catalogFile = new String[uris.length]; |
|
for (int i=0; i<uris.length; i++) { |
|
catalogFile[i] = uris[i].toASCIIString(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
if ((catalogFile != null && catalogFile.length > 0)) { |
|
int start = 0; |
|
URI uri = null; |
|
for (String temp : catalogFile) { |
|
uri = URI.create(temp); |
|
start++; |
|
if (verifyCatalogFile(null, uri)) { |
|
systemId = temp; |
|
try { |
|
baseURI = new URL(systemId); |
|
} catch (MalformedURLException e) { |
|
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_INVALID_PATH, |
|
new Object[]{temp}, e); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
|
|
if (level == 0 && catalogFile.length > start) { |
|
inputFiles = new ArrayList<>(); |
|
for (int i = start; i < catalogFile.length; i++) { |
|
if (catalogFile[i] != null) { |
|
inputFiles.add(catalogFile[i]); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
void load() { |
|
if (systemId != null) { |
|
parse(systemId); |
|
} |
|
|
|
setCatalog(this); |
|
|
|
|
|
loadedCatalogs.put(systemId, this); |
|
|
|
|
|
if (!isDeferred()) { |
|
loadDelegateCatalogs(this); |
|
loadNextCatalogs(); |
|
} |
|
} |
|
|
|
private void init(CatalogFeatures f) { |
|
if (parent == null) { |
|
level = 0; |
|
} else { |
|
level = parent.level + 1; |
|
this.loadedCatalogs = parent.loadedCatalogs; |
|
this.catalogsSearched = parent.catalogsSearched; |
|
} |
|
if (f == null) { |
|
this.features = CatalogFeatures.defaults(); |
|
} else { |
|
this.features = f; |
|
} |
|
setPrefer(features.get(Feature.PREFER)); |
|
setDeferred(features.get(Feature.DEFER)); |
|
setResolve(features.get(Feature.RESOLVE)); |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public void reset() { |
|
super.reset(); |
|
current = 0; |
|
if (level == 0) { |
|
catalogsSearched.clear(); |
|
} |
|
entries.stream().filter((entry) -> (entry.type == CatalogEntryType.GROUP)).forEach((entry) -> { |
|
((GroupEntry) entry).reset(); |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
boolean isTop() { |
|
return level == 0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Catalog getParent() { |
|
return this.parent; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setDeferred(String value) { |
|
isDeferred = DEFER_TRUE.equals(value); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isDeferred() { |
|
return isDeferred; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setResolve(String value) { |
|
resolveType = ResolveType.getType(value); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final ResolveType getResolve() { |
|
return resolveType; |
|
} |
|
|
|
|
|
|
|
*/ |
|
void markAsSearched() { |
|
catalogsSearched.add(systemId); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void parse(String systemId) { |
|
if (parser == null) { |
|
parser = getParser(); |
|
} |
|
|
|
try { |
|
CatalogReader reader = new CatalogReader(this, parser); |
|
parser.parse(systemId, reader); |
|
} catch (SAXException | IOException ex) { |
|
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSING_FAILED, ex); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private SAXParser getParser() { |
|
SAXParser p = null; |
|
try { |
|
SAXParserFactory spf = new SAXParserFactoryImpl(); |
|
spf.setNamespaceAware(true); |
|
spf.setValidating(false); |
|
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); |
|
p = spf.newSAXParser(); |
|
} catch (ParserConfigurationException | SAXException e) { |
|
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSING_FAILED, e); |
|
} |
|
return p; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean isEmpty() { |
|
return isEmpty; |
|
} |
|
|
|
@Override |
|
public Stream<Catalog> catalogs() { |
|
Iterator<Catalog> iter = new Iterator<Catalog>() { |
|
Catalog nextCatalog = null; |
|
|
|
|
|
int inputFilesIndex = 0; |
|
|
|
|
|
int nextCatalogIndex = 0; |
|
|
|
@Override |
|
public boolean hasNext() { |
|
if (nextCatalog != null) { |
|
return true; |
|
} else { |
|
nextCatalog = nextCatalog(); |
|
return (nextCatalog != null); |
|
} |
|
} |
|
|
|
@Override |
|
public Catalog next() { |
|
if (nextCatalog != null || hasNext()) { |
|
Catalog catalog = nextCatalog; |
|
nextCatalog = null; |
|
return catalog; |
|
} else { |
|
throw new NoSuchElementException(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private Catalog nextCatalog() { |
|
Catalog c = null; |
|
|
|
|
|
if (nextCatalogs != null) { |
|
while (c == null && nextCatalogIndex < nextCatalogs.size()) { |
|
c = getCatalog(catalog, |
|
nextCatalogs.get(nextCatalogIndex++).getCatalogURI()); |
|
} |
|
} |
|
|
|
|
|
if (c == null && inputFiles != null) { |
|
while (c == null && inputFilesIndex < inputFiles.size()) { |
|
c = getCatalog(null, |
|
URI.create(inputFiles.get(inputFilesIndex++))); |
|
} |
|
} |
|
|
|
return c; |
|
} |
|
}; |
|
|
|
return StreamSupport.stream(Spliterators.spliteratorUnknownSize( |
|
iter, Spliterator.ORDERED | Spliterator.NONNULL), false); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void addNextCatalog(NextCatalog catalog) { |
|
if (catalog == null) { |
|
return; |
|
} |
|
|
|
if (nextCatalogs == null) { |
|
nextCatalogs = new ArrayList<>(); |
|
} |
|
|
|
nextCatalogs.add(catalog); |
|
} |
|
|
|
|
|
|
|
*/ |
|
void loadNextCatalogs() { |
|
|
|
if (nextCatalogs != null) { |
|
nextCatalogs.stream().forEach((next) -> { |
|
getCatalog(this, next.getCatalogURI()); |
|
}); |
|
} |
|
|
|
|
|
if (inputFiles != null) { |
|
inputFiles.stream().forEach((uri) -> { |
|
getCatalog(null, URI.create(uri)); |
|
}); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Catalog getCatalog(CatalogImpl parent, URI uri) { |
|
if (uri == null) { |
|
return null; |
|
} |
|
|
|
CatalogImpl c = null; |
|
|
|
if (verifyCatalogFile(parent, uri)) { |
|
c = getLoadedCatalog(uri.toASCIIString()); |
|
if (c == null) { |
|
c = new CatalogImpl(this, features, uri); |
|
c.load(); |
|
} |
|
} |
|
return c; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void saveLoadedCatalog(String catalogId, CatalogImpl c) { |
|
loadedCatalogs.put(catalogId, c); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
int loadedCatalogCount() { |
|
return loadedCatalogs.size(); |
|
} |
|
} |