2 * Copyright (c) 2015 Cable Television Laboratories, Inc. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.pcmm.rcd.impl;
11 import com.fasterxml.jackson.annotation.JsonProperty;
12 import com.fasterxml.jackson.databind.ObjectMapper;
13 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
14 import org.pcmm.gates.IGateSpec.Direction;
15 import org.pcmm.rcd.ICMTS;
17 import java.io.FileInputStream;
18 import java.io.IOException;
19 import java.net.Socket;
21 import java.util.concurrent.ConcurrentHashMap;
24 * Mock CMTS that can be used for testing. startServer() is called to start required threads after instantiation.
26 public class CMTS extends AbstractPCMMServer implements ICMTS {
29 * Receives messages from the COPS client
31 private final Map<String, IPCMMClientHandler> handlerMap;
34 * The configured gates
36 private final Map<Direction, Set<String>> gateConfig;
39 * The connected CMTSs and whether or not they are up
41 private final Map<String, Boolean> cmStatus;
44 * Constructor for having the server port automatically assigned
45 * Call getPort() after startServer() is called to determine the port number of the server
47 public CMTS(final Map<Direction, Set<String>> gateConfig, final Map<String, Boolean> cmStatus) {
48 this(0, gateConfig, cmStatus);
52 * Constructor for starting the server to a pre-defined port number
53 * @param port - the port number on which to start the server.
55 public CMTS(final int port, final Map<Direction, Set<String>> gateConfig, final Map<String, Boolean> cmStatus) {
57 if (gateConfig == null || cmStatus == null) throw new IllegalArgumentException("Config must not be null");
58 this.gateConfig = Collections.unmodifiableMap(gateConfig);
59 this.cmStatus = Collections.unmodifiableMap(cmStatus);
60 handlerMap = new ConcurrentHashMap<>();
64 public void stopServer() {
65 for (final IPCMMClientHandler handler : handlerMap.values()) {
72 protected IPCMMClientHandler getPCMMClientHandler(final Socket socket) throws IOException {
73 final String key = socket.getLocalAddress().getHostName() + ':' + socket.getPort();
74 if (handlerMap.get(key) == null) {
75 final IPCMMClientHandler handler = new CmtsPcmmClientHandler(socket, gateConfig, cmStatus);
77 handlerMap.put(key, handler);
79 } else return handlerMap.get(key);
84 * @param args - the arguments which will contain configuration information
85 * @throws IOException - should the server fail to start for reasons such as port contention.
87 public static void main(final String[] args) throws IOException {
88 final CmtsYaml config = getConfig(args[0]);
89 final CMTS cmts = new CMTS(config.port, config.getGates(), config.getCmStatus());
94 * Returns the object that represents the YAML file
95 * @param uri - the location of the YAML file
96 * @return - the config object
97 * @throws IOException - when the URI does not contain the proper YAML file
99 private static CmtsYaml getConfig(final String uri) throws IOException {
100 final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
101 return mapper.readValue(new FileInputStream(uri), CmtsYaml.class);
105 * Class to hold configuration settings in a YAML file
107 public static class CmtsYaml {
108 @JsonProperty("port")
111 @JsonProperty("gates")
112 private Collection<GateConfigYaml> gateConfigs;
114 @JsonProperty("cmStatuses")
115 private Collection<CmStatusYaml> cmStatuses;
117 public Map<Direction, Set<String>> getGates() {
118 final Map<Direction, Set<String>> out = new HashMap<>();
120 for (final GateConfigYaml gateConfig : gateConfigs) {
121 final Direction direction;
122 if (gateConfig.gateType.equalsIgnoreCase("UPSTREAM")) {
123 direction = Direction.UPSTREAM;
124 } else if (gateConfig.gateType.equalsIgnoreCase("DOWNSTREAM")) {
125 direction = Direction.DOWNSTREAM;
126 } else direction = null;
128 if (direction != null) {
129 out.put(direction, gateConfig.gateNames);
135 public Map<String, Boolean> getCmStatus() {
136 final Map<String, Boolean> out = new HashMap<>();
138 for (final CmStatusYaml cmStatus : cmStatuses) {
139 out.put(cmStatus.hostIp, cmStatus.status);
146 * Class to hold the YAML gate configuration values
148 public static class GateConfigYaml {
149 @JsonProperty("type")
150 private String gateType;
152 @JsonProperty("names")
153 private Set<String> gateNames;
157 * Class to hold the YAML Cable Modem configuration values
159 public static class CmStatusYaml {
160 @JsonProperty("host")
161 private String hostIp;
163 @JsonProperty("status")
164 private boolean status;