Committed by
Ray Milkey
Initial sketch of codecs and REST API approach.
FIxed typos and defects. ONOS-81 Change-Id: I789444a181abea509c354966545c927e305710d1
Showing
28 changed files
with
985 additions
and
22 deletions
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * Context for codecs to use while encoding/decoding. | ||
| 22 | + */ | ||
| 23 | +public interface CodecContext { | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * Returns the JSON object mapper. | ||
| 27 | + * | ||
| 28 | + * @return object mapper | ||
| 29 | + */ | ||
| 30 | + ObjectMapper mapper(); | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * Returns the JSON codec for the specified entity class. | ||
| 34 | + * | ||
| 35 | + * @param entityClass entity class | ||
| 36 | + * @param <T> entity type | ||
| 37 | + * @return JSON codec; null if no codec available for the class | ||
| 38 | + */ | ||
| 39 | + <T> JsonCodec<T> codec(Class<T> entityClass); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * Returns reference to the specified service implementation. | ||
| 43 | + * | ||
| 44 | + * @param serviceClass service class | ||
| 45 | + * @param <T> service type | ||
| 46 | + * @return JSON codec; null if no codec available for the class | ||
| 47 | + */ | ||
| 48 | + <T> T get(Class<T> serviceClass); | ||
| 49 | + | ||
| 50 | +} |
| ... | @@ -33,9 +33,10 @@ public interface CodecService { | ... | @@ -33,9 +33,10 @@ public interface CodecService { |
| 33 | * Returns the JSON codec for the specified entity class. | 33 | * Returns the JSON codec for the specified entity class. |
| 34 | * | 34 | * |
| 35 | * @param entityClass entity class | 35 | * @param entityClass entity class |
| 36 | + * @param <T> entity type | ||
| 36 | * @return JSON codec; null if no codec available for the class | 37 | * @return JSON codec; null if no codec available for the class |
| 37 | */ | 38 | */ |
| 38 | - JsonCodec getCodec(Class<?> entityClass); | 39 | + <T> JsonCodec<T> getCodec(Class<T> entityClass); |
| 39 | 40 | ||
| 40 | /** | 41 | /** |
| 41 | * Registers the specified JSON codec for the given entity class. | 42 | * Registers the specified JSON codec for the given entity class. |
| ... | @@ -43,7 +44,7 @@ public interface CodecService { | ... | @@ -43,7 +44,7 @@ public interface CodecService { |
| 43 | * @param entityClass entity class | 44 | * @param entityClass entity class |
| 44 | * @param codec JSON codec | 45 | * @param codec JSON codec |
| 45 | */ | 46 | */ |
| 46 | - void registerCodec(Class<?> entityClass, JsonCodec codec); | 47 | + <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec); |
| 47 | 48 | ||
| 48 | /** | 49 | /** |
| 49 | * Unregisters the JSON codec for the specified entity class. | 50 | * Unregisters the JSON codec for the specified entity class. | ... | ... |
| ... | @@ -16,7 +16,6 @@ | ... | @@ -16,7 +16,6 @@ |
| 16 | package org.onlab.onos.codec; | 16 | package org.onlab.onos.codec; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
| 19 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 20 | import com.fasterxml.jackson.databind.node.ArrayNode; | 19 | import com.fasterxml.jackson.databind.node.ArrayNode; |
| 21 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 22 | 21 | ||
| ... | @@ -32,36 +31,41 @@ public abstract class JsonCodec<T> { | ... | @@ -32,36 +31,41 @@ public abstract class JsonCodec<T> { |
| 32 | * Encodes the specified entity into JSON. | 31 | * Encodes the specified entity into JSON. |
| 33 | * | 32 | * |
| 34 | * @param entity entity to encode | 33 | * @param entity entity to encode |
| 35 | - * @param mapper object mapper | 34 | + * @param context encoding context |
| 36 | * @return JSON node | 35 | * @return JSON node |
| 37 | * @throws java.lang.UnsupportedOperationException if the codec does not | 36 | * @throws java.lang.UnsupportedOperationException if the codec does not |
| 38 | * support encode operations | 37 | * support encode operations |
| 39 | */ | 38 | */ |
| 40 | - public abstract ObjectNode encode(T entity, ObjectMapper mapper); | 39 | + public ObjectNode encode(T entity, CodecContext context) { |
| 40 | + throw new UnsupportedOperationException("encode() not supported"); | ||
| 41 | + } | ||
| 41 | 42 | ||
| 42 | /** | 43 | /** |
| 43 | * Decodes the specified entity from JSON. | 44 | * Decodes the specified entity from JSON. |
| 44 | * | 45 | * |
| 45 | * @param json JSON to decode | 46 | * @param json JSON to decode |
| 47 | + * @param context decoding context | ||
| 46 | * @return decoded entity | 48 | * @return decoded entity |
| 47 | * @throws java.lang.UnsupportedOperationException if the codec does not | 49 | * @throws java.lang.UnsupportedOperationException if the codec does not |
| 48 | * support decode operations | 50 | * support decode operations |
| 49 | */ | 51 | */ |
| 50 | - public abstract T decode(ObjectNode json); | 52 | + public T decode(ObjectNode json, CodecContext context) { |
| 53 | + throw new UnsupportedOperationException("decode() not supported"); | ||
| 54 | + } | ||
| 51 | 55 | ||
| 52 | /** | 56 | /** |
| 53 | * Encodes the collection of the specified entities. | 57 | * Encodes the collection of the specified entities. |
| 54 | * | 58 | * |
| 55 | * @param entities collection of entities to encode | 59 | * @param entities collection of entities to encode |
| 56 | - * @param mapper object mapper | 60 | + * @param context encoding context |
| 57 | * @return JSON array | 61 | * @return JSON array |
| 58 | * @throws java.lang.UnsupportedOperationException if the codec does not | 62 | * @throws java.lang.UnsupportedOperationException if the codec does not |
| 59 | * support encode operations | 63 | * support encode operations |
| 60 | */ | 64 | */ |
| 61 | - public ArrayNode encode(Iterable<T> entities, ObjectMapper mapper) { | 65 | + public ArrayNode encode(Iterable<T> entities, CodecContext context) { |
| 62 | - ArrayNode result = mapper.createArrayNode(); | 66 | + ArrayNode result = context.mapper().createArrayNode(); |
| 63 | for (T entity : entities) { | 67 | for (T entity : entities) { |
| 64 | - result.add(encode(entity, mapper)); | 68 | + result.add(encode(entity, context)); |
| 65 | } | 69 | } |
| 66 | return result; | 70 | return result; |
| 67 | } | 71 | } |
| ... | @@ -70,14 +74,15 @@ public abstract class JsonCodec<T> { | ... | @@ -70,14 +74,15 @@ public abstract class JsonCodec<T> { |
| 70 | * Decodes the specified JSON array into a collection of entities. | 74 | * Decodes the specified JSON array into a collection of entities. |
| 71 | * | 75 | * |
| 72 | * @param json JSON array to decode | 76 | * @param json JSON array to decode |
| 77 | + * @param context decoding context | ||
| 73 | * @return collection of decoded entities | 78 | * @return collection of decoded entities |
| 74 | * @throws java.lang.UnsupportedOperationException if the codec does not | 79 | * @throws java.lang.UnsupportedOperationException if the codec does not |
| 75 | * support decode operations | 80 | * support decode operations |
| 76 | */ | 81 | */ |
| 77 | - public List<T> decode(ArrayNode json) { | 82 | + public List<T> decode(ArrayNode json, CodecContext context) { |
| 78 | List<T> result = new ArrayList<>(); | 83 | List<T> result = new ArrayList<>(); |
| 79 | for (JsonNode node : json) { | 84 | for (JsonNode node : json) { |
| 80 | - result.add(decode((ObjectNode) node)); | 85 | + result.add(decode((ObjectNode) node, context)); |
| 81 | } | 86 | } |
| 82 | return result; | 87 | return result; |
| 83 | } | 88 | } | ... | ... |
| ... | @@ -92,6 +92,8 @@ public interface LinkService { | ... | @@ -92,6 +92,8 @@ public interface LinkService { |
| 92 | */ | 92 | */ |
| 93 | Set<Link> getIngressLinks(ConnectPoint connectPoint); | 93 | Set<Link> getIngressLinks(ConnectPoint connectPoint); |
| 94 | 94 | ||
| 95 | + // FIXME: I don't think this makes sense; discuss and remove or adjust return | ||
| 96 | + // to be a Set<Link> or add Link.Type parameter | ||
| 95 | /** | 97 | /** |
| 96 | * Returns the infrastructure links between the specified source | 98 | * Returns the infrastructure links between the specified source |
| 97 | * and destination connection points. | 99 | * and destination connection points. | ... | ... |
| ... | @@ -58,12 +58,12 @@ public class JsonCodecTest { | ... | @@ -58,12 +58,12 @@ public class JsonCodecTest { |
| 58 | 58 | ||
| 59 | private static class FooCodec extends JsonCodec<Foo> { | 59 | private static class FooCodec extends JsonCodec<Foo> { |
| 60 | @Override | 60 | @Override |
| 61 | - public ObjectNode encode(Foo entity, ObjectMapper mapper) { | 61 | + public ObjectNode encode(Foo entity, CodecContext context) { |
| 62 | - return mapper.createObjectNode().put("name", entity.name); | 62 | + return context.mapper().createObjectNode().put("name", entity.name); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | @Override | 65 | @Override |
| 66 | - public Foo decode(ObjectNode json) { | 66 | + public Foo decode(ObjectNode json, CodecContext context) { |
| 67 | return new Foo(json.get("name").asText()); | 67 | return new Foo(json.get("name").asText()); |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| ... | @@ -74,9 +74,26 @@ public class JsonCodecTest { | ... | @@ -74,9 +74,26 @@ public class JsonCodecTest { |
| 74 | Foo f2 = new Foo("bar"); | 74 | Foo f2 = new Foo("bar"); |
| 75 | FooCodec codec = new FooCodec(); | 75 | FooCodec codec = new FooCodec(); |
| 76 | ImmutableList<Foo> entities = ImmutableList.of(f1, f2); | 76 | ImmutableList<Foo> entities = ImmutableList.of(f1, f2); |
| 77 | - ArrayNode json = codec.encode(entities, new ObjectMapper()); | 77 | + ArrayNode json = codec.encode(entities, new TestContext()); |
| 78 | - List<Foo> foos = codec.decode(json); | 78 | + List<Foo> foos = codec.decode(json, new TestContext()); |
| 79 | assertEquals("incorrect encode/decode", entities, foos); | 79 | assertEquals("incorrect encode/decode", entities, foos); |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | + private class TestContext implements CodecContext { | ||
| 83 | + private ObjectMapper mapper = new ObjectMapper(); | ||
| 84 | + @Override | ||
| 85 | + public ObjectMapper mapper() { | ||
| 86 | + return mapper; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @Override | ||
| 90 | + public <T> JsonCodec<T> codec(Class<T> entityClass) { | ||
| 91 | + return null; | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Override | ||
| 95 | + public <T> T get(Class<T> serviceClass) { | ||
| 96 | + return null; | ||
| 97 | + } | ||
| 98 | + } | ||
| 82 | } | 99 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -80,7 +80,7 @@ | ... | @@ -80,7 +80,7 @@ |
| 80 | <group> | 80 | <group> |
| 81 | <title>GUI, REST & Command-Line</title> | 81 | <title>GUI, REST & Command-Line</title> |
| 82 | <packages> | 82 | <packages> |
| 83 | - org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.* | 83 | + org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.*:org.onlab.onos.codec.impl |
| 84 | </packages> | 84 | </packages> |
| 85 | </group> | 85 | </group> |
| 86 | <group> | 86 | <group> | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.api; | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * Represents condition where an item is not found or not available. | ||
| 20 | + */ | ||
| 21 | +public class ItemNotFoundException extends RuntimeException { | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * Creates a new exception with no message. | ||
| 25 | + */ | ||
| 26 | + public ItemNotFoundException() { | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * Creates a new exception with the supplied message. | ||
| 31 | + * @param message error message | ||
| 32 | + */ | ||
| 33 | + public ItemNotFoundException(String message) { | ||
| 34 | + super(message); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * Creates a new exception with the supplied message and cause. | ||
| 39 | + * @param message error message | ||
| 40 | + * @param cause cause of the error | ||
| 41 | + */ | ||
| 42 | + public ItemNotFoundException(String message, Throwable cause) { | ||
| 43 | + super(message, cause); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | +} |
| ... | @@ -18,6 +18,8 @@ package org.onlab.rest; | ... | @@ -18,6 +18,8 @@ package org.onlab.rest; |
| 18 | import org.onlab.osgi.DefaultServiceDirectory; | 18 | import org.onlab.osgi.DefaultServiceDirectory; |
| 19 | import org.onlab.osgi.ServiceDirectory; | 19 | import org.onlab.osgi.ServiceDirectory; |
| 20 | 20 | ||
| 21 | +import javax.ws.rs.core.Response; | ||
| 22 | + | ||
| 21 | /** | 23 | /** |
| 22 | * Base abstraction of a JAX-RS resource. | 24 | * Base abstraction of a JAX-RS resource. |
| 23 | */ | 25 | */ |
| ... | @@ -44,8 +46,12 @@ public abstract class BaseResource { | ... | @@ -44,8 +46,12 @@ public abstract class BaseResource { |
| 44 | * @param <T> type of service | 46 | * @param <T> type of service |
| 45 | * @return service implementation | 47 | * @return service implementation |
| 46 | */ | 48 | */ |
| 47 | - protected static <T> T get(Class<T> service) { | 49 | + public <T> T get(Class<T> service) { |
| 48 | return services.get(service); | 50 | return services.get(service); |
| 49 | } | 51 | } |
| 50 | 52 | ||
| 53 | + protected static Response.ResponseBuilder ok(Object obj) { | ||
| 54 | + return Response.ok(obj); | ||
| 55 | + } | ||
| 56 | + | ||
| 51 | } | 57 | } | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.codec.CodecContext; | ||
| 20 | +import org.onlab.onos.codec.JsonCodec; | ||
| 21 | +import org.onlab.onos.net.Annotated; | ||
| 22 | +import org.onlab.onos.net.Annotations; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * Base JSON codec for annotated entities. | ||
| 26 | + */ | ||
| 27 | +public abstract class AnnotatedCodec<T extends Annotated> extends JsonCodec<T> { | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * Adds JSON encoding of the given item annotations to the specified node. | ||
| 31 | + * | ||
| 32 | + * @param node node to add annotations to | ||
| 33 | + * @param entity annotated entity | ||
| 34 | + * @param context encode context | ||
| 35 | + * @return the given node | ||
| 36 | + */ | ||
| 37 | + protected ObjectNode annotate(ObjectNode node, T entity, CodecContext context) { | ||
| 38 | + if (!entity.annotations().keys().isEmpty()) { | ||
| 39 | + JsonCodec<Annotations> codec = context.codec(Annotations.class); | ||
| 40 | + node.set("annotations", codec.encode(entity.annotations(), context)); | ||
| 41 | + } | ||
| 42 | + return node; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.codec.CodecContext; | ||
| 20 | +import org.onlab.onos.codec.JsonCodec; | ||
| 21 | +import org.onlab.onos.net.Annotations; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Annotations JSON codec. | ||
| 25 | + */ | ||
| 26 | +public class AnnotationsCodec extends JsonCodec<Annotations> { | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public ObjectNode encode(Annotations annotations, CodecContext context) { | ||
| 30 | + ObjectNode result = context.mapper().createObjectNode(); | ||
| 31 | + for (String key : annotations.keys()) { | ||
| 32 | + result.put(key, annotations.value(key)); | ||
| 33 | + } | ||
| 34 | + return result; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.google.common.collect.ImmutableSet; | ||
| 19 | +import org.apache.felix.scr.annotations.Activate; | ||
| 20 | +import org.apache.felix.scr.annotations.Component; | ||
| 21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
| 22 | +import org.apache.felix.scr.annotations.Service; | ||
| 23 | +import org.onlab.onos.codec.CodecService; | ||
| 24 | +import org.onlab.onos.codec.JsonCodec; | ||
| 25 | +import org.onlab.onos.net.Annotations; | ||
| 26 | +import org.onlab.onos.net.ConnectPoint; | ||
| 27 | +import org.onlab.onos.net.Device; | ||
| 28 | +import org.onlab.onos.net.Link; | ||
| 29 | +import org.onlab.onos.net.Port; | ||
| 30 | +import org.slf4j.Logger; | ||
| 31 | +import org.slf4j.LoggerFactory; | ||
| 32 | + | ||
| 33 | +import java.util.Map; | ||
| 34 | +import java.util.Set; | ||
| 35 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * Implementation of the JSON codec brokering service. | ||
| 39 | + */ | ||
| 40 | +@Component(immediate = true) | ||
| 41 | +@Service | ||
| 42 | +public class CodecManager implements CodecService { | ||
| 43 | + | ||
| 44 | + private static Logger log = LoggerFactory.getLogger(CodecManager.class); | ||
| 45 | + | ||
| 46 | + private final Map<Class<?>, JsonCodec> codecs = new ConcurrentHashMap<>(); | ||
| 47 | + | ||
| 48 | + @Activate | ||
| 49 | + public void activate() { | ||
| 50 | + codecs.clear(); | ||
| 51 | + registerCodec(Annotations.class, new AnnotationsCodec()); | ||
| 52 | + registerCodec(Device.class, new DeviceCodec()); | ||
| 53 | + registerCodec(Port.class, new PortCodec()); | ||
| 54 | + registerCodec(ConnectPoint.class, new ConnectPointCodec()); | ||
| 55 | + registerCodec(Link.class, new LinkCodec()); | ||
| 56 | + log.info("Started"); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + @Deactivate | ||
| 60 | + public void deativate() { | ||
| 61 | + codecs.clear(); | ||
| 62 | + log.info("Stopped"); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + public Set<Class<?>> getCodecs() { | ||
| 67 | + return ImmutableSet.copyOf(codecs.keySet()); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @Override | ||
| 71 | + @SuppressWarnings("unchecked") | ||
| 72 | + public <T> JsonCodec<T> getCodec(Class<T> entityClass) { | ||
| 73 | + return codecs.get(entityClass); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 77 | + public <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec) { | ||
| 78 | + codecs.putIfAbsent(entityClass, codec); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void unregisterCodec(Class<?> entityClass) { | ||
| 83 | + codecs.remove(entityClass); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.codec.CodecContext; | ||
| 20 | +import org.onlab.onos.codec.JsonCodec; | ||
| 21 | +import org.onlab.onos.net.ConnectPoint; | ||
| 22 | + | ||
| 23 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Connection point JSON codec. | ||
| 27 | + */ | ||
| 28 | +public class ConnectPointCodec extends JsonCodec<ConnectPoint> { | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public ObjectNode encode(ConnectPoint point, CodecContext context) { | ||
| 32 | + checkNotNull(point, "Connect point cannot be null"); | ||
| 33 | + return context.mapper().createObjectNode() | ||
| 34 | + .put("device", point.deviceId().toString()) | ||
| 35 | + .put("port", point.port().toString()); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.codec.CodecContext; | ||
| 20 | +import org.onlab.onos.net.Device; | ||
| 21 | +import org.onlab.onos.net.device.DeviceService; | ||
| 22 | + | ||
| 23 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Device JSON codec. | ||
| 27 | + */ | ||
| 28 | +public class DeviceCodec extends AnnotatedCodec<Device> { | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public ObjectNode encode(Device device, CodecContext context) { | ||
| 32 | + checkNotNull(device, "Device cannot be null"); | ||
| 33 | + DeviceService service = context.get(DeviceService.class); | ||
| 34 | + ObjectNode result = context.mapper().createObjectNode() | ||
| 35 | + .put("id", device.id().toString()) | ||
| 36 | + .put("available", service.isAvailable(device.id())) | ||
| 37 | + .put("role", service.getRole(device.id()).toString()) | ||
| 38 | + .put("mfr", device.manufacturer()) | ||
| 39 | + .put("hw", device.hwVersion()) | ||
| 40 | + .put("sw", device.swVersion()) | ||
| 41 | + .put("serial", device.serialNumber()); | ||
| 42 | + return annotate(result, device, context); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.codec.CodecContext; | ||
| 20 | +import org.onlab.onos.codec.JsonCodec; | ||
| 21 | +import org.onlab.onos.net.ConnectPoint; | ||
| 22 | +import org.onlab.onos.net.Link; | ||
| 23 | +import org.onlab.onos.net.device.DeviceService; | ||
| 24 | + | ||
| 25 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * Link JSON codec. | ||
| 29 | + */ | ||
| 30 | +public class LinkCodec extends AnnotatedCodec<Link> { | ||
| 31 | + | ||
| 32 | + @Override | ||
| 33 | + public ObjectNode encode(Link link, CodecContext context) { | ||
| 34 | + checkNotNull(link, "Link cannot be null"); | ||
| 35 | + DeviceService service = context.get(DeviceService.class); | ||
| 36 | + JsonCodec<ConnectPoint> codec = context.codec(ConnectPoint.class); | ||
| 37 | + ObjectNode result = context.mapper().createObjectNode(); | ||
| 38 | + result.set("src", codec.encode(link.src(), context)); | ||
| 39 | + result.set("dst", codec.encode(link.dst(), context)); | ||
| 40 | + return annotate(result, link, context); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.codec.CodecContext; | ||
| 20 | +import org.onlab.onos.net.Port; | ||
| 21 | +import org.onlab.onos.net.PortNumber; | ||
| 22 | + | ||
| 23 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * Device port JSON codec. | ||
| 27 | + */ | ||
| 28 | +public class PortCodec extends AnnotatedCodec<Port> { | ||
| 29 | + | ||
| 30 | + @Override | ||
| 31 | + public ObjectNode encode(Port port, CodecContext context) { | ||
| 32 | + checkNotNull(port, "Port cannot be null"); | ||
| 33 | + ObjectNode result = context.mapper().createObjectNode() | ||
| 34 | + .put("port", portName(port.number())) | ||
| 35 | + .put("isEnabled", port.isEnabled()) | ||
| 36 | + .put("type", port.type().toString().toLowerCase()) | ||
| 37 | + .put("portSpeed", port.portSpeed()); | ||
| 38 | + return annotate(result, port, context); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + private String portName(PortNumber port) { | ||
| 42 | + return port.equals(PortNumber.LOCAL) ? "local" : port.toString(); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Implementations of the codec broker and built-in entity JSON codecs. | ||
| 19 | + */ | ||
| 20 | +package org.onlab.onos.codec.impl; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | +import org.onlab.api.ItemNotFoundException; | ||
| 21 | +import org.onlab.onos.codec.CodecContext; | ||
| 22 | +import org.onlab.onos.codec.CodecService; | ||
| 23 | +import org.onlab.onos.codec.JsonCodec; | ||
| 24 | +import org.onlab.rest.BaseResource; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * Abstract REST resource. | ||
| 28 | + */ | ||
| 29 | +public class AbstractWebResource extends BaseResource implements CodecContext { | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public ObjectMapper mapper() { | ||
| 33 | + return new ObjectMapper(); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * Returns the JSON codec for the specified entity class. | ||
| 38 | + * | ||
| 39 | + * @param entityClass entity class | ||
| 40 | + * @param <T> entity type | ||
| 41 | + * @return JSON codec | ||
| 42 | + */ | ||
| 43 | + public <T> JsonCodec<T> codec(Class<T> entityClass) { | ||
| 44 | + return get(CodecService.class).getCodec(entityClass); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * Returns JSON object wrapping the array encoding of the specified | ||
| 49 | + * collection of items. | ||
| 50 | + * | ||
| 51 | + * @param codecClass codec item class | ||
| 52 | + * @param field field holding the array | ||
| 53 | + * @param items collection of items to be encoded into array | ||
| 54 | + * @param <T> item type | ||
| 55 | + * @return JSON object | ||
| 56 | + */ | ||
| 57 | + protected <T> ObjectNode encodeArray(Class<T> codecClass, String field, | ||
| 58 | + Iterable<T> items) { | ||
| 59 | + ObjectNode result = mapper().createObjectNode(); | ||
| 60 | + result.set(field, codec(codecClass).encode(items, this)); | ||
| 61 | + return result; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * Returns the specified item if that items is null; otherwise throws | ||
| 66 | + * not found exception. | ||
| 67 | + * | ||
| 68 | + * @param item item to check | ||
| 69 | + * @param message not found message | ||
| 70 | + * @param <T> item type | ||
| 71 | + * @return item if not null | ||
| 72 | + * @throws org.onlab.api.ItemNotFoundException if item is null | ||
| 73 | + */ | ||
| 74 | + protected <T> T nullIsNotFound(T item, String message) { | ||
| 75 | + if (item == null) { | ||
| 76 | + throw new ItemNotFoundException(message); | ||
| 77 | + } | ||
| 78 | + return item; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onlab.onos.net.Device; | ||
| 20 | +import org.onlab.onos.net.Port; | ||
| 21 | +import org.onlab.onos.net.device.DeviceService; | ||
| 22 | + | ||
| 23 | +import javax.ws.rs.GET; | ||
| 24 | +import javax.ws.rs.Path; | ||
| 25 | +import javax.ws.rs.PathParam; | ||
| 26 | +import javax.ws.rs.core.Response; | ||
| 27 | +import java.util.List; | ||
| 28 | + | ||
| 29 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 30 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * REST resource for interacting with the inventory of infrastructure devices. | ||
| 34 | + */ | ||
| 35 | +@Path("devices") | ||
| 36 | +public class DevicesWebResource extends AbstractWebResource { | ||
| 37 | + | ||
| 38 | + public static final String DEVICE_NOT_FOUND = "Device is not found"; | ||
| 39 | + | ||
| 40 | + @GET | ||
| 41 | + public Response getDevices() { | ||
| 42 | + Iterable<Device> devices = get(DeviceService.class).getDevices(); | ||
| 43 | + return ok(encodeArray(Device.class, "devices", devices)).build(); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + @GET | ||
| 47 | + @Path("{id}") | ||
| 48 | + public Response getDevice(@PathParam("id") String id) { | ||
| 49 | + Device device = nullIsNotFound(get(DeviceService.class).getDevice(deviceId(id)), | ||
| 50 | + DEVICE_NOT_FOUND); | ||
| 51 | + return ok(codec(Device.class).encode(device, this)).build(); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + @GET | ||
| 55 | + @Path("{id}/ports") | ||
| 56 | + public Response getDevicePorts(@PathParam("id") String id) { | ||
| 57 | + DeviceService service = get(DeviceService.class); | ||
| 58 | + Device device = nullIsNotFound(service.getDevice(deviceId(id)), DEVICE_NOT_FOUND); | ||
| 59 | + List<Port> ports = checkNotNull(service.getPorts(deviceId(id)), "Ports could not be retrieved"); | ||
| 60 | + ObjectNode result = codec(Device.class).encode(device, this); | ||
| 61 | + result.set("ports", codec(Port.class).encode(ports, this)); | ||
| 62 | + return ok(result).build(); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | + | ||
| 21 | +import javax.ws.rs.Produces; | ||
| 22 | +import javax.ws.rs.core.MediaType; | ||
| 23 | +import javax.ws.rs.core.MultivaluedMap; | ||
| 24 | +import javax.ws.rs.ext.MessageBodyWriter; | ||
| 25 | +import java.io.IOException; | ||
| 26 | +import java.io.OutputStream; | ||
| 27 | +import java.lang.annotation.Annotation; | ||
| 28 | +import java.lang.reflect.Type; | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * JAX-RS Response message body writer. | ||
| 32 | + */ | ||
| 33 | +@Produces("application/json") | ||
| 34 | +public class JsonBodyWriter implements MessageBodyWriter<ObjectNode> { | ||
| 35 | + | ||
| 36 | + private ObjectMapper mapper = new ObjectMapper(); | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public boolean isWriteable(Class<?> type, Type genericType, | ||
| 40 | + Annotation[] annotations, MediaType mediaType) { | ||
| 41 | + return type == ObjectNode.class; | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + @Override | ||
| 45 | + public long getSize(ObjectNode node, Class<?> type, Type genericType, | ||
| 46 | + Annotation[] annotations, MediaType mediaType) { | ||
| 47 | + return -1; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public void writeTo(ObjectNode node, Class<?> type, Type genericType, | ||
| 52 | + Annotation[] annotations, MediaType mediaType, | ||
| 53 | + MultivaluedMap<String, Object> httpHeaders, | ||
| 54 | + OutputStream entityStream) throws IOException { | ||
| 55 | + mapper.writer().writeValue(entityStream, node); | ||
| 56 | + entityStream.flush(); | ||
| 57 | + } | ||
| 58 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest; | ||
| 17 | + | ||
| 18 | +import org.onlab.onos.net.ConnectPoint; | ||
| 19 | +import org.onlab.onos.net.DeviceId; | ||
| 20 | +import org.onlab.onos.net.Link; | ||
| 21 | +import org.onlab.onos.net.link.LinkService; | ||
| 22 | + | ||
| 23 | +import javax.ws.rs.GET; | ||
| 24 | +import javax.ws.rs.Path; | ||
| 25 | +import javax.ws.rs.QueryParam; | ||
| 26 | +import javax.ws.rs.core.Response; | ||
| 27 | + | ||
| 28 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
| 29 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
| 30 | +import static org.onlab.onos.rest.LinksWebResource.Direction.valueOf; | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * REST resource for interacting with the inventory of infrastructure links. | ||
| 34 | + */ | ||
| 35 | +@Path("links") | ||
| 36 | +public class LinksWebResource extends AbstractWebResource { | ||
| 37 | + | ||
| 38 | + enum Direction { ALL, INGRESS, EGRESS } | ||
| 39 | + | ||
| 40 | + @GET | ||
| 41 | + public Response getLinks(@QueryParam("device") String deviceId, | ||
| 42 | + @QueryParam("port") String port, | ||
| 43 | + @QueryParam("direction") String direction) { | ||
| 44 | + LinkService service = get(LinkService.class); | ||
| 45 | + Iterable<Link> links; | ||
| 46 | + | ||
| 47 | + if (deviceId != null && port != null) { | ||
| 48 | + links = getConnectPointLinks(new ConnectPoint(deviceId(deviceId), | ||
| 49 | + portNumber(port)), | ||
| 50 | + direction, service); | ||
| 51 | + } else if (deviceId != null) { | ||
| 52 | + links = getDeviceLinks(deviceId(deviceId), direction, service); | ||
| 53 | + } else { | ||
| 54 | + links = service.getLinks(); | ||
| 55 | + } | ||
| 56 | + return ok(encodeArray(Link.class, "links", links)).build(); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + private Iterable<Link> getConnectPointLinks(ConnectPoint point, | ||
| 60 | + String direction, | ||
| 61 | + LinkService service) { | ||
| 62 | + Direction dir = direction != null ? | ||
| 63 | + valueOf(direction.toUpperCase()) : Direction.ALL; | ||
| 64 | + switch (dir) { | ||
| 65 | + case INGRESS: | ||
| 66 | + return service.getIngressLinks(point); | ||
| 67 | + case EGRESS: | ||
| 68 | + return service.getEgressLinks(point); | ||
| 69 | + default: | ||
| 70 | + return service.getLinks(point); | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + private Iterable<Link> getDeviceLinks(DeviceId deviceId, | ||
| 75 | + String direction, | ||
| 76 | + LinkService service) { | ||
| 77 | + Direction dir = direction != null ? | ||
| 78 | + valueOf(direction.toUpperCase()) : Direction.ALL; | ||
| 79 | + switch (dir) { | ||
| 80 | + case INGRESS: | ||
| 81 | + return service.getDeviceIngressLinks(deviceId); | ||
| 82 | + case EGRESS: | ||
| 83 | + return service.getDeviceEgressLinks(deviceId); | ||
| 84 | + default: | ||
| 85 | + return service.getDeviceLinks(deviceId); | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest.exceptions; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | + | ||
| 21 | +import javax.ws.rs.core.Response; | ||
| 22 | +import javax.ws.rs.ext.ExceptionMapper; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * Base exception mapper implementation. | ||
| 26 | + */ | ||
| 27 | +public abstract class AbstractMapper<E extends Throwable> implements ExceptionMapper<E> { | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * Returns the response status to be given when the exception occurs. | ||
| 31 | + * | ||
| 32 | + * @return response status | ||
| 33 | + */ | ||
| 34 | + protected abstract Response.Status responseStatus(); | ||
| 35 | + | ||
| 36 | + @Override | ||
| 37 | + public Response toResponse(E exception) { | ||
| 38 | + return response(responseStatus(), exception).build(); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * Produces a response builder primed with the supplied status code | ||
| 43 | + * and JSON entity with the status code and exception message. | ||
| 44 | + * | ||
| 45 | + * @param status response status | ||
| 46 | + * @param exception exception to encode | ||
| 47 | + * @return response builder | ||
| 48 | + */ | ||
| 49 | + protected Response.ResponseBuilder response(Response.Status status, | ||
| 50 | + Throwable exception) { | ||
| 51 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 52 | + ObjectNode result = mapper.createObjectNode() | ||
| 53 | + .put("code", status.getStatusCode()) | ||
| 54 | + .put("message", exception.getMessage()); | ||
| 55 | + return Response.status(status).entity(result.toString()); | ||
| 56 | + } | ||
| 57 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest.exceptions; | ||
| 17 | + | ||
| 18 | +import org.onlab.api.ItemNotFoundException; | ||
| 19 | + | ||
| 20 | +import javax.ws.rs.core.Response; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * Mapper for service not found exceptions to the NOT_FOUND response code. | ||
| 24 | + */ | ||
| 25 | +public class EntityNotFoundMapper extends AbstractMapper<ItemNotFoundException> { | ||
| 26 | + @Override | ||
| 27 | + protected Response.Status responseStatus() { | ||
| 28 | + return Response.Status.NOT_FOUND; | ||
| 29 | + } | ||
| 30 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest.exceptions; | ||
| 17 | + | ||
| 18 | +import javax.ws.rs.core.Response; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * Mapper for service not found exceptions to the NOT_FOUND response code. | ||
| 22 | + */ | ||
| 23 | +public class ServerErrorMapper extends AbstractMapper<RuntimeException> { | ||
| 24 | + @Override | ||
| 25 | + protected Response.Status responseStatus() { | ||
| 26 | + return Response.Status.INTERNAL_SERVER_ERROR; | ||
| 27 | + } | ||
| 28 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.onos.rest.exceptions; | ||
| 17 | + | ||
| 18 | +import org.onlab.osgi.ServiceNotFoundException; | ||
| 19 | + | ||
| 20 | +import javax.ws.rs.core.Response; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * Mapper for service not found exceptions to the SERVICE_UNAVAILABLE response code. | ||
| 24 | + */ | ||
| 25 | +public class ServiceNotFoundMapper extends AbstractMapper<ServiceNotFoundException> { | ||
| 26 | + @Override | ||
| 27 | + protected Response.Status responseStatus() { | ||
| 28 | + return Response.Status.SERVICE_UNAVAILABLE; | ||
| 29 | + } | ||
| 30 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Various exception mappers to map errors to proper response status codes. | ||
| 19 | + */ | ||
| 20 | +package org.onlab.onos.rest.exceptions; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -24,8 +24,21 @@ | ... | @@ -24,8 +24,21 @@ |
| 24 | <servlet-name>JAX-RS Service</servlet-name> | 24 | <servlet-name>JAX-RS Service</servlet-name> |
| 25 | <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> | 25 | <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> |
| 26 | <init-param> | 26 | <init-param> |
| 27 | - <param-name>com.sun.jersey.config.property.packages</param-name> | 27 | + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name> |
| 28 | - <param-value>org.onlab.onos.rest</param-value> | 28 | + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value> |
| 29 | + </init-param> | ||
| 30 | + <init-param> | ||
| 31 | + <param-name>com.sun.jersey.config.property.classnames</param-name> | ||
| 32 | + <param-value> | ||
| 33 | + org.onlab.onos.rest.exceptions.EntityNotFoundMapper, | ||
| 34 | + org.onlab.onos.rest.exceptions.ServiceNotFoundMapper, | ||
| 35 | + org.onlab.onos.rest.exceptions.ServerErrorMapper, | ||
| 36 | + org.onlab.onos.rest.JsonBodyWriter, | ||
| 37 | + | ||
| 38 | + org.onlab.onos.rest.DevicesWebResource, | ||
| 39 | + org.onlab.onos.rest.LinksWebResource, | ||
| 40 | + org.onlab.onos.rest.ConfigResource | ||
| 41 | + </param-value> | ||
| 29 | </init-param> | 42 | </init-param> |
| 30 | <load-on-startup>1</load-on-startup> | 43 | <load-on-startup>1</load-on-startup> |
| 31 | </servlet> | 44 | </servlet> | ... | ... |
| ... | @@ -109,6 +109,10 @@ | ... | @@ -109,6 +109,10 @@ |
| 109 | <plugins> | 109 | <plugins> |
| 110 | <plugin> | 110 | <plugin> |
| 111 | <groupId>org.apache.felix</groupId> | 111 | <groupId>org.apache.felix</groupId> |
| 112 | + <artifactId>maven-scr-plugin</artifactId> | ||
| 113 | + </plugin> | ||
| 114 | + <plugin> | ||
| 115 | + <groupId>org.apache.felix</groupId> | ||
| 112 | <artifactId>maven-bundle-plugin</artifactId> | 116 | <artifactId>maven-bundle-plugin</artifactId> |
| 113 | <extensions>true</extensions> | 117 | <extensions>true</extensions> |
| 114 | <configuration> | 118 | <configuration> |
| ... | @@ -120,13 +124,15 @@ | ... | @@ -120,13 +124,15 @@ |
| 120 | <Import-Package> | 124 | <Import-Package> |
| 121 | org.slf4j, | 125 | org.slf4j, |
| 122 | org.osgi.framework, | 126 | org.osgi.framework, |
| 123 | - javax.ws.rs,javax.ws.rs.core, | 127 | + javax.ws.rs,javax.ws.rs.core,javax.ws.rs.ext, |
| 124 | com.sun.jersey.api.core, | 128 | com.sun.jersey.api.core, |
| 125 | com.sun.jersey.spi.container.servlet, | 129 | com.sun.jersey.spi.container.servlet, |
| 126 | com.sun.jersey.server.impl.container.servlet, | 130 | com.sun.jersey.server.impl.container.servlet, |
| 127 | com.fasterxml.jackson.databind, | 131 | com.fasterxml.jackson.databind, |
| 128 | com.fasterxml.jackson.databind.node, | 132 | com.fasterxml.jackson.databind.node, |
| 129 | com.google.common.base.*, | 133 | com.google.common.base.*, |
| 134 | + org.onlab.api.*, | ||
| 135 | + org.onlab.osgi.*, | ||
| 130 | org.onlab.packet.*, | 136 | org.onlab.packet.*, |
| 131 | org.onlab.rest.*, | 137 | org.onlab.rest.*, |
| 132 | org.onlab.onos.* | 138 | org.onlab.onos.* | ... | ... |
-
Please register or login to post a comment