/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.dispatch;
import java.io.IOException;
import org.ws4d.java.client.AppSequenceBuffer;
import org.ws4d.java.communication.CommunicationManager;
import org.ws4d.java.communication.CommunicationManagerRegistry;
import org.ws4d.java.communication.DefaultIncomingMessageListener;
import org.ws4d.java.communication.DiscoveryBinding;
import org.ws4d.java.communication.IncomingMessageListener;
import org.ws4d.java.communication.ProtocolData;
import org.ws4d.java.concurrency.DeadlockException;
import org.ws4d.java.configuration.DispatchingProperties;
import org.ws4d.java.constants.DPWSMessageConstants;
import org.ws4d.java.message.Message;
import org.ws4d.java.message.discovery.ByeMessage;
import org.ws4d.java.message.discovery.HelloMessage;
import org.ws4d.java.service.LocalDevice;
import org.ws4d.java.service.LocalService;
import org.ws4d.java.service.Service;
import org.ws4d.java.service.reference.DeviceReference;
import org.ws4d.java.service.reference.Reference;
import org.ws4d.java.service.reference.ServiceReference;
import org.ws4d.java.structures.ArrayList;
import org.ws4d.java.structures.DataStructure;
import org.ws4d.java.structures.HashSet;
import org.ws4d.java.structures.Iterator;
import org.ws4d.java.structures.LinkedSet;
import org.ws4d.java.structures.LockedList;
import org.ws4d.java.structures.LockedMap;
import org.ws4d.java.types.AppSequence;
import org.ws4d.java.types.DiscoveryData;
import org.ws4d.java.types.EndpointReference;
import org.ws4d.java.types.EprInfo;
import org.ws4d.java.types.EprInfoSet;
import org.ws4d.java.types.HostedMData;
import org.ws4d.java.types.ProbeScopeSet;
import org.ws4d.java.types.QNameSet;
import org.ws4d.java.types.XAddressInfoSet;
import org.ws4d.java.util.Log;
/**
* Registry class which manages deviceInvokers, serviceInvokers and their
* references. Many methods of this class register service and service reference
* listeners.
*
* @author mspies
*/
public abstract class DeviceServiceRegistry {
private static final int[] DEVICE_LIFECYCLE_MESSAGE_TYPES = { DPWSMessageConstants.HELLO_MESSAGE, DPWSMessageConstants.BYE_MESSAGE };
private static final IncomingMessageListener DEVICE_LIFECYCLE_LISTENER = new IncomingHelloByeListener();
private static final int MAX_CACHE_SIZE = DispatchingProperties.getInstance().getServiceReferenceCacheSize();
// epr -> devRef
static final LockedMap DEVICE_REFS = new LockedMap();
// epr -> servRef
static final LockedMap SERVICE_REFS = new LockedMap();
// default device instances
private static final LockedList DEVICES = new LockedList();
// default service instances
private static final LockedList SERVICES = new LockedList();
private static AppSequenceBuffer appSequenceBuffer = null;
private static int appSequenceBufferUser = 0;
/**
* Set of service refs ordered by access. Used to determine the eldest
* service ref. Holds only references, which are not local and not assigned
* to a device.
*/
private static final LinkedSet SERVICE_REFS_GARBAGE_LIST = new LinkedSet(MAX_CACHE_SIZE, true);
// ------------------- CONSTRUCTOR -------------------------
/**
* Package-private constructor.
*/
private DeviceServiceRegistry() {
super();
}
// public static void init() {
// GLOBAL_LOCK.exclusiveLock();
// try {
// for (Iterator it = CommunicationManagerRegistry.getLoadedManagers();
// it.hasNext();) {
// CommunicationManager manager = (CommunicationManager) it.next();
// try {
// manager.registerDeviceReference(DEVICE_LIFECYCLE_MESSAGE_TYPES, null,
// DEVICE_LIFECYCLE_LISTENER);
// } catch (IOException e) {
// Log.printStackTrace(e);
// }
// }
// } finally {
// GLOBAL_LOCK.releaseExclusiveLock();
// }
// }
public static void tearDown() {
// unregister device lifecycle listener
for (Iterator it = CommunicationManagerRegistry.getLoadedManagers(); it.hasNext();) {
CommunicationManager manager = (CommunicationManager) it.next();
try {
manager.unregisterDeviceReference(DEVICE_LIFECYCLE_MESSAGE_TYPES, null, DEVICE_LIFECYCLE_LISTENER);
} catch (IOException e) {
Log.printStackTrace(e);
}
}
DEVICES.exclusiveLock();
try {
int count = DEVICES.size();
while (count-- > 0) {
LocalDevice device = (LocalDevice) DEVICES.get(0);
try {
// this stops also all service of this device
device.stop();
} catch (IOException e) {
Log.printStackTrace(e);
}
}
} finally {
DEVICES.releaseExclusiveLock();
}
// now stop services, which are NOT on top of device
SERVICES.exclusiveLock();
try {
int count = SERVICES.size();
while (count-- > 0) {
LocalService service = (LocalService) SERVICES.get(0);
try {
service.stop();
} catch (IOException e) {
Log.printStackTrace(e);
}
}
} finally {
SERVICES.releaseExclusiveLock();
}
}
/**
* Get device reference of a remote device. If no device reference
* registered for this device, a new one will be created.
*
* @param helloData
* @return
*/
public static DeviceReference getDeviceReference(HelloData helloData) {
if (helloData == null || helloData.getDiscoveryData() == null) {
return null;
}
DEVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
Object o = DEVICE_REFS.get(helloData.getEndpointReference());
if (o != null) {
// kkkneu if the device is known, merge the
// ProtocolVersionInfo!(to set the best fitting DPWSVersion
DefaultDeviceReference d = (DefaultDeviceReference) o;
if (d.getPreferredXAddressInfo() != null && d.getPreferredXAddressInfo().getProtocolInfo() != null && helloData.getProtocolData() != null) {
d.getPreferredXAddressInfo().getProtocolInfo().merge(helloData.getProtocolData().getProtocolInfo());
}
return d;
}
try {
DEVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
return getDeviceReference(helloData);
}
try {
// no device reference available, create one
DefaultDeviceReference devRef = new DefaultDeviceReference(helloData.getAppSequence(), helloData.getDiscoveryData(), helloData.getProtocolData());
DEVICE_REFS.put(helloData.getEndpointReference(), devRef);
return devRef;
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
} finally {
if (sharedLockHold) {
DEVICE_REFS.releaseSharedLock();
}
}
}
/**
* Get device reference of a device location is unknown. If no device
* reference registered for this device, a new will be created.
*
* @param endpointReference
* @return
*/
public static DeviceReference getDeviceReference(EndpointReference endpointReference) {
return getDeviceReference(endpointReference, true);
}
/**
* Returns the device reference to the specified endpoint reference.
*
* @param endpointReference Endpoint reference of the device being looked
* for.
* @param doCreate If <code>true</code>, reference will be created if not
* already existing.
* @return Device reference being looked for.
*/
public static DeviceReference getDeviceReference(EndpointReference epr, boolean doCreate) {
if (epr == null) {
return null;
}
DEVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
Object o = DEVICE_REFS.get(epr);
if (o != null || !doCreate) {
return (DefaultDeviceReference) o;
}
try {
DEVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
return getDeviceReference(epr, doCreate);
}
try {
// no device reference available, create one
DefaultDeviceReference devRef = new DefaultDeviceReference(epr);
DEVICE_REFS.put(epr, devRef);
return devRef;
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
} finally {
if (sharedLockHold) {
DEVICE_REFS.releaseSharedLock();
}
}
}
/**
* Returns the device reference to the specified endpoint reference.
*
* @param endpointReference Endpoint reference of the device being looked
* for.
* @param doCreate If <code>true</code>, reference will be created if not
* already existing.
* @return Device reference being looked for.
*/
public static DeviceReference getDeviceReference(EndpointReference epr, XAddressInfoSet addresses, boolean doCreate) {
if (epr == null) {
return null;
}
DEVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
Object o = DEVICE_REFS.get(epr);
if (o != null || !doCreate) {
return (DefaultDeviceReference) o;
}
try {
DEVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
return getDeviceReference(epr, addresses, doCreate);
}
try {
// no device reference available, create one
DefaultDeviceReference devRef = new DefaultDeviceReference(epr, addresses);
DEVICE_REFS.put(epr, devRef);
return devRef;
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
} finally {
if (sharedLockHold) {
DEVICE_REFS.releaseSharedLock();
}
}
}
/**
* Get device reference of a local device. If no device reference registered
* for this device, a new will be created.
*
* @param device
* @return
*/
public static DefaultDeviceReference getDeviceReference(LocalDevice device) {
EndpointReference epr = device.getEndpointReference();
if (epr == null) {
return null;
}
DEVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
Object o = DEVICE_REFS.get(epr);
if (o != null) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
DefaultDeviceReference devRef = (DefaultDeviceReference) o;
/*
* if somebody has created a dev ref to an unknown device, and
* this local device is now registering.
*/
devRef.setLocalDevice(device);
return devRef;
}
try {
DEVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
return getDeviceReference(device);
}
try {
// no device reference available, create one
DefaultDeviceReference devRef = new DefaultDeviceReference(device);
DEVICE_REFS.put(epr, devRef);
return devRef;
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
} finally {
if (sharedLockHold) {
DEVICE_REFS.releaseSharedLock();
}
}
}
public static ServiceReference createServiceReference(EndpointReference epr, QNameSet portTypes, String comManId, ProtocolData protocolData) throws DuplicateServiceReferenceException {
SERVICE_REFS.exclusiveLock();
try {
Object o = SERVICE_REFS.get(epr);
if (o != null) {
throw new DuplicateServiceReferenceException("Existing service reference with equal endpoint reference found: " + o);
}
HostedMData hosted = new HostedMData();
EprInfoSet eprs = new EprInfoSet();
eprs.add(new EprInfo(epr, comManId));
hosted.setEprInfoSet(eprs);
hosted.setTypes(portTypes);
ServiceReference serviceRef = ServiceReferenceFactory.getInstance().newServiceReference(hosted, comManId, protocolData);
addServiceReferenceToGarbageList(serviceRef);
SERVICE_REFS.put(epr, serviceRef);
return serviceRef;
} finally {
SERVICE_REFS.releaseExclusiveLock();
}
}
public static ServiceReference getUpdatedServiceReference(HostedMData hosted, DeviceReference devRef, String comManId, ProtocolData protocolData) {
ServiceReferenceInternal servRef = null;
SERVICE_REFS.sharedLock();
try {
servRef = getFirstMatchingServiceReferenceForReuse(hosted);
} finally {
SERVICE_REFS.releaseSharedLock();
}
if (servRef != null) {
servRef.update(hosted, devRef, protocolData);
return servRef;
}
SERVICE_REFS.exclusiveLock();
try {
servRef = getFirstMatchingServiceReferenceForReuse(hosted);
if (servRef != null) {
servRef.update(hosted, devRef, protocolData);
return servRef;
}
servRef = ServiceReferenceFactory.getInstance().newServiceReference(hosted, comManId, protocolData);
for (Iterator it = hosted.getEprInfoSet().iterator(); it.hasNext();) {
EprInfo serviceEpr = (EprInfo) it.next();
SERVICE_REFS.put(serviceEpr.getEndpointReference(), servRef);
}
if (devRef != null && servRef.getParentDeviceRef() == null) {
servRef.setParentDeviceReference(devRef);
}
return servRef;
} finally {
SERVICE_REFS.releaseExclusiveLock();
}
}
/**
* @param hosted
* @param servRef
* @return
*/
private static ServiceReferenceInternal getFirstMatchingServiceReferenceForReuse(HostedMData hosted) {
for (Iterator it = hosted.getEprInfoSet().iterator(); it.hasNext();) {
EprInfo serviceEpr = (EprInfo) it.next();
Object o = SERVICE_REFS.get(serviceEpr.getEndpointReference());
if (o != null) {
ServiceReferenceInternal servRef = (ServiceReferenceInternal) o;
removeServiceReferenceFromGarbageList(servRef);
return servRef;
}
}
return null;
}
/**
* Returns the service reference to the specified endpoint reference.
*
* @param endpointReference Endpoint reference of the service being looked
* for.
* @param doCreate If <code>true</code>, reference will be created if not
* already existing.
* @return Service reference being looked for.
*/
/**
* @param endpointReference
* @return
*/
public static ServiceReference getServiceReference(EndpointReference endpointReference, String comManId, boolean doCreate) {
if (endpointReference == null) {
return null;
}
SERVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
Object o = SERVICE_REFS.get(endpointReference);
if (o != null || !doCreate) {
return (ServiceReference) SERVICE_REFS.get(endpointReference);
}
try {
SERVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
SERVICE_REFS.releaseSharedLock();
sharedLockHold = false;
return getServiceReference(endpointReference, comManId, doCreate);
}
try {
ServiceReference serviceRef = ServiceReferenceFactory.getInstance().newServiceReference(endpointReference, comManId);
addServiceReferenceToGarbageList(serviceRef);
SERVICE_REFS.put(endpointReference, serviceRef);
return serviceRef;
} finally {
SERVICE_REFS.releaseExclusiveLock();
}
} finally {
if (sharedLockHold) {
SERVICE_REFS.releaseSharedLock();
}
}
}
/**
* Update the registered endpoint addresses of the service reference.
*
* @param newHosted
* @param servRef
* @return
*/
static ServiceReferenceInternal updateServiceReferenceRegistration(HostedMData newHosted, ServiceReferenceInternal servRef) {
// ServiceReferenceHandler servRef = null;
EprInfoSet newEprs = newHosted.getEprInfoSet();
SERVICE_REFS.exclusiveLock();
try {
/*
* remove all eprs from registry, which are not transmitted
*/
for (Iterator it = servRef.getEprInfos(); it.hasNext();) {
EprInfo epr = (EprInfo) it.next();
if (!newEprs.contains(epr)) {
SERVICE_REFS.remove(epr.getEndpointReference());
}
}
/*
* add all transmitted eprs
*/
for (Iterator it = newEprs.iterator(); it.hasNext();) {
EprInfo serviceEpr = (EprInfo) it.next();
SERVICE_REFS.put(serviceEpr.getEndpointReference(), servRef);
}
} finally {
SERVICE_REFS.releaseExclusiveLock();
}
return servRef;
}
static void addServiceReferenceToGarbageList(ServiceReference servRef) {
if (servRef == null) {
return;
}
ServiceReference eldest = null;
synchronized (SERVICE_REFS_GARBAGE_LIST) {
if (SERVICE_REFS_GARBAGE_LIST.size() >= MAX_CACHE_SIZE) {
eldest = (ServiceReference) SERVICE_REFS_GARBAGE_LIST.removeFirst();
}
SERVICE_REFS_GARBAGE_LIST.add(servRef);
}
if (eldest != null) {
unregisterServiceReference(eldest);
}
}
static void updateServiceReferenceInGarbageList(ServiceReference servRef) {
synchronized (SERVICE_REFS_GARBAGE_LIST) {
SERVICE_REFS_GARBAGE_LIST.touch(servRef);
}
}
public static void removeServiceReferenceFromGarbageList(ServiceReference servRef) {
synchronized (SERVICE_REFS_GARBAGE_LIST) {
SERVICE_REFS_GARBAGE_LIST.remove(servRef);
}
}
/**
* @param deviceTypes
* @param scopes
* @return
*/
public static DataStructure getLocalDeviceReferences(QNameSet deviceTypes, ProbeScopeSet scopes) {
DEVICES.sharedLock();
try {
DataStructure matchingDeviceRefs = new HashSet();
for (Iterator it = DEVICES.iterator(); it.hasNext();) {
LocalDevice device = (LocalDevice) it.next();
if (device.deviceMatches(deviceTypes, scopes)) {
matchingDeviceRefs.add(device.getDeviceReference());
}
}
return matchingDeviceRefs;
} finally {
DEVICES.releaseSharedLock();
}
}
/**
* @param serviceTypes
* @param deviceTypes
* @param scopes
* @return
*/
public static DataStructure getLocalServiceReferences(QNameSet serviceTypes, QNameSet deviceTypes, ProbeScopeSet scopes) {
DataStructure matchingServiceRefs = new ArrayList();
if ((deviceTypes != null && deviceTypes.size() > 0) || scopes != null && scopes.size() > 0) {
DEVICES.sharedLock();
try {
for (Iterator it = DEVICES.iterator(); it.hasNext();) {
LocalDevice device = (LocalDevice) it.next();
if (device.deviceMatches(deviceTypes, scopes)) {
device.addServiceReferences(matchingServiceRefs, serviceTypes);
}
}
} finally {
DEVICES.releaseSharedLock();
}
} else {
SERVICES.sharedLock();
try {
for (Iterator it = SERVICES.iterator(); it.hasNext();) {
Service service = (Service) it.next();
ServiceReference servRef = service.getServiceReference();
if (serviceTypes.isContainedBy(servRef.getPortTypes())) {
matchingServiceRefs.add(servRef);
}
}
} finally {
SERVICES.releaseSharedLock();
}
}
return matchingServiceRefs;
}
/**
* Removes proxy device reference.
*
* @param deviceReference proxy device reference to remove.
*/
static void unregisterDeviceReference(DefaultDeviceReference deviceReference) {
if (deviceReference == null) {
return;
}
EndpointReference epr = deviceReference.getEndpointReference();
DEVICE_REFS.exclusiveLock();
try {
if (DEVICE_REFS.remove(epr) == null) {
return;
}
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
// disconnect service references
deviceReference.disconnectAllServiceReferences(false);
}
private static void unregisterServiceReference(ServiceReference servRef) {
Iterator eprs = servRef.getEprInfos();
if (!eprs.hasNext()) {
Log.error("ERROR: DeviceServiceRegistry.unregisterServiceReference0: no epr in service");
return;
}
SERVICE_REFS.exclusiveLock();
try {
while (eprs.hasNext()) {
EprInfo eprInfo = (EprInfo) eprs.next();
SERVICE_REFS.remove(eprInfo.getEndpointReference());
}
} finally {
SERVICE_REFS.releaseExclusiveLock();
}
// invalidate service of servRef
ServiceReferenceInternal servRefHandler = (ServiceReferenceInternal) servRef;
// invalidate the service
servRefHandler.setService(null, null);
removeServiceReferenceFromGarbageList(servRefHandler);
}
// ----------------------------------------------------------
public static DeviceReference getUpdatedDeviceReference(DiscoveryData newData, Message msg, ProtocolData protocolData) {
EndpointReference epr = newData.getEndpointReference();
DEVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
DefaultDeviceReference devRef = (DefaultDeviceReference) DEVICE_REFS.get(epr);
if (devRef != null) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
if (devRef.getLocation() == Reference.LOCATION_LOCAL || !devRef.checkAppSequence(msg.getAppSequence())) {
/*
* It's our own device or message out of date => nothing to
* handle
*/
return devRef;
}
devRef.updateDiscoveryData(newData, protocolData);
} else {
// devRef == null
try {
DEVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
return getUpdatedDeviceReference(newData, msg, protocolData);
}
try {
devRef = new DefaultDeviceReference(msg.getAppSequence(), newData, protocolData);
if (devRef.getPreferredXAddressInfo().getProtocolInfo() != null) {
devRef.getPreferredXAddressInfo().getProtocolInfo().merge(msg.getProtocolInfo());
} else {
devRef.getPreferredXAddressInfo().setProtocolInfo(msg.getProtocolInfo());
}
DEVICE_REFS.put(epr, devRef);
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
}
devRef.setSecureDevice(msg.isSecure());
return devRef;
} finally {
if (sharedLockHold) {
DEVICE_REFS.releaseSharedLock();
}
}
}
public static void register(LocalDevice device) {
DEVICES.exclusiveLock();
try {
if (DEVICES.contains(device)) {
return;
}
DEVICES.add(device);
} finally {
DEVICES.releaseExclusiveLock();
}
}
public static void unregister(LocalDevice device) {
DEVICES.exclusiveLock();
try {
DEVICES.remove(device);
} finally {
DEVICES.releaseExclusiveLock();
}
}
public static void register(LocalService service) {
SERVICES.exclusiveLock();
try {
if (SERVICES.contains(service)) {
return;
}
SERVICES.add(service);
} finally {
SERVICES.releaseExclusiveLock();
}
}
public static void unregister(LocalService service) {
SERVICES.exclusiveLock();
try {
SERVICES.remove(service);
} finally {
SERVICES.releaseExclusiveLock();
}
}
public static void register(DiscoveryBinding binding) {
for (Iterator it = CommunicationManagerRegistry.getLoadedManagers(); it.hasNext();) {
CommunicationManager manager = (CommunicationManager) it.next();
try {
manager.registerDeviceReference(DEVICE_LIFECYCLE_MESSAGE_TYPES, binding, DEVICE_LIFECYCLE_LISTENER);
} catch (IOException e) {
Log.printStackTrace(e);
}
}
}
public static void unregister(DiscoveryBinding binding) {
// unregister device lifecycle listener
for (Iterator it = CommunicationManagerRegistry.getLoadedManagers(); it.hasNext();) {
CommunicationManager manager = (CommunicationManager) it.next();
try {
manager.unregisterDeviceReference(DEVICE_LIFECYCLE_MESSAGE_TYPES, binding, DEVICE_LIFECYCLE_LISTENER);
} catch (IOException e) {
Log.printStackTrace(e);
}
}
}
/**
* Returns the buffer for the application sequence counter.
*
* @return
*/
public static synchronized boolean checkAndUpdateAppSequence(EndpointReference ref, AppSequence seq) {
if (appSequenceBufferUser == 0) {
return true;
}
return appSequenceBuffer.checkAndUpdate(ref, seq);
}
public static synchronized void incAppSequenceUser() {
if (appSequenceBufferUser++ == 0) {
appSequenceBuffer = new AppSequenceBuffer();
}
}
public static synchronized void decAppSequenceUser() {
if (appSequenceBufferUser-- == 1) {
appSequenceBuffer = null;
} else if (appSequenceBufferUser == -1) {
appSequenceBufferUser++;
throw new RuntimeException("Cannot decrease Application Sequence Buffer User.");
}
}
private static class IncomingHelloByeListener extends DefaultIncomingMessageListener {
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.DefaultIncomingMessageListener#handle
* (org.ws4d.java.message.discovery.HelloMessage,
* org.ws4d.java.communication.CommunicationID)
*/
public void handle(HelloMessage hello, ProtocolData protocolData) {
DiscoveryData newData = hello.getDiscoveryData();
EndpointReference epr;
if (newData == null || (epr = newData.getEndpointReference()) == null) {
return;
}
DEVICE_REFS.sharedLock();
boolean sharedLockHold = true;
try {
DefaultDeviceReference devRef = (DefaultDeviceReference) DEVICE_REFS.get(epr);
if (devRef != null) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
if (devRef.getLocation() == Reference.LOCATION_LOCAL) {
/*
* It's our own device => nothing to handle
*/
return;
}
devRef.updateFromHello(hello, protocolData);
} else {
// devRef == null
if (DispatchingProperties.getInstance().isDeviceReferenceAutoBuild()) {
try {
DEVICE_REFS.exclusiveLock();
} catch (DeadlockException e) {
DEVICE_REFS.releaseSharedLock();
sharedLockHold = false;
handle(hello, protocolData);
return;
}
try {
/*
* Build device reference
*/
devRef = new DefaultDeviceReference(hello.getAppSequence(), newData, protocolData);
DEVICE_REFS.put(epr, devRef);
} finally {
DEVICE_REFS.releaseExclusiveLock();
}
if (Log.isInfo()) {
Log.info("Set DPWS Version for " + devRef.getEndpointReference().toString() + " to : " + devRef.getPreferredXAddressInfo().getProtocolInfo());
}
devRef.setSecureDevice(hello.getHeader().getSignature() != null);
} else {
/*
* We don't add automatically device references.
*/
return;
}
}
} finally {
if (sharedLockHold) {
DEVICE_REFS.releaseSharedLock();
}
}
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.communication.DefaultIncomingMessageListener#handle
* (org.ws4d.java.message.discovery.ByeMessage,
* org.ws4d.java.communication.CommunicationID)
*/
public void handle(ByeMessage bye, ProtocolData protocolData) {
EndpointReference epr;
if (bye == null || (epr = bye.getEndpointReference()) == null) {
return;
}
Object o = DEVICE_REFS.get(epr);
if (o != null) {
DefaultDeviceReference devRef = (DefaultDeviceReference) o;
if (devRef.getLocation() == Reference.LOCATION_LOCAL) {
/*
* local device stops are transmitted by local device
*/
return;
}
devRef.updateFromBye(bye, protocolData);
}
}
}
}