Reference.java
// Copyright (c) ZeroC, Inc.
package com.zeroc.Ice;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* @hidden Public because it's used by the generated code.
*/
public abstract class Reference implements Cloneable {
public static final int ModeTwoway = 0;
public static final int ModeOneway = 1;
public static final int ModeBatchOneway = 2;
public static final int ModeDatagram = 3;
public static final int ModeBatchDatagram = 4;
public static final int ModeLast = ModeBatchDatagram;
/**
* Callback interface for asynchronous connection establishment.
*/
public interface GetConnectionCallback {
/**
* Sets the established connection.
*
* @param connection the established connection
* @param compress whether compression is enabled for the connection
*/
void setConnection(ConnectionI connection, boolean compress);
/**
* Sets an exception that occurred during connection establishment.
*
* @param ex the exception that occurred
*/
void setException(LocalException ex);
}
/**
* Returns true if this reference uses a batch mode.
*
* @return true if the reference is for batch oneway or batch datagram invocations
*/
public final boolean isBatch() {
return _mode == ModeBatchOneway || _mode == ModeBatchDatagram;
}
/**
* Returns true if this reference uses twoway mode.
*
* @return true if the reference is for twoway invocations
*/
public final boolean isTwoway() {
return _mode == ModeTwoway;
}
/**
* Gets the invocation mode for this reference.
*
* @return the invocation mode (twoway, oneway, etc.)
*/
public final int getMode() {
return _mode;
}
/**
* Gets the Ice protocol version for this reference.
*
* @return the protocol version
*/
public final ProtocolVersion getProtocol() {
return _protocol;
}
/**
* Gets the Slice encoding version for this reference.
*
* @return the encoding version
*/
public final EncodingVersion getEncoding() {
return _encoding;
}
/**
* Gets the object identity for this reference.
*
* @return the object identity
*/
public final Identity getIdentity() {
return _identity;
}
/**
* Gets the facet name for this reference.
*
* @return the facet name
*/
public final String getFacet() {
return _facet;
}
/**
* Gets the Ice instance associated with this reference.
*
* @return the Ice instance
*/
public final Instance getInstance() {
return _instance;
}
/**
* Gets the request context for this reference.
*
* @return the request context map
*/
public final Map<String, String> getContext() {
return _context;
}
/**
* Gets the invocation timeout for this reference.
*
* @return the invocation timeout
*/
public Duration getInvocationTimeout() {
return _invocationTimeout;
}
/**
* Gets the compression setting for this reference.
*
* @return the compression setting, or empty if not specified
*/
public Optional<Boolean> getCompress() {
return _compress;
}
/**
* Gets the communicator associated with this reference.
*
* @return the communicator
*/
public final Communicator getCommunicator() {
return _communicator;
}
/**
* Gets the endpoints for this reference.
*
* @return the array of endpoints
*/
public abstract EndpointI[] getEndpoints();
/**
* Gets the adapter ID for this reference.
*
* @return the adapter ID
*/
public abstract String getAdapterId();
/**
* Gets the router information for this reference.
*
* @return the router information
*/
public abstract RouterInfo getRouterInfo();
/**
* Gets the locator information for this reference.
*
* @return the locator information
*/
public abstract LocatorInfo getLocatorInfo();
/**
* Returns true if collocation optimization is enabled.
*
* @return true if collocation optimization is enabled
*/
public abstract boolean getCollocationOptimized();
/**
* Returns true if connection caching is enabled.
*
* @return true if connection caching is enabled
*/
public abstract boolean getCacheConnection();
/**
* Gets the endpoint selection type for this reference.
*
* @return the endpoint selection type
*/
public abstract EndpointSelectionType getEndpointSelection();
/**
* Gets the locator cache timeout for this reference.
*
* @return the locator cache timeout
*/
public abstract Duration getLocatorCacheTimeout();
/**
* Gets the connection ID for this reference.
*
* @return the connection ID
*/
public abstract String getConnectionId();
/**
* Gets the thread pool for this reference.
*
* @return the thread pool
*/
public abstract ThreadPool getThreadPool();
/**
* Gets the connection for this reference.
*
* @return the connection
*/
public abstract ConnectionI getConnection();
//
// The change* methods (here and in derived classes) create
// a new reference based on the existing one, with the
// corresponding value changed.
//
/**
* Creates a new reference with the specified context.
*
* @param newContext the new context map
* @return a new reference with the updated context
*/
public final Reference changeContext(Map<String, String> newContext) {
if (newContext == null) {
newContext = _emptyContext;
}
Reference r = _instance.referenceFactory().copy(this);
if (newContext.isEmpty()) {
r._context = _emptyContext;
} else {
r._context = new HashMap<>(newContext);
}
return r;
}
/**
* Creates a new reference with the specified invocation mode.
*
* @param newMode the new invocation mode
* @return a new reference with the updated mode
*/
public Reference changeMode(int newMode) {
Reference r = _instance.referenceFactory().copy(this);
r._mode = newMode;
return r;
}
/**
* Creates a new reference with the specified identity.
*
* @param newIdentity the new object identity
* @return a new reference with the updated identity
*/
public final Reference changeIdentity(Identity newIdentity) {
Reference r = _instance.referenceFactory().copy(this);
r._identity = newIdentity.clone();
return r;
}
/**
* Creates a new reference with the specified facet.
*
* @param newFacet the new facet name
* @return a new reference with the updated facet
*/
public final Reference changeFacet(String newFacet) {
Reference r = _instance.referenceFactory().copy(this);
r._facet = newFacet;
return r;
}
/**
* Creates a new reference with the specified invocation timeout.
*
* @param newTimeout the new invocation timeout
* @return a new reference with the updated timeout
*/
public final Reference changeInvocationTimeout(Duration newTimeout) {
Reference r = _instance.referenceFactory().copy(this);
r._invocationTimeout = newTimeout;
return r;
}
/**
* Creates a new reference with the specified encoding version.
*
* @param newEncoding the new encoding version
* @return a new reference with the updated encoding
*/
public Reference changeEncoding(EncodingVersion newEncoding) {
Reference r = _instance.referenceFactory().copy(this);
r._encoding = newEncoding;
return r;
}
/**
* Creates a new reference with the specified compression setting.
*
* @param newCompress the new compression setting
* @return a new reference with the updated compression setting
*/
public Reference changeCompress(boolean newCompress) {
Reference r = _instance.referenceFactory().copy(this);
r._compress = Optional.of(newCompress);
return r;
}
/**
* Creates a new reference with the specified adapter ID.
*
* @param newAdapterId the new adapter ID
* @return a new reference with the updated adapter ID
*/
public abstract Reference changeAdapterId(String newAdapterId);
/**
* Creates a new reference with the specified endpoints.
*
* @param newEndpoints the new endpoints
* @return a new reference with the updated endpoints
*/
public abstract Reference changeEndpoints(EndpointI[] newEndpoints);
/**
* Creates a new reference with the specified locator.
*
* @param newLocator the new locator proxy
* @return a new reference with the updated locator
*/
public abstract Reference changeLocator(LocatorPrx newLocator);
/**
* Creates a new reference with the specified router.
*
* @param newRouter the new router proxy
* @return a new reference with the updated router
*/
public abstract Reference changeRouter(RouterPrx newRouter);
/**
* Creates a new reference with the specified collocation optimization setting.
*
* @param newCollocationOptimized the new collocation optimization setting
* @return a new reference with the updated setting
*/
public abstract Reference changeCollocationOptimized(boolean newCollocationOptimized);
/**
* Creates a new reference with the specified connection caching setting.
*
* @param newCache the new connection caching setting
* @return a new reference with the updated setting
*/
public abstract Reference changeCacheConnection(boolean newCache);
/**
* Creates a new reference with the specified endpoint selection type.
*
* @param newType the new endpoint selection type
* @return a new reference with the updated selection type
*/
public abstract Reference changeEndpointSelection(EndpointSelectionType newType);
/**
* Creates a new reference with the specified locator cache timeout.
*
* @param newTimeout the new locator cache timeout
* @return a new reference with the updated timeout
*/
public abstract Reference changeLocatorCacheTimeout(Duration newTimeout);
/**
* Creates a new reference with the specified connection ID.
*
* @param connectionId the new connection ID
* @return a new reference with the updated connection ID
*/
public abstract Reference changeConnectionId(String connectionId);
/**
* Creates a new reference with the specified connection.
*
* @param connection the new connection
* @return a new reference with the updated connection
*/
public abstract Reference changeConnection(ConnectionI connection);
@Override
public int hashCode() {
int h = 5381;
h = HashUtil.hashAdd(h, _mode);
h = HashUtil.hashAdd(h, _identity);
h = HashUtil.hashAdd(h, _context);
h = HashUtil.hashAdd(h, _facet);
if (_compress.isPresent()) {
h = HashUtil.hashAdd(h, _compress.get());
}
// We don't include protocol and encoding in the hash; they are using 1.0 and 1.1,
// respectively.
h = HashUtil.hashAdd(h, _invocationTimeout.toMillis());
return h;
}
/**
* Gets the effective compression setting, taking into account the override.
*
* @return the effective compression setting
*/
public Optional<Boolean> getCompressOverride() {
DefaultsAndOverrides defaultsAndOverrides = getInstance().defaultsAndOverrides();
return defaultsAndOverrides.overrideCompress.isPresent()
? defaultsAndOverrides.overrideCompress
: _compress;
}
//
// Utility methods
//
/**
* Returns true if this is an indirect reference.
*
* @return true if this is an indirect reference
*/
public abstract boolean isIndirect();
/**
* Returns true if this is a well-known reference.
*
* @return true if this is a well-known reference
*/
public abstract boolean isWellKnown();
//
// Marshal the reference.
//
/**
* Writes this reference to an output stream.
*
* @param s the output stream to write to
*/
public void streamWrite(OutputStream s) {
//
// Don't write the identity here. Operations calling streamWrite
// write the identity.
//
//
// For compatibility with the old FacetPath.
//
if (_facet.isEmpty()) {
s.writeStringSeq(null);
} else {
String[] facetPath = {_facet};
s.writeStringSeq(facetPath);
}
s.writeByte((byte) _mode);
s.writeBool(false); // the secure field, no longer used.
if (!s.getEncoding().equals(Util.Encoding_1_0)) {
_protocol.ice_writeMembers(s);
_encoding.ice_writeMembers(s);
}
// Derived class writes the remainder of the reference.
}
//
// Convert the reference to its string form.
//
@Override
public String toString() {
//
// WARNING: Certain features, such as proxy validation in Glacier2,
// depend on the format of proxy strings. Changes to toString() and
// methods called to generate parts of the reference string could break
// these features. Please review for all features that depend on the
// format of proxyToString() before changing this and related code.
//
StringBuilder s = new StringBuilder(128);
ToStringMode toStringMode = _instance.toStringMode();
final String separators = " :@";
String id = Util.identityToString(_identity, toStringMode);
//
// If the encoded identity string contains characters which
// the reference parser uses as separators, then we enclose
// the identity string in quotes.
//
if (StringUtil.findFirstOf(id, separators) != -1) {
s.append('"');
s.append(id);
s.append('"');
} else {
s.append(id);
}
if (!_facet.isEmpty()) {
//
// If the encoded facet string contains characters which
// the reference parser uses as separators, then we enclose
// the facet string in quotes.
//
s.append(" -f ");
String fs = StringUtil.escapeString(_facet, "", toStringMode);
if (StringUtil.findFirstOf(fs, separators) != -1) {
s.append('"');
s.append(fs);
s.append('"');
} else {
s.append(fs);
}
}
switch (_mode) {
case ModeTwoway -> {} // Don't print the default mode.
case ModeOneway -> s.append(" -o");
case ModeBatchOneway -> s.append(" -O");
case ModeDatagram -> s.append(" -d");
case ModeBatchDatagram -> s.append(" -D");
}
if (!_protocol.equals(Util.Protocol_1_0)) {
// We print the protocol unless it's 1.0.
s.append(" -p ");
s.append(Util.protocolVersionToString(_protocol));
}
// We print the encoding if it's not 1.1 or if Ice.Default.EncodingVersion is set to
// something other than 1.1.
if (!_encoding.equals(Util.Encoding_1_1)
|| !_instance.defaultsAndOverrides().defaultEncoding.equals(Util.Encoding_1_1)) {
s.append(" -e ");
s.append(Util.encodingVersionToString(_encoding));
}
return s.toString();
// Derived class writes the remainder of the string.
}
//
// Convert the reference to its property form.
//
/**
* Converts this reference to its property form.
*
* @param prefix the property prefix to use
* @return a map of properties representing this reference
*/
public abstract Map<String, String> toProperty(String prefix);
/**
* Gets the request handler for this reference.
*
* @return the request handler
*/
abstract RequestHandler getRequestHandler();
/**
* Gets the batch request queue for this reference.
*
* @return the batch request queue
*/
abstract BatchRequestQueue getBatchRequestQueue();
@Override
public boolean equals(java.lang.Object obj) {
//
// Note: if(this == obj) and type test are performed by each non-abstract derived class.
//
Reference r = (Reference) obj; // Guaranteed to succeed.
if (_mode != r._mode) {
return false;
}
if (!_identity.equals(r._identity)) {
return false;
}
if (!_context.equals(r._context)) {
return false;
}
if (!_facet.equals(r._facet)) {
return false;
}
if (!_compress.equals(r._compress)) {
return false;
}
if (!_protocol.equals(r._protocol)) {
return false;
}
if (!_encoding.equals(r._encoding)) {
return false;
}
if (!_invocationTimeout.equals(r._invocationTimeout)) {
return false;
}
return true;
}
@Override
public Reference clone() {
Reference c = null;
try {
c = (Reference) super.clone();
} catch (CloneNotSupportedException ex) {
assert false;
}
return c;
}
private static final Map<String, String> _emptyContext = new HashMap<>();
private final Instance _instance;
private final Communicator _communicator;
private int _mode;
private Optional<Boolean> _compress;
private Identity _identity;
private Map<String, String> _context;
private String _facet;
private final ProtocolVersion _protocol;
private EncodingVersion _encoding;
private Duration _invocationTimeout;
/**
* Constructs a new Reference with the specified parameters.
*
* @param instance the Ice instance
* @param communicator the communicator
* @param identity the object identity
* @param facet the facet name
* @param mode the invocation mode
* @param compress the compression setting
* @param protocol the protocol version
* @param encoding the encoding version
* @param invocationTimeout the invocation timeout
* @param context the request context
*/
protected Reference(
Instance instance,
Communicator communicator,
Identity identity,
String facet,
int mode,
Optional<Boolean> compress,
ProtocolVersion protocol,
EncodingVersion encoding,
Duration invocationTimeout,
Map<String, String> context) {
//
// Validate string arguments.
//
assert (identity.name != null);
assert (identity.category != null);
assert (facet != null);
_instance = instance;
_communicator = communicator;
_mode = mode;
_compress = compress;
_identity = identity;
_context = context != null ? new HashMap<>(context) : _emptyContext;
_facet = facet;
_protocol = protocol;
_encoding = encoding;
_invocationTimeout = invocationTimeout;
}
}