// **********************************************************************
//
// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
package IceInternal;
public final class LocatorInfo
{
interface GetEndpointsCallback
{
void setEndpoints(EndpointI[] endpoints, boolean cached);
void setException(Ice.LocalException ex);
}
private static class RequestCallback
{
public void
response(LocatorInfo locatorInfo, Ice.ObjectPrx proxy)
{
EndpointI[] endpoints = null;
if(proxy != null)
{
Reference r = ((Ice.ObjectPrxHelperBase)proxy).__reference();
if(!r.isIndirect())
{
endpoints = r.getEndpoints();
}
else if(_ref.isWellKnown() && !r.isWellKnown())
{
//
// We're resolving the endpoints of a well-known object and the proxy returned
// by the locator is an indirect proxy. We now need to resolve the endpoints
// of this indirect proxy.
//
locatorInfo.getEndpoints(r, _ref, _ttl, _callback);
return;
}
}
if(_ref.getInstance().traceLevels().location >= 1)
{
locatorInfo.getEndpointsTrace(_ref, endpoints, false);
}
if(_callback != null)
{
_callback.setEndpoints(endpoints == null ? new EndpointI[0] : endpoints, false);
}
}
public void
exception(LocatorInfo locatorInfo, Exception exc)
{
try
{
locatorInfo.getEndpointsException(_ref, exc); // This throws.
}
catch(Ice.LocalException ex)
{
if(_callback != null)
{
_callback.setException(ex);
}
}
}
RequestCallback(Reference ref, int ttl, GetEndpointsCallback cb)
{
_ref = ref;
_ttl = ttl;
_callback = cb;
}
final Reference _ref;
final int _ttl;
final GetEndpointsCallback _callback;
};
private abstract class Request
{
synchronized public void
addCallback(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback cb)
{
RequestCallback callback = new RequestCallback(ref, ttl, cb);
if(_response)
{
callback.response(_locatorInfo, _proxy);
}
else if(_exception != null)
{
callback.exception(_locatorInfo, _exception);
}
else
{
_callbacks.add(callback);
if(wellKnownRef != null) // This request is to resolve the endpoints of a cached well-known object ref
{
_wellKnownRefs.add(wellKnownRef);
}
if(!_sent)
{
_sent = true;
send(true);
}
}
}
synchronized EndpointI[]
getEndpoints(Reference ref, Reference wellKnownRef, int ttl, Ice.BooleanHolder cached)
{
if(!_response || _exception == null)
{
if(wellKnownRef != null) // This request is to resolve the endpoints of a cached well-known object ref
{
_wellKnownRefs.add(wellKnownRef);
}
if(!_sent)
{
_sent = true;
send(true);
}
while(!_response && _exception == null)
{
try
{
wait();
}
catch(java.lang.InterruptedException ex)
{
}
}
}
if(_exception != null)
{
_locatorInfo.getEndpointsException(ref, _exception); // This throws.
}
assert(_response);
EndpointI[] endpoints = null;
if(_proxy != null)
{
Reference r = ((Ice.ObjectPrxHelperBase)_proxy).__reference();
if(!r.isIndirect())
{
endpoints = r.getEndpoints();
}
else if(ref.isWellKnown() && !r.isWellKnown())
{
//
// We're resolving the endpoints of a well-known object and the proxy returned
// by the locator is an indirect proxy. We now need to resolve the endpoints
// of this indirect proxy.
//
return _locatorInfo.getEndpoints(r, ref, ttl, cached);
}
}
cached.value = false;
if(_ref.getInstance().traceLevels().location >= 1)
{
_locatorInfo.getEndpointsTrace(ref, endpoints, false);
}
return endpoints == null ? new EndpointI[0] : endpoints;
}
Request(LocatorInfo locatorInfo, Reference ref)
{
_locatorInfo = locatorInfo;
_ref = ref;
_sent = false;
_response = false;
}
synchronized protected void
response(Ice.ObjectPrx proxy)
{
_locatorInfo.finishRequest(_ref, _wellKnownRefs, proxy, false);
_response = true;
_proxy = proxy;
for(RequestCallback callback : _callbacks)
{
callback.response(_locatorInfo, proxy);
}
notifyAll();
}
protected void
exception(Exception ex)
{
if(ex instanceof Ice.CollocationOptimizationException)
{
send(false); // Use synchronous collocation optimized locator request instead.
return;
}
synchronized(this)
{
_locatorInfo.finishRequest(_ref, _wellKnownRefs, null, ex instanceof Ice.UserException);
_exception = ex;
for(RequestCallback callback : _callbacks)
{
callback.exception(_locatorInfo, ex);
}
notifyAll();
}
}
protected abstract void send(boolean async);
final protected LocatorInfo _locatorInfo;
final protected Reference _ref;
private java.util.List<RequestCallback> _callbacks = new java.util.ArrayList<RequestCallback>();
private java.util.List<Reference> _wellKnownRefs = new java.util.ArrayList<Reference>();
private boolean _sent;
private boolean _response;
private Ice.ObjectPrx _proxy;
private Exception _exception;
};
private class ObjectRequest extends Request
{
public ObjectRequest(LocatorInfo locatorInfo, Reference reference)
{
super(locatorInfo, reference);
assert(reference.isWellKnown());
}
protected void
send(boolean async)
{
try
{
if(async)
{
_locatorInfo.getLocator().findObjectById_async(
new Ice.AMI_Locator_findObjectById()
{
public void
ice_response(Ice.ObjectPrx proxy)
{
ObjectRequest.this.response(proxy);
}
public void
ice_exception(Ice.UserException ex)
{
ObjectRequest.this.exception(ex);
}
public void
ice_exception(Ice.LocalException ex)
{
ObjectRequest.this.exception(ex);
}
},
_ref.getIdentity());
}
else
{
response(_locatorInfo.getLocator().findObjectById(_ref.getIdentity()));
}
}
catch(Exception ex)
{
exception(ex);
}
}
};
private class AdapterRequest extends Request
{
public AdapterRequest(LocatorInfo locatorInfo, Reference reference)
{
super(locatorInfo, reference);
assert(reference.isIndirect());
}
protected void
send(boolean async)
{
try
{
if(async)
{
_locatorInfo.getLocator().findAdapterById_async(
new Ice.AMI_Locator_findAdapterById()
{
public void
ice_response(Ice.ObjectPrx proxy)
{
AdapterRequest.this.response(proxy);
}
public void
ice_exception(Ice.UserException ex)
{
AdapterRequest.this.exception(ex);
}
public void
ice_exception(Ice.LocalException ex)
{
AdapterRequest.this.exception(ex);
}
},
_ref.getAdapterId());
}
else
{
response(_locatorInfo.getLocator().findAdapterById(_ref.getAdapterId()));
}
}
catch(Exception ex)
{
exception(ex);
}
}
};
LocatorInfo(Ice.LocatorPrx locator, LocatorTable table, boolean background)
{
_locator = locator;
_table = table;
_background = background;
}
synchronized public void
destroy()
{
_locatorRegistry = null;
_table.clear();
}
public boolean
equals(java.lang.Object obj)
{
if(this == obj)
{
return true;
}
if(obj instanceof LocatorInfo)
{
return _locator.equals(((LocatorInfo)obj)._locator);
}
return false;
}
public int
hashCode()
{
return _locator.hashCode();
}
public Ice.LocatorPrx
getLocator()
{
//
// No synchronization necessary, _locator is immutable.
//
return _locator;
}
public Ice.LocatorRegistryPrx
getLocatorRegistry()
{
synchronized(this)
{
if(_locatorRegistry != null)
{
return _locatorRegistry;
}
}
//
// Do not make locator calls from within sync.
//
Ice.LocatorRegistryPrx locatorRegistry = _locator.getRegistry();
synchronized(this)
{
//
// The locator registry can't be located.
//
_locatorRegistry = Ice.LocatorRegistryPrxHelper.uncheckedCast(locatorRegistry.ice_locator(null));
return _locatorRegistry;
}
}
public EndpointI[]
getEndpoints(Reference ref, int ttl, Ice.BooleanHolder cached)
{
return getEndpoints(ref, null, ttl, cached);
}
public EndpointI[]
getEndpoints(Reference ref, Reference wellKnownRef, int ttl, Ice.BooleanHolder cached)
{
assert(ref.isIndirect());
EndpointI[] endpoints = null;
cached.value = false;
if(!ref.isWellKnown())
{
endpoints = _table.getAdapterEndpoints(ref.getAdapterId(), ttl, cached);
if(!cached.value)
{
if(_background && endpoints != null)
{
getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, null);
}
else
{
return getAdapterRequest(ref).getEndpoints(ref, wellKnownRef, ttl, cached);
}
}
}
else
{
Reference r = _table.getObjectReference(ref.getIdentity(), ttl, cached);
if(!cached.value)
{
if(_background && r != null)
{
getObjectRequest(ref).addCallback(ref, null, ttl, null);
}
else
{
return getObjectRequest(ref).getEndpoints(ref, null, ttl, cached);
}
}
if(!r.isIndirect())
{
endpoints = r.getEndpoints();
}
else if(!r.isWellKnown())
{
return getEndpoints(r, ref, ttl, cached);
}
}
assert(endpoints != null);
cached.value = true;
if(ref.getInstance().traceLevels().location >= 1)
{
getEndpointsTrace(ref, endpoints, true);
}
return endpoints;
}
public void
getEndpoints(Reference ref, int ttl, GetEndpointsCallback callback)
{
getEndpoints(ref, null, ttl, callback);
}
public void
getEndpoints(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback callback)
{
assert(ref.isIndirect());
EndpointI[] endpoints = null;
Ice.BooleanHolder cached = new Ice.BooleanHolder();
if(!ref.isWellKnown())
{
endpoints = _table.getAdapterEndpoints(ref.getAdapterId(), ttl, cached);
if(!cached.value)
{
if(_background && endpoints != null)
{
getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, null);
}
else
{
getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, callback);
return;
}
}
}
else
{
Reference r = _table.getObjectReference(ref.getIdentity(), ttl, cached);
if(!cached.value)
{
if(_background && r != null)
{
getObjectRequest(ref).addCallback(ref, null, ttl, null);
}
else
{
getObjectRequest(ref).addCallback(ref, null, ttl, callback);
return;
}
}
if(!r.isIndirect())
{
endpoints = r.getEndpoints();
}
else if(!r.isWellKnown())
{
getEndpoints(r, ref, ttl, callback);
return;
}
}
assert(endpoints != null);
if(ref.getInstance().traceLevels().location >= 1)
{
getEndpointsTrace(ref, endpoints, true);
}
if(callback != null)
{
callback.setEndpoints(endpoints, true);
}
}
public void
clearCache(Reference ref)
{
assert(ref.isIndirect());
if(!ref.isWellKnown())
{
EndpointI[] endpoints = _table.removeAdapterEndpoints(ref.getAdapterId());
if(endpoints != null && ref.getInstance().traceLevels().location >= 2)
{
trace("removed endpoints from locator table\n", ref, endpoints);
}
}
else
{
Reference r = _table.removeObjectReference(ref.getIdentity());
if(r != null)
{
if(!r.isIndirect())
{
if(ref.getInstance().traceLevels().location >= 2)
{
trace("removed endpoints from locator table", ref, r.getEndpoints());
}
}
else if(!r.isWellKnown())
{
clearCache(r);
}
}
}
}
private void
trace(String msg, Reference ref, EndpointI[] endpoints)
{
assert(ref.isIndirect());
StringBuilder s = new StringBuilder(128);
s.append(msg);
s.append("\n");
if(!ref.isWellKnown())
{
s.append("adapter = ");
s.append(ref.getAdapterId());
s.append("\n");
}
else
{
s.append("object = ");
s.append(ref.getInstance().identityToString(ref.getIdentity()));
s.append("\n");
}
s.append("endpoints = ");
final int sz = endpoints.length;
for(int i = 0; i < sz; i++)
{
s.append(endpoints[i].toString());
if(i + 1 < sz)
{
s.append(":");
}
}
ref.getInstance().initializationData().logger.trace(ref.getInstance().traceLevels().locationCat, s.toString());
}
private void
getEndpointsException(Reference ref, Exception exc)
{
assert(ref.isIndirect());
try
{
throw exc;
}
catch(Ice.AdapterNotFoundException ex)
{
final Instance instance = ref.getInstance();
if(instance.traceLevels().location >= 1)
{
StringBuilder s = new StringBuilder(128);
s.append("adapter not found\n");
s.append("adapter = ");
s.append(ref.getAdapterId());
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
Ice.NotRegisteredException e = new Ice.NotRegisteredException();
e.kindOfObject = "object adapter";
e.id = ref.getAdapterId();
throw e;
}
catch(Ice.ObjectNotFoundException ex)
{
final Instance instance = ref.getInstance();
if(instance.traceLevels().location >= 1)
{
StringBuilder s = new StringBuilder(128);
s.append("object not found\n");
s.append("object = ");
s.append(instance.identityToString(ref.getIdentity()));
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
Ice.NotRegisteredException e = new Ice.NotRegisteredException();
e.kindOfObject = "object";
e.id = instance.identityToString(ref.getIdentity());
throw e;
}
catch(Ice.NotRegisteredException ex)
{
throw ex;
}
catch(Ice.LocalException ex)
{
final Instance instance = ref.getInstance();
if(instance.traceLevels().location >= 1)
{
StringBuilder s = new StringBuilder(128);
s.append("couldn't contact the locator to retrieve adapter endpoints\n");
if(ref.getAdapterId().length() > 0)
{
s.append("adapter = ");
s.append(ref.getAdapterId());
s.append("\n");
}
else
{
s.append("object = ");
s.append(instance.identityToString(ref.getIdentity()));
s.append("\n");
}
s.append("reason = " + ex);
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
throw ex;
}
catch(Exception ex)
{
assert(false);
}
}
private void
getEndpointsTrace(Reference ref, EndpointI[] endpoints, boolean cached)
{
if(endpoints != null && endpoints.length > 0)
{
if(cached)
{
trace("found endpoints in locator table", ref, endpoints);
}
else
{
trace("retrieved endpoints from locator, adding to locator table", ref, endpoints);
}
}
else
{
final Instance instance = ref.getInstance();
StringBuilder s = new StringBuilder(128);
s.append("no endpoints configured for ");
if(ref.getAdapterId().length() > 0)
{
s.append("adapter\n");
s.append("adapter = ");
s.append(ref.getAdapterId());
s.append("\n");
}
else
{
s.append("object\n");
s.append("object = ");
s.append(instance.identityToString(ref.getIdentity()));
s.append("\n");
}
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
}
synchronized private Request
getAdapterRequest(Reference ref)
{
if(ref.getInstance().traceLevels().location >= 1)
{
Instance instance = ref.getInstance();
StringBuilder s = new StringBuilder(128);
s.append("searching for adapter by id\n");
s.append("adapter = ");
s.append(ref.getAdapterId());
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
Request request = _adapterRequests.get(ref.getAdapterId());
if(request != null)
{
return request;
}
request = new AdapterRequest(this, ref);
_adapterRequests.put(ref.getAdapterId(), request);
return request;
}
synchronized private Request
getObjectRequest(Reference ref)
{
if(ref.getInstance().traceLevels().location >= 1)
{
Instance instance = ref.getInstance();
StringBuilder s = new StringBuilder(128);
s.append("searching for object by id\n");
s.append("object = ");
s.append(instance.identityToString(ref.getIdentity()));
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
Request request = _objectRequests.get(ref.getIdentity());
if(request != null)
{
return request;
}
request = new ObjectRequest(this, ref);
_objectRequests.put(ref.getIdentity(), request);
return request;
}
private void
finishRequest(Reference ref, java.util.List<Reference> wellKnownRefs, Ice.ObjectPrx proxy, boolean notRegistered)
{
if(proxy == null || ((Ice.ObjectPrxHelperBase)proxy).__reference().isIndirect())
{
//
// Remove the cached references of well-known objects for which we tried
// to resolved the endpoints if these endpoints are empty.
//
for(Reference r : wellKnownRefs)
{
_table.removeObjectReference(r.getIdentity());
}
}
if(!ref.isWellKnown())
{
if(proxy != null && !((Ice.ObjectPrxHelperBase)proxy).__reference().isIndirect())
{
// Cache the adapter endpoints.
_table.addAdapterEndpoints(ref.getAdapterId(),
((Ice.ObjectPrxHelperBase)proxy).__reference().getEndpoints());
}
else if(notRegistered) // If the adapter isn't registered anymore, remove it from the cache.
{
_table.removeAdapterEndpoints(ref.getAdapterId());
}
synchronized(this)
{
assert(_adapterRequests.get(ref.getAdapterId()) != null);
_adapterRequests.remove(ref.getAdapterId());
}
}
else
{
if(proxy != null && !((Ice.ObjectPrxHelperBase)proxy).__reference().isWellKnown())
{
// Cache the well-known object reference.
_table.addObjectReference(ref.getIdentity(), ((Ice.ObjectPrxHelperBase)proxy).__reference());
}
else if(notRegistered) // If the well-known object isn't registered anymore, remove it from the cache.
{
_table.removeObjectReference(ref.getIdentity());
}
synchronized(this)
{
assert(_objectRequests.get(ref.getIdentity()) != null);
_objectRequests.remove(ref.getIdentity());
}
}
}
private final Ice.LocatorPrx _locator;
private Ice.LocatorRegistryPrx _locatorRegistry;
private final LocatorTable _table;
private final boolean _background;
private java.util.Map<String, Request> _adapterRequests = new java.util.HashMap<String, Request>();
private java.util.Map<Ice.Identity, Request> _objectRequests = new java.util.HashMap<Ice.Identity, Request>();
}