* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
package org.opendaylight.netconf.sal.rest.impl;
import com.google.common.base.Preconditions;
-import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.gson.stream.JsonWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.xml.stream.XMLStreamWriter;
import org.opendaylight.netconf.sal.rest.api.Draft02;
import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
-import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
-import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
-import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.common.context.NormalizedNodeContext;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.restconf.common.errors.RestconfError;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
-import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactory;
+import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier;
import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.codec.gson.JsonWriterFactory;
import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@Context
private HttpHeaders headers;
+ private final ControllerContext controllerContext;
+
+ public RestconfDocumentedExceptionMapper(final ControllerContext controllerContext) {
+ this.controllerContext = Preconditions.checkNotNull(controllerContext);
+ }
+
@Override
public Response toResponse(final RestconfDocumentedException exception) {
LOG.debug("In toResponse: {}", exception.getMessage());
- final List<MediaType> accepts = headers.getAcceptableMediaTypes();
- accepts.remove(MediaType.WILDCARD_TYPE);
-
- LOG.debug("Accept headers: {}", accepts);
-
- final MediaType mediaType;
- if (accepts != null && accepts.size() > 0) {
- mediaType = accepts.get(0); // just pick the first one
- } else {
- // Default to the content type if there's no Accept header
- mediaType = MediaType.APPLICATION_JSON_TYPE;
+ final List<MediaType> mediaTypeList = new ArrayList<>();
+ if (headers.getMediaType() != null) {
+ mediaTypeList.add(headers.getMediaType());
}
+ mediaTypeList.addAll(headers.getAcceptableMediaTypes());
+ final MediaType mediaType = mediaTypeList.stream().filter(type -> !type.equals(MediaType.WILDCARD_TYPE))
+ .findFirst().orElse(MediaType.APPLICATION_JSON_TYPE);
+
LOG.debug("Using MediaType: {}", mediaType);
final List<RestconfError> errors = exception.getErrors();
final int status = errors.iterator().next().getErrorTag().getStatusCode();
- final ControllerContext context = ControllerContext.getInstance();
- final DataNodeContainer errorsSchemaNode = (DataNodeContainer) context.getRestconfModuleErrorsSchemaNode();
+ final DataNodeContainer errorsSchemaNode =
+ (DataNodeContainer) controllerContext.getRestconfModuleErrorsSchemaNode();
if (errorsSchemaNode == null) {
return Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(exception.getMessage()).build();
Preconditions.checkState(errorsSchemaNode instanceof ContainerSchemaNode,
"Found Errors SchemaNode isn't ContainerNode");
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> errContBuild =
+ final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> errContBuild =
Builders.containerBuilder((ContainerSchemaNode) errorsSchemaNode);
final List<DataSchemaNode> schemaList = ControllerContext.findInstanceDataChildrenByName(errorsSchemaNode,
errContBuild.withChild(listErorsBuilder.build());
final NormalizedNodeContext errContext = new NormalizedNodeContext(new InstanceIdentifierContext<>(null,
- (DataSchemaNode) errorsSchemaNode, null, context.getGlobalSchema()), errContBuild.build());
+ (DataSchemaNode) errorsSchemaNode, null, controllerContext.getGlobalSchema()), errContBuild.build());
Object responseBody;
if (mediaType.getSubtype().endsWith("json")) {
Preconditions.checkArgument(errListSchemaNode instanceof ListSchemaNode,
"errListSchemaNode has to be of type ListSchemaNode");
final ListSchemaNode listStreamSchemaNode = (ListSchemaNode) errListSchemaNode;
- final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> errNodeValues = Builders
+ final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> errNodeValues = Builders
.mapEntryBuilder(listStreamSchemaNode);
List<DataSchemaNode> lsChildDataSchemaNode = ControllerContext.findInstanceDataChildrenByName(
final JsonWriter jsonWriter = JsonWriterFactory.createJsonWriter(outputWriter);
final NormalizedNodeStreamWriter jsonStreamWriter = JSONNormalizedNodeStreamWriter.createExclusiveWriter(
- JSONCodecFactory.getShared(context.getSchemaContext()), path, initialNs, jsonWriter);
+ JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(context.getSchemaContext()), path,
+ initialNs, jsonWriter);
// We create a delegating writer to special-case error-info as error-info is defined as an empty
// container in the restconf yang schema but we create a leaf node so we can output it. The delegate
LOG.warn("Error writing error response body", e);
}
- return outStream.toString();
-
+ try {
+ return outStream.toString(StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ // Shouldn't happen
+ return "Failure encoding error response: " + e;
+ }
}
private static Object toXMLResponseBody(final NormalizedNodeContext errorsNode,
final XMLStreamWriter xmlWriter;
try {
xmlWriter = XML_FACTORY.createXMLStreamWriter(outStream, StandardCharsets.UTF_8.name());
- } catch (final XMLStreamException e) {
- throw new IllegalStateException(e);
- } catch (final FactoryConfigurationError e) {
+ } catch (final XMLStreamException | FactoryConfigurationError e) {
throw new IllegalStateException(e);
}
NormalizedNode<?, ?> data = errorsNode.getData();
LOG.warn("Error writing error response body.", e);
}
- return outStream.toString();
+ try {
+ return outStream.toString(StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ // Shouldn't happen
+ return "Failure encoding error response: " + e;
+ }
}
private static void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter,
- final ContainerNode data)
- throws IOException {
+ final ContainerNode data) throws IOException {
+ final QName name = SchemaContext.NAME;
try {
- final QName name = SchemaContext.NAME;
xmlWriter.writeStartElement(name.getNamespace().toString(), name.getLocalName());
for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
nnWriter.write(child);
xmlWriter.writeEndElement();
xmlWriter.flush();
} catch (final XMLStreamException e) {
- Throwables.propagate(e);
+ throw new IOException("Failed to write elements", e);
}
}
private static void writeDataRoot(final OutputStreamWriter outputWriter, final NormalizedNodeWriter nnWriter,
final ContainerNode data) throws IOException {
- final Iterator<DataContainerChild<? extends PathArgument, ?>> iterator = data.getValue().iterator();
- while (iterator.hasNext()) {
- final DataContainerChild<? extends PathArgument, ?> child = iterator.next();
+ for (final DataContainerChild<? extends PathArgument, ?> child : data.getValue()) {
nnWriter.write(child);
nnWriter.flush();
}