1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2000-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 package com.ericsson.otp.erlang;
21 
22 /**
23  * Provides a Java representation of Erlang ports.
24  */
25 public class OtpErlangPort extends OtpErlangObject {
26     // don't change this!
27     private static final long serialVersionUID = 4037115468007644704L;
28 
29     private final String node;
30     private final int id;
31     private final int creation;
32 
33     /*
34      * Create a unique Erlang port belonging to the local node. Since it isn't
35      * meaninful to do so, this constructor is private...
36      *
37      * @param self the local node.
38      *
39      * @deprecated use OtpLocalNode:createPort() instead
40      */
41     @SuppressWarnings("unused")
OtpErlangPort(final OtpSelf self)42     private OtpErlangPort(final OtpSelf self) {
43         final OtpErlangPort p = self.createPort();
44 
45         id = p.id;
46         creation = p.creation;
47         node = p.node;
48     }
49 
50     /**
51      * Create an Erlang port from a stream containing a port encoded in Erlang
52      * external format.
53      *
54      * @param buf
55      *            the stream containing the encoded port.
56      *
57      * @exception OtpErlangDecodeException
58      *                if the buffer does not contain a valid external
59      *                representation of an Erlang port.
60      */
OtpErlangPort(final OtpInputStream buf)61     public OtpErlangPort(final OtpInputStream buf)
62             throws OtpErlangDecodeException {
63         final OtpErlangPort p = buf.read_port();
64 
65         node = p.node();
66         id = p.id();
67         creation = p.creation();
68     }
69 
70     /**
71      * Create an Erlang port from its components.
72      *
73      * @param node
74      *            the nodename.
75      *
76      * @param id
77      *            an arbitrary number. Only the low order 28 bits will be used.
78      *
79      * @param creation
80      *            another arbitrary number. Only the low order 2 bits will be used.
81      */
OtpErlangPort(final String node, final int id, final int creation)82     public OtpErlangPort(final String node, final int id, final int creation) {
83         this(OtpExternal.portTag, node, id, creation);
84     }
85 
86     /**
87      * Create an Erlang port from its components.
88      *
89      * @param tag
90      *            the external format to be compliant with.
91      *            OtpExternal.portTag where only a subset of the bits are used (see other constructor)
92      *            OtpExternal.newPortTag where all 32 bits of id and creation are significant.
93      *            newPortTag can only be decoded by OTP-19 and newer.
94      * @param node
95      *            the nodename.
96      *
97      * @param id
98      *            an arbitrary number. Only the low order 28 bits will be used.
99      *
100      * @param creation
101      *            another arbitrary number.
102      */
OtpErlangPort(final int tag, final String node, final int id, final int creation)103     public OtpErlangPort(final int tag, final String node, final int id,
104 			 final int creation) {
105 	this.node = node;
106 	if (tag == OtpExternal.portTag) {
107 	    this.id = id & 0xfffffff; // 28 bits
108 	    this.creation = creation & 0x3; // 2 bits
109 	}
110 	else {
111 	    this.id = id;
112 	    this.creation = creation;
113 	}
114     }
115 
tag()116     protected int tag() {
117         return OtpExternal.newPortTag;
118     }
119 
120     /**
121      * Get the id number from the port.
122      *
123      * @return the id number from the port.
124      */
id()125     public int id() {
126         return id;
127     }
128 
129     /**
130      * Get the creation number from the port.
131      *
132      * @return the creation number from the port.
133      */
creation()134     public int creation() {
135         return creation;
136     }
137 
138     /**
139      * Get the node name from the port.
140      *
141      * @return the node name from the port.
142      */
node()143     public String node() {
144         return node;
145     }
146 
147     /**
148      * Get the string representation of the port. Erlang ports are printed as
149      * #Port<node.id>.
150      *
151      * @return the string representation of the port.
152      */
153     @Override
toString()154     public String toString() {
155         return "#Port<" + node + "." + id + ">";
156     }
157 
158     /**
159      * Convert this port to the equivalent Erlang external representation.
160      *
161      * @param buf
162      *            an output stream to which the encoded port should be written.
163      */
164     @Override
encode(final OtpOutputStream buf)165     public void encode(final OtpOutputStream buf) {
166         buf.write_port(this);
167     }
168 
169     /**
170      * Determine if two ports are equal. Ports are equal if their components are
171      * equal.
172      *
173      * @param o
174      *            the other port to compare to.
175      *
176      * @return true if the ports are equal, false otherwise.
177      */
178     @Override
equals(final Object o)179     public boolean equals(final Object o) {
180         if (!(o instanceof OtpErlangPort)) {
181             return false;
182         }
183 
184         final OtpErlangPort port = (OtpErlangPort) o;
185 
186         return creation == port.creation && id == port.id
187                 && node.compareTo(port.node) == 0;
188     }
189 
190     @Override
doHashCode()191     protected int doHashCode() {
192         final OtpErlangObject.Hash hash = new OtpErlangObject.Hash(6);
193         hash.combine(creation);
194         hash.combine(id, node.hashCode());
195         return hash.valueOf();
196     }
197 }
198