b3cbb31f193d13263145008821c96570f3646ab5
[netconf.git] / restconf / restconf-openapi / src / main / java / org / opendaylight / restconf / openapi / impl / ComponentsStream.java
1 /*
2  * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.restconf.openapi.impl;
9
10 import com.fasterxml.jackson.core.JsonGenerator;
11 import java.io.ByteArrayInputStream;
12 import java.io.ByteArrayOutputStream;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.InputStreamReader;
16 import java.io.Reader;
17 import java.nio.charset.StandardCharsets;
18 import java.util.Iterator;
19 import java.util.Map;
20 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
21 import org.opendaylight.restconf.openapi.model.security.Http;
22 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
23 import org.opendaylight.yangtools.yang.model.api.Module;
24
25 public final class ComponentsStream extends InputStream {
26     private static final String BASIC_AUTH_NAME = "basicAuth";
27     private static final Http OPEN_API_BASIC_AUTH = new Http("basic", null, null);
28
29     private final Iterator<? extends Module> iterator;
30     private final OpenApiBodyWriter writer;
31     private final EffectiveModelContext context;
32     private final JsonGenerator generator;
33     private final ByteArrayOutputStream stream;
34     private final boolean isForSingleModule;
35
36     private boolean schemasWritten;
37     private boolean securityWritten;
38     private Reader reader;
39
40     public ComponentsStream(final EffectiveModelContext context, final OpenApiBodyWriter writer,
41         final JsonGenerator generator, final ByteArrayOutputStream stream,
42         final Iterator<? extends Module> iterator, final boolean isForSingleModule) {
43         this.iterator = iterator;
44         this.context = context;
45         this.writer = writer;
46         this.generator = generator;
47         this.stream = stream;
48         this.isForSingleModule = isForSingleModule;
49     }
50
51     @Override
52     public int read() throws IOException {
53         if (reader == null) {
54             generator.writeObjectFieldStart("components");
55             generator.flush();
56             reader = new InputStreamReader(new ByteArrayInputStream(stream.toByteArray()), StandardCharsets.UTF_8);
57             stream.reset();
58         }
59
60         var read = reader.read();
61         while (read == -1) {
62             if (!schemasWritten) {
63                 reader = new InputStreamReader(new SchemasStream(context, writer, generator, stream, iterator,
64                     isForSingleModule), StandardCharsets.UTF_8);
65                 read = reader.read();
66                 schemasWritten = true;
67                 continue;
68             }
69             if (!securityWritten) {
70                 reader = new InputStreamReader(new SecuritySchemesStream(writer, Map.of(BASIC_AUTH_NAME,
71                     OPEN_API_BASIC_AUTH)), StandardCharsets.UTF_8);
72                 read = reader.read();
73                 securityWritten = true;
74                 generator.writeEndObject();
75                 continue;
76             }
77             generator.flush();
78             reader = new InputStreamReader(new ByteArrayInputStream(stream.toByteArray()), StandardCharsets.UTF_8);
79             stream.reset();
80             return reader.read();
81         }
82         return read;
83     }
84
85     @Override
86     public int read(final byte[] array, final int off, final int len) throws IOException {
87         return super.read(array, off, len);
88     }
89 }