<propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <failOnError>true</failOnError>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Set;
import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
}
};
- private static TransactionChainHandler transactionChainHandler;
- private static DOMDataBroker dataBroker;
- private static DOMMountPointServiceHandler mountPointServiceHandler;
+ @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
+ private static volatile TransactionChainHandler transactionChainHandler;
+ @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
+ private static volatile DOMDataBroker dataBroker;
+ @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
+ private static volatile DOMMountPointServiceHandler mountPointServiceHandler;
private final DOMRpcService rpcService;
private final DOMNotificationService notificationService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
import org.opendaylight.restconf.common.util.IdentityValuesDTO;
import org.opendaylight.restconf.common.util.IdentityValuesDTO.IdentityValue;
private static List<Predicate> keyValuesToPredicateList(final Map<QName, Object> keyValues) {
final List<Predicate> result = new ArrayList<>();
- for (final QName qualifiedName : keyValues.keySet()) {
- final Object value = keyValues.get(qualifiedName);
+ for (final Entry<QName, Object> entry : keyValues.entrySet()) {
+ final QName qualifiedName = entry.getKey();
+ final Object value = entry.getValue();
result.add(new Predicate(qNameToIdentityValue(qualifiedName), String.valueOf(value)));
}
return result;
final SchemaContext schemaContext) {
URI validNamespace;
if (mountPoint != null) {
- validNamespace = findFirstModuleByName(schemaContext, namespace);
+ validNamespace = findFirstModuleByName(mountPoint.getSchemaContext(), namespace);
} else {
validNamespace = findFirstModuleByName(schemaContext, namespace);
}
*/
package org.opendaylight.restconf.nb.rfc8040.handlers;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.Objects;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
/**
*
*/
public class DOMMountPointServiceHandler implements Handler<DOMMountPointService> {
-
private final DOMMountPointService domMountPointService;
- private static DOMMountPointService actualDomMountPointService;
/**
* Prepare mount point service for Restconf services.
* mount point service
*/
public DOMMountPointServiceHandler(final DOMMountPointService domMountPointService) {
- Preconditions.checkNotNull(domMountPointService);
- this.domMountPointService = domMountPointService;
- actualDomMountPointService = domMountPointService;
+ this.domMountPointService = Objects.requireNonNull(domMountPointService);
}
@Override
public DOMMountPointService get() {
return this.domMountPointService;
}
-
- public static Optional<DOMMountPointService> getActualMountPointService() {
- return Optional.fromNullable(actualDomMountPointService);
- }
-
}
package org.opendaylight.restconf.nb.rfc8040.handlers;
import com.google.common.base.Preconditions;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
private static final Logger LOG = LoggerFactory.getLogger(SchemaContextHandler.class);
+ @SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
+ private static volatile SchemaContext schemaContext;
+
private final TransactionChainHandler transactionChainHandler;
- private SchemaContext context;
- private static SchemaContext actualSchemaContext;
- private int moduleSetId;
+ private final AtomicInteger moduleSetId = new AtomicInteger(0);
/**
- * Set module-set-id on initial value - 0.
+ * Constructor.
*
* @param transactionChainHandler Transaction chain handler
*/
public SchemaContextHandler(final TransactionChainHandler transactionChainHandler) {
this.transactionChainHandler = transactionChainHandler;
- this.moduleSetId = 0;
- actualSchemaContext = null;
+ schemaContext = null;
}
@Override
@SuppressWarnings("checkstyle:hiddenField")
public void onGlobalContextUpdated(final SchemaContext context) {
Preconditions.checkNotNull(context);
- this.context = null;
- this.context = context;
-
- actualSchemaContext = context;
+ schemaContext = context;
- this.moduleSetId++;
final Module ietfYangLibraryModule =
context.findModule(IetfYangLibrary.MODULE_QNAME).orElse(null);
NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>> normNode =
RestconfMappingNodeUtil.mapModulesByIetfYangLibraryYang(context.getModules(), ietfYangLibraryModule,
- context, String.valueOf(this.moduleSetId));
+ context, String.valueOf(this.moduleSetId.incrementAndGet()));
putData(normNode);
final Module monitoringModule =
- this.context.findModule(MonitoringModule.MODULE_QNAME).orElse(null);
+ schemaContext.findModule(MonitoringModule.MODULE_QNAME).orElse(null);
normNode = RestconfMappingNodeUtil.mapCapabilites(monitoringModule);
putData(normNode);
}
@Override
public SchemaContext get() {
- return this.context;
+ return schemaContext;
}
- public static SchemaContext getActualSchemaContext() {
- return actualSchemaContext;
+ public static SchemaContext getSchemaContext() {
+ return schemaContext;
}
- public static void setActualSchemaContext(final SchemaContext schemaContext) {
- actualSchemaContext = schemaContext;
+ public static void setSchemaContext(final SchemaContext context) {
+ schemaContext = context;
}
private void putData(
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.Consumes;
final JsonParserStream jsonParser = JsonParserStream.create(writer,
JSONCodecFactorySupplier.RFC7951.getShared(path.getSchemaContext()), parentSchema);
- final JsonReader reader = new JsonReader(new InputStreamReader(entityStream));
+ final JsonReader reader = new JsonReader(new InputStreamReader(entityStream, StandardCharsets.UTF_8));
jsonParser.parse(reader);
NormalizedNode<?, ?> result = resultHolder.getResult();
package org.opendaylight.restconf.nb.rfc8040.jersey.providers.patch;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.gson.stream.JsonReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import javax.annotation.Nonnull;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import org.opendaylight.restconf.common.patch.PatchContext;
import org.opendaylight.restconf.common.patch.PatchEditOperation;
import org.opendaylight.restconf.common.patch.PatchEntity;
+import org.opendaylight.restconf.nb.rfc8040.RestConnectorProvider;
import org.opendaylight.restconf.nb.rfc8040.Rfc8040;
import org.opendaylight.restconf.nb.rfc8040.codecs.StringModuleInstanceIdentifierCodec;
-import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
import org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
private PatchContext readFrom(final InstanceIdentifierContext<?> path, final InputStream entityStream)
throws IOException {
- final JsonReader jsonReader = new JsonReader(new InputStreamReader(entityStream));
+ final JsonReader jsonReader = new JsonReader(new InputStreamReader(entityStream, StandardCharsets.UTF_8));
final List<PatchEntity> resultList = read(jsonReader, path);
jsonReader.close();
RestconfDocumentedException {
try {
return readFrom(
- ParserIdentifier.toInstanceIdentifier(uriPath, SchemaContextHandler.getActualSchemaContext(),
- DOMMountPointServiceHandler.getActualMountPointService()), entityStream);
+ ParserIdentifier.toInstanceIdentifier(uriPath, SchemaContextHandler.getSchemaContext(),
+ Optional.of(RestConnectorProvider.getMountPointService())), entityStream);
} catch (final Exception e) {
propagateExceptionAs(e);
return null; // no-op
edit.setId(in.nextString());
break;
case "operation":
- edit.setOperation(PatchEditOperation.valueOf(in.nextString().toUpperCase()));
+ edit.setOperation(PatchEditOperation.valueOf(in.nextString().toUpperCase(Locale.ROOT)));
break;
case "target":
// target can be specified completely in request URI
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import javax.annotation.Nonnull;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
DataSchemaNode schemaNode = (DataSchemaNode) pathContext.getSchemaNode();
final Element element = (Element) editNodes.item(i);
final String operation = element.getElementsByTagName("operation").item(0).getFirstChild().getNodeValue();
- final PatchEditOperation oper = PatchEditOperation.valueOf(operation.toUpperCase());
+ final PatchEditOperation oper = PatchEditOperation.valueOf(operation.toUpperCase(Locale.ROOT));
final String editId = element.getElementsByTagName("edit-id").item(0).getFirstChild().getNodeValue();
final String target = element.getElementsByTagName("target").item(0).getFirstChild().getNodeValue();
final List<Element> values = readValueNodes(element, oper);
private InstanceIdentifierContext<?> getInstanceIdentifierContext() {
return ParserIdentifier.toInstanceIdentifier(
getIdentifier(),
- SchemaContextHandler.getActualSchemaContext(),
+ SchemaContextHandler.getSchemaContext(),
Optional.of(RestConnectorProvider.getMountPointService()));
}
if (outputContext.getData() != null) {
output = toJson(outputContext);
}
- } catch (final Exception e) {
+ } catch (RuntimeException | IOException e) {
propagateExceptionAs(uriPath, e, "RPC");
}
private NormalizedNodeContext toNormalizedNodeContext(final String uriPath, @Nullable final String payload,
final boolean isPost) throws OperationFailedException {
final InstanceIdentifierContext<?> instanceIdentifierContext = ParserIdentifier.toInstanceIdentifier(
- uriPath, SchemaContextHandler.getActualSchemaContext(),
+ uriPath, SchemaContextHandler.getSchemaContext(),
Optional.of(mountPointServiceHandler.get()));
if (payload == null) {
@Path("/")
public class RestconfInvokeOperationsServiceImpl implements RestconfInvokeOperationsService {
- private RpcServiceHandler rpcServiceHandler;
- private SchemaContextHandler schemaContextHandler;
+ private volatile RpcServiceHandler rpcServiceHandler;
+ private volatile SchemaContextHandler schemaContextHandler;
public RestconfInvokeOperationsServiceImpl(final RpcServiceHandler rpcServiceHandler,
final SchemaContextHandler schemaContextHandler) {
final DOMRpcResult result = RestconfInvokeOperationsUtil.checkResponse(response);
RpcDefinition resultNodeSchema = null;
- final NormalizedNode<?, ?> resultData = result.getResult();
- if ((result != null) && (result.getResult() != null)) {
+ NormalizedNode<?, ?> resultData = null;
+ if (result != null && result.getResult() != null) {
+ resultData = result.getResult();
resultNodeSchema = (RpcDefinition) payload.getInstanceIdentifierContext().getSchemaNode();
}
- return new NormalizedNodeContext(new InstanceIdentifierContext<RpcDefinition>(null, resultNodeSchema,
+ return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, resultNodeSchema,
mountPoint, schemaContextRef.get()), resultData);
}
}
/**
* Holder of all handlers for notifications.
*/
- public final class HandlersHolder {
+ public static final class HandlersHolder {
private final DOMDataBrokerHandler domDataBrokerHandler;
private final NotificationServiceHandler notificationServiceHandler;
*/
private static NotificationOutputType prepareOutputType(final ContainerNode data) {
NotificationOutputType outputType = parseEnum(data, NotificationOutputType.class, OUTPUT_TYPE_PARAM_NAME);
- return outputType = outputType == null ? NotificationOutputType.XML : outputType;
+ return outputType == null ? NotificationOutputType.XML : outputType;
}
private static String prepareDataChangeNotifiStreamName(final YangInstanceIdentifier path,
* Constants for read data.
*
*/
- public final class ReadData {
+ public static final class ReadData {
// URI parameters
public static final String CONTENT = "content";
public static final String DEPTH = "depth";
* Constants for data to put.
*
*/
- public final class PutData {
+ public static final class PutData {
public static final String NETCONF_BASE = "urn:ietf:params:xml:ns:netconf:base:1.0";
public static final String NETCONF_BASE_PAYLOAD_NAME = "data";
public static final String PUT_TX_TYPE = "PUT";
* Constants for data to post.
*
*/
- public final class PostData {
+ public static final class PostData {
public static final String POST_TX_TYPE = "POST";
private PostData() {
* Constants for data to delete.
*
*/
- public final class DeleteData {
+ public static final class DeleteData {
public static final String DELETE_TX_TYPE = "DELETE";
private DeleteData() {
* Constants for data to yang patch.
*
*/
- public final class PatchData {
+ public static final class PatchData {
public static final String PATCH_TX_TYPE = "Patch";
private PatchData() {
} else {
listeners = pickSpecificListenerByOutput(listeners, NotificationOutputType.XML.getName());
}
- if (listeners == null || listeners.isEmpty()) {
+ if (listeners.isEmpty()) {
throw new RestconfDocumentedException("Stream was not found.", ErrorType.PROTOCOL,
ErrorTag.UNKNOWN_ELEMENT);
}
@Path("/")
public class RestconfImpl implements RestconfService {
- private SchemaContextHandler schemaContextHandler;
+ private volatile SchemaContextHandler schemaContextHandler;
public RestconfImpl(final SchemaContextHandler schemaContextHandler) {
this.schemaContextHandler = schemaContextHandler;
private static final Logger LOG = LoggerFactory.getLogger(RestconfOperationsServiceImpl.class);
- private SchemaContextHandler schemaContextHandler;
- private DOMMountPointServiceHandler domMountPointServiceHandler;
+ private volatile SchemaContextHandler schemaContextHandler;
+ private volatile DOMMountPointServiceHandler domMountPointServiceHandler;
/**
* Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}.
@Path("/")
public class RestconfSchemaServiceImpl implements RestconfSchemaService {
- private SchemaContextHandler schemaContextHandler;
- private DOMMountPointServiceHandler domMountPointServiceHandler;
- private DOMYangTextSourceProvider sourceProvider;
+ private volatile SchemaContextHandler schemaContextHandler;
+ private volatile DOMMountPointServiceHandler domMountPointServiceHandler;
+ private volatile DOMYangTextSourceProvider sourceProvider;
/**
* Set {@link SchemaContextHandler} for getting actual {@link SchemaContext}
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
final Event event = new Event(EventType.NOTIFY);
if (this.outputType.equals(NotificationOutputType.JSON)) {
try {
- final JsonNode node = new XmlMapper().readTree(xml.getBytes());
+ final JsonNode node = new XmlMapper().readTree(xml.getBytes(StandardCharsets.UTF_8));
event.setData(node.toString());
} catch (final IOException e) {
LOG.error("Error parsing XML {}", xml, e);
writeIdentifierWithNamespacePrefix(element, textContent, pathArgument.getNodeType(), schemaContext);
if (pathArgument instanceof NodeIdentifierWithPredicates) {
final Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
- for (final QName keyValue : predicates.keySet()) {
- final String predicateValue = String.valueOf(predicates.get(keyValue));
+ for (final Entry<QName, Object> entry : predicates.entrySet()) {
+ final QName keyValue = entry.getKey();
+ final String predicateValue = String.valueOf(entry.getValue());
textContent.append("[");
writeIdentifierWithNamespacePrefix(element, textContent, keyValue, schemaContext);
textContent.append("='");
package org.opendaylight.restconf.nb.rfc8040.streams.websockets;
-import static io.netty.handler.codec.http.HttpHeaders.Names.HOST;
import static io.netty.handler.codec.http.HttpHeaders.isKeepAlive;
import static io.netty.handler.codec.http.HttpHeaders.setContentLength;
import static io.netty.handler.codec.http.HttpMethod.GET;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpHeaders.Names;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
}
} else if (streamName.contains(RestconfConstants.NOTIFICATION_STREAM)) {
final List<NotificationListenerAdapter> listeners = Notificator.getNotificationListenerFor(streamName);
- if (!listeners.isEmpty() && (listeners != null)) {
+ if (listeners != null && !listeners.isEmpty()) {
for (final NotificationListenerAdapter listener : listeners) {
listener.addSubscriber(ctx.channel());
LOG.debug("Subscriber successfully registered.");
// Send the response and close the connection if necessary.
final ChannelFuture f = ctx.channel().writeAndFlush(res);
- if (!isKeepAlive(req) || (res.getStatus().code() != 200)) {
+ if (!isKeepAlive(req) || res.getStatus().code() != 200) {
f.addListener(ChannelFutureListener.CLOSE);
}
}
if (listener != null) {
listener.removeSubscriber(ctx.channel());
LOG.debug("Subscriber successfully registered.");
+ Notificator.removeListenerIfNoSubscriberExists(listener);
}
- Notificator.removeListenerIfNoSubscriberExists(listener);
} else if (streamName.contains(RestconfConstants.NOTIFICATION_STREAM)) {
final List<NotificationListenerAdapter> listeners = Notificator.getNotificationListenerFor(streamName);
- if (!listeners.isEmpty() && (listeners != null)) {
+ if (listeners != null && !listeners.isEmpty()) {
for (final NotificationListenerAdapter listener : listeners) {
listener.removeSubscriber(ctx.channel());
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
- if (!(cause instanceof java.nio.channels.ClosedChannelException)) {
- // LOG.info("Not expected error cause: ", cause.toString());
- }
ctx.close();
}
* @return String representation of web socket location.
*/
private static String getWebSocketLocation(final HttpRequest req) {
- return "ws://" + req.headers().get(HOST) + req.getUri();
+ return "ws://" + req.headers().get(Names.HOST) + req.getUri();
}
}
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Optional;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError;
import org.opendaylight.restconf.common.util.RestUtil;
import org.opendaylight.restconf.common.util.RestconfSchemaUtil;
} else if (currentChar(variables.getOffset(),
variables.getData()) == ParserBuilderConstants.Deserializer.EQUAL) {
if (nextContextNode(qname, path, variables).getDataSchemaNode() instanceof ListSchemaNode) {
- prepareNodeWithPredicates(qname, path, variables);
+ prepareNodeWithPredicates(qname, path, variables,
+ (ListSchemaNode) variables.getCurrent().getDataSchemaNode());
} else {
prepareNodeWithValue(qname, path, variables);
}
}
private static void prepareNodeWithPredicates(final QName qname, final List<PathArgument> path,
- final MainVarsWrapper variables) {
+ final MainVarsWrapper variables, final ListSchemaNode listSchemaNode) {
+ checkValid(listSchemaNode != null, "Data schema node is null", variables.getData(), variables.getOffset());
- final DataSchemaNode dataSchemaNode = variables.getCurrent().getDataSchemaNode();
- checkValid(dataSchemaNode != null, "Data schema node is null", variables.getData(), variables.getOffset());
-
- final Iterator<QName> keys = ((ListSchemaNode) dataSchemaNode).getKeyDefinition().iterator();
+ final Iterator<QName> keys = listSchemaNode.getKeyDefinition().iterator();
final ImmutableMap.Builder<QName, Object> values = ImmutableMap.builder();
// skip already expected equal sign
// parse value
final QName key = keys.next();
- DataSchemaNode leafSchemaNode = null;
- if (dataSchemaNode instanceof ListSchemaNode) {
- leafSchemaNode = ((ListSchemaNode) dataSchemaNode).getDataChildByName(key);
- } else if (dataSchemaNode instanceof LeafListSchemaNode) {
- leafSchemaNode = dataSchemaNode;
+ Optional<DataSchemaNode> leafSchemaNode = listSchemaNode.findDataChildByName(key);
+ if (!leafSchemaNode.isPresent()) {
+ throw new RestconfDocumentedException("Schema not found for " + key,
+ RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.BAD_ELEMENT);
}
+
final String value = findAndParsePercentEncoded(nextIdentifierFromNextSequence(
ParserBuilderConstants.Deserializer.IDENTIFIER_PREDICATE, variables));
- final Object valueByType = prepareValueByType(leafSchemaNode, value, variables);
+ final Object valueByType = prepareValueByType(leafSchemaNode.get(), value, variables);
values.put(key, valueByType);
switch (currentChar(variables.getOffset(), variables.getData())) {
case RestconfConstants.SLASH:
+ case ParserBuilderConstants.Deserializer.EQUAL:
prefix = preparedPrefix;
return getQNameOfDataSchemaNode(prefix, variables);
case ParserBuilderConstants.Deserializer.COLON:
Preconditions.checkArgument(module != null, "Failed to lookup prefix %s", prefix);
return QName.create(module.getQNameModule(), localName);
}
- case ParserBuilderConstants.Deserializer.EQUAL:
- prefix = preparedPrefix;
- return getQNameOfDataSchemaNode(prefix, variables);
default:
throw new IllegalArgumentException("Failed build path.");
}
variables.getData(), variables.getOffset());
}
+ @SuppressFBWarnings("NP_NULL_ON_SOME_PATH") // code does check for null 'current' but FB doesn't recognize it
private static DataSchemaContextNode<?> nextContextNode(final QName qname, final List<PathArgument> path,
final MainVarsWrapper variables) {
variables.setCurrent(variables.getCurrent().getChild(qname));
DataSchemaContextNode<?> current = variables.getCurrent();
if (current == null) {
- for (final RpcDefinition rpcDefinition : variables.getSchemaContext()
- .findModule(qname.getModule()).orElse(null).getRpcs()) {
- if (rpcDefinition.getQName().getLocalName().equals(qname.getLocalName())) {
- return null;
+ final Optional<Module> module = variables.getSchemaContext().findModule(qname.getModule());
+ if (module.isPresent()) {
+ for (final RpcDefinition rpcDefinition : module.get().getRpcs()) {
+ if (rpcDefinition.getQName().getLocalName().equals(qname.getLocalName())) {
+ return null;
+ }
}
}
}
import com.google.common.base.Preconditions;
import java.util.Iterator;
+import java.util.Locale;
import java.util.Map.Entry;
import org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants;
import org.opendaylight.restconf.nb.rfc8040.utils.parser.builder.ParserBuilderConstants;
while (start < valueOf.length()) {
if (Serializer.PERCENT_ENCODE_CHARS.matches(valueOf.charAt(start))) {
final String format = String.format("%x", (int) valueOf.charAt(start));
- final String upperCase = format.toUpperCase();
+ final String upperCase = format.toUpperCase(Locale.ROOT);
sb.append(ParserBuilderConstants.Deserializer.PERCENT_ENCODING + upperCase);
} else {
sb.append(valueOf.charAt(start));
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.Iterator;
+import java.util.Locale;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
);
RestconfValidationUtils.checkDocumentedError(
- !name.toUpperCase().startsWith("XML"),
+ !name.toUpperCase(Locale.ROOT).startsWith("XML"),
ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE,
"Identifier must NOT start with XML ignore case."
);
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mountPointService);
when(mountPointService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountPoint));
when(mountPoint.getSchemaContext()).thenReturn(schemaContext);
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mountPointService);
when(mountPointService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountPoint));
when(mountPoint.getSchemaContext()).thenReturn(schemaContext);
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
public static void initialization() {
schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mock(DOMMountPointService.class));
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mountPointService);
when(mountPointService.getMountPoint(any(YangInstanceIdentifier.class))).thenReturn(Optional.of(mountPoint));
when(mountPoint.getSchemaContext()).thenReturn(schemaContext);
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
public static void initialization() {
schemaContext = schemaContextLoader("/instanceidentifier/yang", schemaContext);
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mock(DOMMountPointService.class));
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
testFiles.addAll(TestRestconfUtils.loadFiles("/modules"));
schemaContext = YangParserTestUtils.parseYangFiles(testFiles);
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mock(DOMMountPointService.class));
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
testFiles.addAll(TestRestconfUtils.loadFiles("/foo-xml-test/yang"));
schemaContext = YangParserTestUtils.parseYangFiles(testFiles);
when(MOUNT_POINT_SERVICE_HANDLER.get()).thenReturn(mock(DOMMountPointService.class));
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
@Test
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.restconf.nb.rfc8040.RestConnectorProvider;
import org.opendaylight.restconf.nb.rfc8040.TestUtils;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMDataBrokerHandler;
import org.opendaylight.restconf.nb.rfc8040.handlers.DOMMountPointServiceHandler;
@BeforeClass
public static void init() throws IOException, ReactorException {
schemaContext = TestUtils.loadSchemaContext("/full-versions/yangs");
- SchemaContextHandler.setActualSchemaContext(schemaContext);
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
+ @SuppressWarnings("resource")
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
final DOMMountPointServiceHandler mountPointServiceHandler =
new DOMMountPointServiceHandler(mockMountPointService);
+ final DOMNotificationService mockNotificationService = mock(DOMNotificationService.class);
ServicesWrapperImpl.getInstance().setHandlers(mockSchemaContextHandler, mountPointServiceHandler,
txChainHandler, new DOMDataBrokerHandler(mockDOMDataBroker),
new RpcServiceHandler(mockRpcService),
- new NotificationServiceHandler(mock(DOMNotificationService.class)), domSchemaService);
+ new NotificationServiceHandler(mockNotificationService), domSchemaService);
service = new JSONRestconfServiceRfc8040Impl(ServicesWrapperImpl.getInstance(), mountPointServiceHandler);
+
+ new RestConnectorProvider<>(mockDOMDataBroker, domSchemaService, mockRpcService, mockNotificationService,
+ mockMountPointService).start();
+
+ SchemaContextHandler.setSchemaContext(schemaContext);
}
private static String loadData(final String path) throws IOException {
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
import org.opendaylight.yangtools.yang2sources.spi.MavenProjectAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This class gathers all yang defined {@link Module}s and generates Swagger compliant documentation.
*/
public class StaticDocGenerator extends ApiDocGenerator implements BasicCodeGenerator, MavenProjectAware {
+ private static final Logger LOG = LoggerFactory.getLogger(StaticDocGenerator.class);
+
private static final String DEFAULT_OUTPUT_BASE_DIR_PATH = "target" + File.separator + "generated-resources"
+ File.separator + "swagger-api-documentation";
- private MavenProject mavenProject;
- private File projectBaseDir;
- private Map<String, String> additionalConfig;
- private File resourceBaseDir;
-
@Override
+ @SuppressFBWarnings("DM_DEFAULT_ENCODING")
public Collection<File> generateSources(final SchemaContext context, final File outputBaseDir,
final Set<Module> currentModules, final Function<Module, Optional<String>> moduleResourcePathResolver)
throws IOException {
} else {
outputDir = outputBaseDir;
}
- outputDir.mkdirs();
+
+ if (!outputDir.mkdirs()) {
+ throw new IOException("Could not create directory " + outputDir);
+ }
// Create Resources directory
File resourcesDir = new File(outputDir, "resources");
- resourcesDir.mkdirs();
+ if (!resourcesDir.mkdirs()) {
+ throw new IOException("Could not create directory " + resourcesDir);
+ }
// Create JS file
File resourcesJsFile = new File(outputDir, "resources.js");
- resourcesJsFile.createNewFile();
- BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(resourcesJsFile));
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
-
- // Write resource listing to JS file
- ResourceList resourceList = super.getResourceListing(null, context, "");
- String resourceListJson = mapper.writeValueAsString(resourceList);
- resourceListJson = resourceListJson.replace("\'", "\\\'").replace("\\n", "\\\\n");
- bufferedWriter.write("function getSpec() {\n\treturn \'" + resourceListJson + "\';\n}\n\n");
-
- // Write resources/APIs to JS file and to disk
- bufferedWriter.write("function jsonFor(resource) {\n\tswitch(resource) {\n");
- for (Resource resource : resourceList.getApis()) {
- int revisionIndex = resource.getPath().indexOf('(');
- String name = resource.getPath().substring(0, revisionIndex);
- String revision = resource.getPath().substring(revisionIndex + 1, resource.getPath().length() - 1);
- ApiDeclaration apiDeclaration = super.getApiDeclaration(name, revision, null, context, "");
- String json = mapper.writeValueAsString(apiDeclaration);
- // Manually insert models because org.json.JSONObject cannot be serialized by ObjectMapper
- json = json.replace(
- "\"models\":{}", "\"models\":" + apiDeclaration.getModels().toString().replace("\\\"", "\""));
- // Escape single quotes and new lines
- json = json.replace("\'", "\\\'").replace("\\n", "\\\\n");
- bufferedWriter.write("\t\tcase \"" + name + "(" + revision + ")\": return \'" + json + "\';\n");
-
- File resourceFile = new File(resourcesDir, name + "(" + revision + ").json");
- BufferedWriter resourceFileWriter = new BufferedWriter(new FileWriter(resourceFile));
- resourceFileWriter.write(json);
- resourceFileWriter.close();
- result.add(resourceFile);
+ if (!resourcesJsFile.createNewFile()) {
+ LOG.info("File " + resourcesJsFile + " already exists.");
+ }
+
+ try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(resourcesJsFile))) {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+
+ // Write resource listing to JS file
+ ResourceList resourceList = super.getResourceListing(null, context, "");
+ String resourceListJson = mapper.writeValueAsString(resourceList);
+ resourceListJson = resourceListJson.replace("\'", "\\\'").replace("\\n", "\\\\n");
+ bufferedWriter.write("function getSpec() {\n\treturn \'" + resourceListJson + "\';\n}\n\n");
+
+ // Write resources/APIs to JS file and to disk
+ bufferedWriter.write("function jsonFor(resource) {\n\tswitch(resource) {\n");
+ for (Resource resource : resourceList.getApis()) {
+ int revisionIndex = resource.getPath().indexOf('(');
+ String name = resource.getPath().substring(0, revisionIndex);
+ String revision = resource.getPath().substring(revisionIndex + 1, resource.getPath().length() - 1);
+ ApiDeclaration apiDeclaration = super.getApiDeclaration(name, revision, null, context, "");
+ String json = mapper.writeValueAsString(apiDeclaration);
+ // Manually insert models because org.json.JSONObject cannot be serialized by ObjectMapper
+ json = json.replace(
+ "\"models\":{}", "\"models\":" + apiDeclaration.getModels().toString().replace("\\\"", "\""));
+ // Escape single quotes and new lines
+ json = json.replace("\'", "\\\'").replace("\\n", "\\\\n");
+ bufferedWriter.write("\t\tcase \"" + name + "(" + revision + ")\": return \'" + json + "\';\n");
+
+ File resourceFile = new File(resourcesDir, name + "(" + revision + ").json");
+
+ try (BufferedWriter resourceFileWriter = new BufferedWriter(new FileWriter(resourceFile))) {
+ resourceFileWriter.write(json);
+ }
+
+ result.add(resourceFile);
+ }
+ bufferedWriter.write("\t}\n\treturn \"\";\n}");
}
- bufferedWriter.write("\t}\n\treturn \"\";\n}");
- bufferedWriter.close();
result.add(resourcesJsFile);
return result;
@Override
public void setAdditionalConfig(final Map<String, String> additionalConfig) {
- this.additionalConfig = additionalConfig;
}
@Override
public void setResourceBaseDir(final File resourceBaseDir) {
- this.resourceBaseDir = resourceBaseDir;
}
@Override
public void setMavenProject(final MavenProject mavenProject) {
- this.mavenProject = mavenProject;
- this.projectBaseDir = mavenProject.getBasedir();
}
}
}
public ApiDeclaration getApiDeclaration(final String module, final String revision, final UriInfo uriInfo) {
+ Preconditions.checkState(schemaService != null);
final SchemaContext schemaContext = schemaService.getGlobalContext();
Preconditions.checkState(schemaContext != null);
return super.getApiDeclaration(module, revision, uriInfo, schemaContext, "");
return INSTANCE;
}
- public void setDraft(final boolean newDraft) {
- super.setDraft(newDraft);
- }
-
public void setSchemaService(final SchemaService schemaService) {
this.schemaService = schemaService;
}
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Map.Entry;
import javax.ws.rs.core.Response;
return Response.seeOther(uriInfo.getBaseUriBuilder().path("../explorer/index.html").build()).build();
}
- @SuppressWarnings("checkstyle:IllegalCatch")
@Override
public synchronized Response getListOfMounts(final UriInfo uriInfo) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
}
writer.writeEndArray();
writer.flush();
- } catch (final Exception e) {
- return Response.status(500).entity(e.getMessage()).build();
+ } catch (IOException e) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
+ }
+
+ try {
+ String responseStr = baos.toString(StandardCharsets.UTF_8.name());
+ return Response.status(Response.Status.OK).entity(responseStr).build();
+ } catch (UnsupportedEncodingException e) {
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
- return Response.status(200).entity(baos.toString()).build();
}
@Override
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
// private Map<String, ApiDeclaration> MODULE_DOC_CACHE = new HashMap<>()
private final ObjectMapper mapper = new ObjectMapper();
- private static boolean newDraft;
+ private volatile boolean newDraft;
protected BaseYangSwaggerGenerator() {
this.mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
return null;
}
- private static void addRootPostLink(final Module module, final DataNodeContainer node,
+ private void addRootPostLink(final Module module, final DataNodeContainer node,
final List<Parameter> pathParams, final String resourcePath, final String dataStore, final List<Api> apis) {
if (containsListOrContainer(module.getChildNodes())) {
final Api apiForRootPostUri = new Api();
}
}
- protected static String getContent(final String dataStore) {
+ protected String getContent(final String dataStore) {
if (newDraft) {
if ("operational".contains(dataStore)) {
return "?content=nonconfig";
return operations;
}
- private static String createPath(final DataSchemaNode schemaNode, final List<Parameter> pathParams,
+ private String createPath(final DataSchemaNode schemaNode, final List<Parameter> pathParams,
final SchemaContext schemaContext) {
- final ArrayList<LeafSchemaNode> pathListParams = new ArrayList<>();
final StringBuilder path = new StringBuilder();
final String localName = resolvePathArgumentsName(schemaNode, schemaContext);
path.append(localName);
for (final QName listKey : listKeys) {
final DataSchemaNode dataChildByName = ((DataNodeContainer) schemaNode).getDataChildByName(listKey);
- pathListParams.add((LeafSchemaNode) dataChildByName);
final String pathParamIdentifier;
if (newDraft) {
pathParamIdentifier = keyBuilder.append("{").append(listKey.getLocalName()).append("}").toString();
}
public void setDraft(final boolean draft) {
- BaseYangSwaggerGenerator.newDraft = draft;
+ this.newDraft = draft;
+ }
+
+ protected boolean isNewDraft() {
+ return newDraft;
}
}
*/
package org.opendaylight.netconf.sal.rest.doc.model.builder;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import org.opendaylight.netconf.sal.rest.doc.swagger.Operation;
public static final String CONFIG = "(config)";
public static final String TOP = "-TOP";
- public static final List<String> CONSUMES_PUT_POST = new ArrayList<>();
-
- static {
- CONSUMES_PUT_POST.add("application/json");
- CONSUMES_PUT_POST.add("application/xml");
- }
+ public static final List<String> CONSUMES_PUT_POST = ImmutableList.of("application/json", "application/xml");
private OperationBuilder() {
package org.opendaylight.netconf.sal.rest.doc.mountpoints;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
private static final String DATASTORES_REVISION = "-";
private static final String DATASTORES_LABEL = "Datastores";
- private static final String RESTCONF_DRAFT = "18";
private static final AtomicReference<MountPointSwagger> SELF_REF = new AtomicReference<>();
private DOMMountPointService mountService;
private final AtomicLong idKey = new AtomicLong(0);
private SchemaService globalSchema;
- private static boolean newDraft;
public Map<String, Long> getInstanceIdentifiers() {
+ Preconditions.checkState(globalSchema != null);
final Map<String, Long> urlToId = new HashMap<>();
synchronized (this.lock) {
final SchemaContext context = this.globalSchema.getGlobalContext();
if (arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
final NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
for (final Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
- if (newDraft) {
+ if (isNewDraft()) {
builder.deleteCharAt(builder.length() - 1).append("=").append(entry.getValue()).append('/');
} else {
builder.append(entry.getValue()).append('/');
}
private String getYangMountUrl(final YangInstanceIdentifier key) {
+ Preconditions.checkState(globalSchema != null);
final String modName = findModuleName(key, this.globalSchema.getGlobalContext());
return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount";
}
return null;
}
+ Preconditions.checkState(mountService != null);
final Optional<DOMMountPoint> mountPoint = this.mountService.getMountPoint(id);
if (!mountPoint.isPresent()) {
return null;
SELF_REF.compareAndSet(null, new MountPointSwagger());
swagger = SELF_REF.get();
}
- newDraft = false;
+
+ swagger.setDraft(false);
return swagger;
}
SELF_REF.compareAndSet(null, new MountPointSwagger());
swagger = SELF_REF.get();
}
- newDraft = true;
+
+ swagger.setDraft(true);
return swagger;
}
}