Skip to content

Commit

Permalink
Refactored input stream handling. Input streams should now be properl…
Browse files Browse the repository at this point in the history
…y closed.
  • Loading branch information
david-waltermire committed Aug 15, 2023
1 parent 6c24149 commit f9e2fb8
Show file tree
Hide file tree
Showing 45 changed files with 2,042 additions and 1,495 deletions.
5 changes: 5 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@
<!-- <version>0.3.2</version> -->
<!-- <scope>test</scope> -->
<!-- </dependency> -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.hosuaby</groupId>
<artifactId>inject-resources-junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* Provides a basic configuration management implementation that allows mutable access to
* configuration state.
* Provides a basic configuration management implementation that allows mutable
* access to configuration state.
*
* @param <T>
* the type of managed features
Expand Down Expand Up @@ -112,16 +112,6 @@ public IMutableConfiguration<T> applyConfiguration(@NonNull IConfiguration<T> or
return this;
}

@SuppressWarnings("unchecked")
@Override
public <V> V get(T feature) {
V value = (V) featureValues.get(feature);
if (value == null) {
value = (V) feature.getDefault();
}
return value;
}

@Override
public IMutableConfiguration<T> set(T feature, Object value) {
Class<?> featureValueClass = feature.getValueClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* The base interface for getting the configuration of processors and parsers in this library. This
* provides an immutable view of the current configuration.
* The base interface for getting the configuration of processors and parsers in
* this library. This provides an immutable view of the current configuration.
*
* @param <T>
* the type of the feature set
Expand All @@ -59,8 +59,15 @@ public interface IConfiguration<T extends IConfigurationFeature<?>> {
* the requested feature
* @return the value of the feature
*/
@SuppressWarnings("unchecked")
@NonNull
<V> V get(@NonNull T feature);
default <V> V get(@NonNull T feature) {
V value = (V) getFeatureValues().get(feature);
if (value == null) {
value = (V) feature.getDefault();
}
return value;
}

/**
* Get the mapping of each feature mapped to its value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
* The common interface that all configuration features must implement.
* <p>
* This approach is inspired by the configuration implementation in the
* <a href="https://github.com/FasterXML/jackson-databind">Jackson databind library</a>.
* <a href="https://github.com/FasterXML/jackson-databind">Jackson databind
* library</a>.
*
* @param <V>
* the value type of the feature
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@
import gov.nist.secauto.metaschema.core.metapath.function.DefaultFunction.CallingContext;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.model.IUriResolver;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
Expand All @@ -49,7 +50,6 @@
import java.util.concurrent.ConcurrentHashMap;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

public class DynamicContext { // NOPMD - intentional data class
@NonNull
Expand Down Expand Up @@ -131,6 +131,19 @@ public void cacheResult(@NonNull CallingContext callingContext, @NonNull ISequen
assert old == null;
}

@NonNull
public ISequence<?> getVariableValue(String name) {
return ObjectUtils.requireNonNull(letVariableMap.get(name));
}

public void setVariableValue(String name, ISequence<?> boundValue) {
letVariableMap.put(name, boundValue);
}

public void clearVariableValue(String name) {
letVariableMap.remove(name);
}

private class CachingLoader implements IDocumentLoader {
@NonNull
private final IDocumentLoader proxy;
Expand All @@ -140,86 +153,83 @@ public CachingLoader(@NonNull IDocumentLoader proxy) {
}

@Override
public @Nullable EntityResolver getEntityResolver() {
return new ContextEntityResolver();
public IUriResolver getUriResolver() {
return new ContextUriResolver();
}

@Override
public void setEntityResolver(@NonNull EntityResolver resolver) {
public void setUriResolver(@NonNull IUriResolver resolver) {
// we delegate to the document loader proxy, so the resolver should be set there
throw new UnsupportedOperationException("Set the resolver on the proxy");
}

@NonNull
protected IDocumentLoader getProxiedDocumentLoader() {
return proxy;
}

@Override
public @NonNull IDocumentNodeItem loadAsNodeItem(@NonNull InputSource source) throws IOException {
String systemId = source.getSystemId();
URI uri = ObjectUtils.notNull(URI.create(systemId));
public IDocumentNodeItem loadAsNodeItem(Path path) throws IOException {
URI uri = path.toUri();
IDocumentNodeItem retval = availableDocuments.get(uri);
if (retval == null) {
retval = getProxiedDocumentLoader().loadAsNodeItem(path);
availableDocuments.put(uri, retval);
}
return retval;
}

@Override
public IDocumentNodeItem loadAsNodeItem(URL url) throws IOException, URISyntaxException {
URI uri = ObjectUtils.notNull(url.toURI());
IDocumentNodeItem retval = availableDocuments.get(uri);
if (retval == null) {
retval = getProxiedDocumentLoader().loadAsNodeItem(uri);
availableDocuments.put(uri, retval);
}
return retval;
}

@Override
public IDocumentNodeItem loadAsNodeItem(URI uri) throws IOException {
IDocumentNodeItem retval = availableDocuments.get(uri);
if (retval == null) {
retval = getProxiedDocumentLoader().loadAsNodeItem(source);
retval = getProxiedDocumentLoader().loadAsNodeItem(uri);
availableDocuments.put(uri, retval);
}
return retval;
}

public class ContextEntityResolver implements EntityResolver {
@Override
public @NonNull IDocumentNodeItem loadAsNodeItem(
@NonNull InputStream is,
@NonNull URI documentUri) throws IOException {
throw new UnsupportedOperationException();
// return getProxiedDocumentLoader().loadAsNodeItem(is, documentUri);
}

public class ContextUriResolver implements IUriResolver {

/**
* Provides an {@link InputSource} for the provided {@code systemId} after attempting to resolve
* this system identifier.
* {@inheritDoc}
* <p>
* This implementation of an {@link EntityResolver} will perform the following operations in order:
* <ol>
* <li>Resolves the {@code systemId} against the base URI provided by the
* {@link StaticContext#getBaseUri()} method, if this method returns a non-{@code null} result, to
* get a localized resource identifier.</li>
* <li>It will then delegate to the EntityResolver provided by the
* {@link IDocumentLoader#getEntityResolver()} method, if the result is not-{@code null}, to get the
* {@link InputSource}.</li>
* <li>If no InputSource is provided by the previous step, then an InputSource will be created from
* the URI resolved in the first step, if possible.
* <li>If an InputSource is still not provided, then an InputSource will be created from the
* provided {@code systemId}.
* </ol>
* This method first resolves the provided URI against the static context's base
* URI.
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
public URI resolve(URI uri) {
URI baseUri = getStaticContext().getBaseUri();

String uri;
URI resolvedUri;
if (baseUri == null) {
uri = systemId;
resolvedUri = uri;
} else {
URI resolvedUri = baseUri.resolve(systemId);
uri = resolvedUri.toASCIIString();
}

EntityResolver resolver = getProxiedDocumentLoader().getEntityResolver();
InputSource retval = resolver == null ? null : resolver.resolveEntity(null, uri);
if (retval == null) {
retval = new InputSource(uri);
resolvedUri = ObjectUtils.notNull(baseUri.resolve(uri));
}

return retval;
IUriResolver resolver = getProxiedDocumentLoader().getUriResolver();
return resolver == null ? resolvedUri : resolver.resolve(resolvedUri);
}

}
}

@NonNull
public ISequence<?> getVariableValue(String name) {
return ObjectUtils.requireNonNull(letVariableMap.get(name));
}

public void setVariableValue(String name, ISequence<?> boundValue) {
letVariableMap.put(name, boundValue);
}

public void clearVariableValue(String name) {
letVariableMap.remove(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,47 +28,43 @@

import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.model.IResourceLoader;
import gov.nist.secauto.metaschema.core.model.IUriResolver;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;

import edu.umd.cs.findbugs.annotations.NonNull;

public interface IDocumentLoader extends IResourceLoader {
void setEntityResolver(@NonNull EntityResolver resolver);
void setUriResolver(@NonNull IUriResolver resolver);

@NonNull
default IDocumentNodeItem loadAsNodeItem(@NonNull URL url) throws IOException, URISyntaxException {
return loadAsNodeItem(toInputSource(ObjectUtils.notNull(url.toURI())));
default IDocumentNodeItem loadAsNodeItem(@NonNull File file) throws IOException {
return loadAsNodeItem(ObjectUtils.notNull(file.toPath()));
}

@NonNull
default IDocumentNodeItem loadAsNodeItem(@NonNull Path path) throws IOException {
return loadAsNodeItem(toInputSource(ObjectUtils.notNull(path.toUri())));
try (InputStream is = ObjectUtils.notNull(Files.newInputStream(path))) {
return loadAsNodeItem(is, ObjectUtils.notNull(path.toUri()));
}
}

@NonNull
default IDocumentNodeItem loadAsNodeItem(@NonNull File file) throws IOException {
return loadAsNodeItem(toInputSource(ObjectUtils.notNull(file.toPath().toUri())));
default IDocumentNodeItem loadAsNodeItem(@NonNull URL url) throws IOException, URISyntaxException {
return loadAsNodeItem(ObjectUtils.notNull(url.toURI()));
}

@NonNull
default IDocumentNodeItem loadAsNodeItem(@NonNull InputStream is, @NonNull URI documentUri) throws IOException {
InputSource source = toInputSource(documentUri);
source.setByteStream(is);
// TODO: deal with charset?
return loadAsNodeItem(source);
}
IDocumentNodeItem loadAsNodeItem(@NonNull URI uri) throws IOException;

@NonNull
IDocumentNodeItem loadAsNodeItem(@NonNull InputSource source) throws IOException;
IDocumentNodeItem loadAsNodeItem(@NonNull InputStream is, @NonNull URI documentUri) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import edu.umd.cs.findbugs.annotations.NonNull;
Expand Down Expand Up @@ -82,10 +81,11 @@ private static ISequence<IDocumentNodeItem> execute(@NonNull IFunction function,
}

/**
* Dynamically load the document associated with the URI, and return a {@link IDocumentNodeItem}
* containing the result.
* Dynamically load the document associated with the URI, and return a
* {@link IDocumentNodeItem} containing the result.
* <p>
* Based on the XPath 3.1 <a href="https://www.w3.org/TR/xpath-functions-31/#func-doc">fn:doc</a>
* Based on the XPath 3.1
* <a href="https://www.w3.org/TR/xpath-functions-31/#func-doc">fn:doc</a>
* function.
*
* @param uri
Expand Down Expand Up @@ -115,8 +115,8 @@ public static IDocumentNodeItem fnDoc(@NonNull IStringItem uri, @NonNull Dynamic
}

try {
return context.getDocumentLoader().loadAsNodeItem(ObjectUtils.notNull(documentUri.toURL()));
} catch (IOException | URISyntaxException ex) {
return context.getDocumentLoader().loadAsNodeItem(ObjectUtils.notNull(documentUri));
} catch (IOException ex) {
throw new DocumentFunctionException(DocumentFunctionException.ERROR_RETRIEVING_RESOURCE, String
.format("Unable to retrieve the resource identified by the URI '%s'.", documentUri.toString()), ex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ public interface IItem {
/**
* Get the item's "wrapped" value. This "wrapped" value may be:
* <ul>
* <li>In the case of an Assembly, a Java object representing the fields and flags of the
* assembly.</li>
* <li>In the case of a Field with flags, a Java object representing the field value and flags of
* the field.
* <li>In the case of an Assembly, a Java object representing the fields and
* flags of the assembly.</li>
* <li>In the case of a Field with flags, a Java object representing the field
* value and flags of the field.
* <li>In the case of a Field without flags or a flag, a Java type managed by a
* {@link IDataTypeAdapter} or a primitive type provided by the Java standard library.
* {@link IDataTypeAdapter} or a primitive type provided by the Java standard
* library.
* </ul>
*
* @return the value or {@code null} if the item has no available value
Expand All @@ -47,7 +48,8 @@ public interface IItem {
/**
* Determine if the item has an associated value.
*
* @return {@code true} if the item has a non-{@code null} value or {@code false} otherwise
* @return {@code true} if the item has a non-{@code null} value or
* {@code false} otherwise
*/
default boolean hasValue() {
return getValue() != null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ default String asString() {
}

/**
* Get a new {@link IStringItem} based on the the textual value of the item's "wrapped" value.
* Get a new {@link IStringItem} based on the the textual value of the item's
* "wrapped" value.
*
* @return a new string item
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,7 @@ static IDecimalItem valueOf(@NonNull String value) {
throws InvalidValueForCastFunctionException {
return MetaschemaDataTypeProvider.DECIMAL.cast(item);
}

@Override
BigDecimal getValue();
}
Loading

0 comments on commit f9e2fb8

Please sign in to comment.