Merge pull request #575 from docker-java/issue-556 · docker-java/docker-java@bf9a57a

11

package com.github.dockerjava.api.model;

223-

import static org.apache.commons.lang.StringUtils.isEmpty;

4-5-

import java.io.IOException;

6-

import java.util.HashMap;

7-

import java.util.Iterator;

8-

import java.util.Map;

9-

import java.util.Map.Entry;

10-11-

import org.apache.commons.lang.ArrayUtils;

12-

import org.apache.commons.lang.builder.EqualsBuilder;

13-143

import com.fasterxml.jackson.core.JsonGenerator;

154

import com.fasterxml.jackson.core.JsonParser;

165

import com.fasterxml.jackson.core.JsonProcessingException;

@@ -23,6 +12,16 @@

2312

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

2413

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

2514

import com.fasterxml.jackson.databind.node.NullNode;

15+

import org.apache.commons.lang.ArrayUtils;

16+

import org.apache.commons.lang.builder.EqualsBuilder;

17+18+

import java.io.IOException;

19+

import java.util.HashMap;

20+

import java.util.Iterator;

21+

import java.util.Map;

22+

import java.util.Map.Entry;

23+24+

import static org.apache.commons.lang.StringUtils.isEmpty;

26252726

/**

2827

* A container for port bindings, made available as a {@link Map} via its {@link #getBindings()} method.

@@ -108,69 +107,85 @@ public Map<ExposedPort, Binding[]> getBindings() {

108107

// return bindings.toArray(new PortBinding[bindings.size()]);

109108

// }

110109111-

/**

112-

* Creates a {@link Binding} for the given IP address and port number.

113-

*/

114-

public static Binding binding(String hostIp, Integer hostPort) {

115-

return new Binding(hostIp, hostPort);

116-

}

117-118-

/**

119-

* Creates a {@link Binding} for the given port number, leaving the IP address undefined.

120-

*/

121-

public static Binding binding(Integer hostPort) {

122-

return new Binding(hostPort);

123-

}

124-125110

/**

126111

* A {@link Binding} represents a socket on the Docker host that is used in a {@link PortBinding}. It is characterized by an

127-

* {@link #getHostIp() IP address} and a {@link #getHostPort() port number}. Both properties may be <code>null</code> in order to let

128-

* Docker assign them dynamically/using defaults.

112+

* {@link #getHostIp() IP address} and a {@link #getHostPortSpec() port spec}. Both properties may be <code>null</code> in order to

113+

* let Docker assign them dynamically/using defaults.

129114

*

130115

* @see Ports#bind(ExposedPort, Binding)

131116

* @see ExposedPort

132117

*/

133118

