2 * (c) 2015 Cable Television Laboratories, Inc. All rights reserved.
5 package org.pcmm.rcd.impl;
7 import com.fasterxml.jackson.annotation.JsonProperty;
8 import com.fasterxml.jackson.databind.ObjectMapper;
9 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
10 import org.pcmm.gates.IGateSpec.Direction;
11 import org.pcmm.rcd.ICMTS;
13 import java.io.FileInputStream;
14 import java.io.IOException;
15 import java.net.Socket;
17 import java.util.concurrent.ConcurrentHashMap;
20 * Mock CMTS that can be used for testing. startServer() is called to start required threads after instantiation.
22 public class CMTS extends AbstractPCMMServer implements ICMTS {
25 * Receives messages from the COPS client
27 private final Map<String, IPCMMClientHandler> handlerMap;
30 * The configured gates
32 private final Map<Direction, Set<String>> gateConfig;
35 * The connected CMTSs and whether or not they are up
37 private final Map<String, Boolean> cmStatus;
40 * Constructor for having the server port automatically assigned
41 * Call getPort() after startServer() is called to determine the port number of the server
43 public CMTS(final Map<Direction, Set<String>> gateConfig, final Map<String, Boolean> cmStatus) {
44 this(0, gateConfig, cmStatus);
48 * Constructor for starting the server to a pre-defined port number
49 * @param port - the port number on which to start the server.
51 public CMTS(final int port, final Map<Direction, Set<String>> gateConfig, final Map<String, Boolean> cmStatus) {
53 if (gateConfig == null || cmStatus == null) throw new IllegalArgumentException("Config must not be null");
54 this.gateConfig = Collections.unmodifiableMap(gateConfig);
55 this.cmStatus = Collections.unmodifiableMap(cmStatus);
56 handlerMap = new ConcurrentHashMap<>();
60 public void stopServer() {
61 for (final IPCMMClientHandler handler : handlerMap.values()) {
68 protected IPCMMClientHandler getPCMMClientHandler(final Socket socket) throws IOException {
69 final String key = socket.getLocalAddress().getHostName() + ':' + socket.getPort();
70 if (handlerMap.get(key) == null) {
71 final IPCMMClientHandler handler = new CmtsPcmmClientHandler(socket, gateConfig, cmStatus);
73 handlerMap.put(key, handler);
75 } else return handlerMap.get(key);
80 * @param args - the arguments which will contain configuration information
81 * @throws IOException - should the server fail to start for reasons such as port contention.
83 public static void main(final String[] args) throws IOException {
84 final CmtsYaml config = getConfig(args[0]);
85 final CMTS cmts = new CMTS(config.port, config.getGates(), config.getCmStatus());
90 * Returns the object that represents the YAML file
91 * @param uri - the location of the YAML file
92 * @return - the config object
93 * @throws IOException - when the URI does not contain the proper YAML file
95 private static CmtsYaml getConfig(final String uri) throws IOException {
96 final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
97 return mapper.readValue(new FileInputStream(uri), CmtsYaml.class);
101 * Class to hold configuration settings in a YAML file
103 public static class CmtsYaml {
104 @JsonProperty("port")
107 @JsonProperty("gates")
108 private Collection<GateConfigYaml> gateConfigs;
110 @JsonProperty("cmStatuses")
111 private Collection<CmStatusYaml> cmStatuses;
113 public Map<Direction, Set<String>> getGates() {
114 final Map<Direction, Set<String>> out = new HashMap<>();
116 for (final GateConfigYaml gateConfig : gateConfigs) {
117 final Direction direction;
118 if (gateConfig.gateType.equalsIgnoreCase("UPSTREAM")) {
119 direction = Direction.UPSTREAM;
120 } else if (gateConfig.gateType.equalsIgnoreCase("DOWNSTREAM")) {
121 direction = Direction.DOWNSTREAM;
122 } else direction = null;
124 if (direction != null) {
125 out.put(direction, gateConfig.gateNames);
131 public Map<String, Boolean> getCmStatus() {
132 final Map<String, Boolean> out = new HashMap<>();
134 for (final CmStatusYaml cmStatus : cmStatuses) {
135 out.put(cmStatus.hostIp, cmStatus.status);
142 * Class to hold the YAML gate configuration values
144 public static class GateConfigYaml {
145 @JsonProperty("type")
146 private String gateType;
148 @JsonProperty("names")
149 private Set<String> gateNames;
153 * Class to hold the YAML Cable Modem configuration values
155 public static class CmStatusYaml {
156 @JsonProperty("host")
157 private String hostIp;
159 @JsonProperty("status")
160 private boolean status;