1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.oscal.lib;
28
29 import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream;
30
31 import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
32 import gov.nist.secauto.oscal.lib.model.BackMatter.Resource;
33 import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Base64;
34 import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Rlink;
35
36 import org.xml.sax.EntityResolver;
37 import org.xml.sax.InputSource;
38 import org.xml.sax.SAXException;
39
40 import java.io.IOException;
41 import java.net.URI;
42 import java.nio.ByteBuffer;
43 import java.util.List;
44 import java.util.UUID;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
47
48 import edu.umd.cs.findbugs.annotations.NonNull;
49 import edu.umd.cs.findbugs.annotations.Nullable;
50
51 public final class OscalUtils {
52 public static final String OSCAL_VERSION = "1.0.4";
53 private static final Pattern INTERNAL_REFERENCE_FRAGMENT_PATTERN = Pattern.compile("^#(.+)$");
54
55 private OscalUtils() {
56
57 }
58
59 @SuppressWarnings("PMD.OnlyOneReturn")
60 public static boolean isInternalReference(@NonNull URI uri) {
61 if (uri.isAbsolute()) {
62 return false;
63 }
64
65 String schemeSpecificPart = uri.getSchemeSpecificPart();
66 return uri.getScheme() == null && (schemeSpecificPart == null || schemeSpecificPart.isEmpty())
67 && uri.getFragment() != null;
68 }
69
70
71
72
73
74
75
76
77
78
79 @NonNull
80 public static String internalReferenceFragmentToId(@NonNull URI fragment) {
81 return internalReferenceFragmentToId(ObjectUtils.notNull(fragment.toString()));
82 }
83
84
85
86
87
88
89
90
91
92
93 @NonNull
94 public static String internalReferenceFragmentToId(@NonNull String fragment) {
95 Matcher matcher = INTERNAL_REFERENCE_FRAGMENT_PATTERN.matcher(fragment);
96 String retval;
97 if (matcher.matches()) {
98 retval = ObjectUtils.notNull(matcher.group(1));
99 } else {
100 throw new IllegalArgumentException(String.format("The fragment '%s' does not match the pattern '%s'", fragment,
101 INTERNAL_REFERENCE_FRAGMENT_PATTERN.pattern()));
102 }
103 return retval;
104 }
105
106 public static boolean hasBase64Data(@NonNull Resource resource) {
107 return resource.getBase64() != null;
108 }
109
110 @Nullable
111 public static ByteBuffer getBase64Data(@NonNull Resource resource) {
112 Base64 base64 = resource.getBase64();
113
114 ByteBuffer retval = null;
115 if (base64 != null) {
116 retval = base64.getValue();
117 }
118 return retval;
119 }
120
121 @Nullable
122 public static URI getResourceURI(@NonNull Resource resource, @Nullable String preferredMediaType) {
123 URI retval;
124 if (hasBase64Data(resource)) {
125 UUID uuid = resource.getUuid();
126 if (uuid == null) {
127 throw new IllegalArgumentException("resource has a null UUID");
128 }
129 retval = ObjectUtils.notNull(URI.create("#" + uuid));
130 } else {
131 Rlink rlink = findMatchingRLink(resource, preferredMediaType);
132 retval = rlink == null ? null : rlink.getHref();
133 }
134 return retval;
135 }
136
137 @Nullable
138 public static Rlink findMatchingRLink(@NonNull Resource resource, @Nullable String preferredMediaType) {
139
140 List<Rlink> rlinks = resource.getRlinks();
141
142 Rlink retval = null;
143 if (rlinks != null) {
144
145 if (preferredMediaType != null) {
146
147 retval = rlinks.stream().filter(rlink -> preferredMediaType.equals(rlink.getMediaType())).findFirst()
148 .orElse(null);
149 } else {
150
151 retval = rlinks.stream().findFirst().orElse(null);
152 }
153 }
154 return retval;
155 }
156
157 @Nullable
158 public static InputSource newInputSource(@NonNull Resource resource, @NonNull EntityResolver resolver,
159 @Nullable String preferredMediaType) throws IOException {
160 URI uri = getResourceURI(resource, preferredMediaType);
161 if (uri == null) {
162 throw new IOException(String.format("unable to determine URI for resource '%s'", resource.getUuid()));
163 }
164
165 InputSource retval;
166 try {
167 retval = resolver.resolveEntity(null, uri.toASCIIString());
168 } catch (SAXException ex) {
169 throw new IOException(ex);
170 }
171
172 if (hasBase64Data(resource)) {
173
174 ByteBuffer buffer = getBase64Data(resource);
175 if (buffer == null) {
176 throw new IOException(String.format("null base64 value for resource '%s'", resource.getUuid()));
177 }
178 retval.setByteStream(new ByteBufferBackedInputStream(buffer));
179 }
180 return retval;
181 }
182 }