public static class Binding {

134119135-

private final String hostIp;

136-137-

private final Integer hostPort;

138-139120

/**

140-

* Creates a {@link Binding} for the given {@link #getHostIp() IP address} and {@link #getHostPort() port number}.

121+

* Creates a {@link Binding} for the given {@link #getHostPortSpec() port spec}, leaving the {@link #getHostIp() IP address}

122+

* undefined.

141123

*

142124

* @see Ports#bind(ExposedPort, Binding)

143125

* @see ExposedPort

144126

*/

145-

public Binding(String hostIp, Integer hostPort) {

146-

this.hostIp = isEmpty(hostIp) ? null : hostIp;

147-

this.hostPort = hostPort;

127+

public static Binding bindPortSpec(String portSpec) {

128+

return new Binding(null, portSpec);

148129

}

149130150131

/**

151-

* Creates a {@link Binding} for the given {@link #getHostPort() port number}, leaving the {@link #getHostIp() IP address}

132+

* Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPortSpec() port spec}

133+

* undefined.

134+

*/

135+

public static Binding bindIp(String hostIp) {

136+

return new Binding(hostIp, null);

137+

}

138+139+

/**

140+

* Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port number.

141+

*/

142+

public static Binding bindIpAndPort(String hostIp, int port) {

143+

return new Binding(hostIp, "" + port);

144+

}

145+146+

/**

147+

* Creates a {@link Binding} for the given {@link #getHostIp() IP address} and port range.

148+

*/

149+

public static Binding bindIpAndPortRange(String hostIp, int lowPort, int highPort) {

150+

return new Binding(hostIp, lowPort + "-" + highPort);

151+

}

152+153+

/**

154+

* Creates a {@link Binding} for the given port range, leaving the {@link #getHostIp() IP address}

152155

* undefined.

153-

*

154-

* @see Ports#bind(ExposedPort, Binding)

155-

* @see ExposedPort

156156

*/

157-

public Binding(Integer hostPort) {

158-

this(null, hostPort);

157+

public static Binding bindPortRange(int lowPort, int highPort) {

158+

return bindIpAndPortRange(null, lowPort, highPort);

159159

}

160160161161

/**

162-

* Creates a {@link Binding} for the given {@link #getHostIp() IP address}, leaving the {@link #getHostPort() port number}

162+

* Creates a {@link Binding} for the given port leaving the {@link #getHostIp() IP address}

163163

* undefined.

164164

*/

165-

public Binding(String hostIp) {

166-

this(hostIp, null);

165+

public static Binding bindPort(int port) {

166+

return bindIpAndPort(null, port);

167167

}

168168169169

/**

170-

* Creates a {@link Binding} with both {@link #getHostIp() IP address} and {@link #getHostPort() port number} undefined.

170+

* Creates an empty {@link Binding}.

171171

*/

172-

public Binding() {

173-

this(null, null);

172+

public static Binding empty() {

173+

return new Binding(null, null);

174+

}

175+176+

private final String hostIp;

177+178+

private final String hostPortSpec;

179+180+

/**

181+

* Creates a {@link Binding} for the given {@link #getHostIp() host IP address} and {@link #getHostPortSpec() host port spec}.

182+

*

183+

* @see Ports#bind(ExposedPort, Binding)

184+

* @see ExposedPort

185+

*/

186+

public Binding(String hostIp, String hostPortSpec) {

187+

this.hostIp = isEmpty(hostIp) ? null : hostIp;

188+

this.hostPortSpec = hostPortSpec;

174189

}

175190176191

/**

@@ -182,16 +197,17 @@ public String getHostIp() {

182197

}

183198184199

/**

185-

* @return the port number on the Docker host. May be <code>null</code>, in which case Docker will dynamically assign a port.

200+

* @return the port spec for the binding on the Docker host. May reference a single port ("1234"), a port range ("1234-2345") or

201+

* <code>null</code>, in which case Docker will dynamically assign a port.

186202

*/

187-

public Integer getHostPort() {

188-

return hostPort;

203+

public String getHostPortSpec() {

204+

return hostPortSpec;

189205

}

190206191207

/**

192208

* Parses a textual host and port specification (as used by the Docker CLI) to a {@link Binding}.

193209

* <p>

194-

* Legal syntax: <code>IP|IP:port|port</code>

210+

* Legal syntax: <code>IP|IP:portSpec|portSpec</code> where <code>portSpec</code> is either a single port or a port range

195211

*

196212

* @param serialized

197213

* serialized the specification, e.g. <code>127.0.0.1:80</code>

@@ -202,16 +218,16 @@ public Integer getHostPort() {

202218

public static Binding parse(String serialized) throws IllegalArgumentException {

203219

try {

204220

if (serialized.isEmpty()) {

205-

return new Binding();

221+

return Binding.empty();

206222

}

207223208224

String[] parts = serialized.split(":");

209225

switch (parts.length) {

210226

case 2: {

211-

return new Binding(parts[0], Integer.valueOf(parts[1]));

227+

return new Binding(parts[0], parts[1]);

212228

}

213229

case 1: {

214-

return parts[0].contains(".") ? new Binding(parts[0]) : new Binding(Integer.valueOf(parts[0]));

230+

return parts[0].contains(".") ? Binding.bindIp(parts[0]) : Binding.bindPortSpec(parts[0]);

215231

}

216232

default: {

217233

throw new IllegalArgumentException();

@@ -231,19 +247,19 @@ public static Binding parse(String serialized) throws IllegalArgumentException {

231247

@Override

232248

public String toString() {

233249

if (isEmpty(hostIp)) {

234-

return Integer.toString(hostPort);

235-

} else if (hostPort == null) {

250+

return hostPortSpec;

251+

} else if (hostPortSpec == null) {

236252

return hostIp;

237253

} else {

238-

return hostIp + ":" + hostPort;

254+

return hostIp + ":" + hostPortSpec;

239255

}

240256

}

241257242258

@Override

243259

public boolean equals(Object obj) {

244260

if (obj instanceof Binding) {

245261

Binding other = (Binding) obj;

246-

return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPort, other.getHostPort())

262+

return new EqualsBuilder().append(hostIp, other.getHostIp()).append(hostPortSpec, other.getHostPortSpec())

247263

.isEquals();

248264

} else {

249265

return super.equals(obj);

@@ -270,7 +286,7 @@ public Ports deserialize(JsonParser jsonParser, DeserializationContext deseriali

270286

JsonNode bindingNode = bindingsArray.get(i);

271287

if (!bindingNode.equals(NullNode.getInstance())) {

272288

String hostIp = bindingNode.get("HostIp").textValue();

273-

int hostPort = bindingNode.get("HostPort").asInt();

289+

String hostPort = bindingNode.get("HostPort").textValue();

274290

out.bind(ExposedPort.parse(portNode.getKey()), new Binding(hostIp, hostPort));

275291

}

276292

}

@@ -294,8 +310,7 @@ public void serialize(Ports portBindings, JsonGenerator jsonGen, SerializerProvi

294310

for (Binding binding : entry.getValue()) {

295311

jsonGen.writeStartObject();

296312

jsonGen.writeStringField("HostIp", binding.getHostIp() == null ? "" : binding.getHostIp());

297-

jsonGen.writeStringField("HostPort", binding.getHostPort() == null ? "" : binding.getHostPort()

298-

.toString());

313+

jsonGen.writeStringField("HostPort", binding.getHostPortSpec() == null ? "" : binding.getHostPortSpec());

299314

jsonGen.writeEndObject();

300315

}

301316

jsonGen.writeEndArray();