11package com .github .dockerjava .api .model ;
22
3- 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-
143import com .fasterxml .jackson .core .JsonGenerator ;
154import com .fasterxml .jackson .core .JsonParser ;
165import com .fasterxml .jackson .core .JsonProcessingException ;
2312import com .fasterxml .jackson .databind .annotation .JsonDeserialize ;
2413import com .fasterxml .jackson .databind .annotation .JsonSerialize ;
2514import 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 ;
2625
2726/**
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 // }
110109
111- /**
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 {
134119
135- 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 }
149130
150131 /**
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 }
160160
161161 /**
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 }
168168
169169 /**
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 }
175190
176191 /**
@@ -182,16 +197,17 @@ public String getHostIp() {
182197 }
183198
184199 /**
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 }
190206
191207 /**
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 }
207223
208224 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 }
241257
242258 @ 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 ();
0 commit comments