/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package ac.hw.display.client;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.comm.xmpp.interfaces.ICommManager;
import org.societies.api.context.broker.ICtxBroker;
import org.societies.api.css.devicemgmt.display.DisplayEvent;
import org.societies.api.css.devicemgmt.display.DisplayEventConstants;
import org.societies.api.css.devicemgmt.display.IDisplayDriver;
import org.societies.api.css.devicemgmt.display.IDisplayableService;
import org.societies.api.identity.IIdentity;
import org.societies.api.identity.IIdentityManager;
import org.societies.api.identity.Requestor;
import org.societies.api.osgi.event.CSSEvent;
import org.societies.api.osgi.event.CSSEventConstants;
import org.societies.api.osgi.event.EMSException;
import org.societies.api.osgi.event.EventListener;
import org.societies.api.osgi.event.EventTypes;
import org.societies.api.osgi.event.IEventMgr;
import org.societies.api.osgi.event.InternalEvent;
import org.societies.api.services.ServiceMgmtEventType;
import ac.hw.display.server.api.remote.IDisplayPortalServer;
/**
* Describe your class here...
*
* @author Eliza
*
*/
public class DisplayPortalClient extends EventListener implements IDisplayDriver {
private ICommManager commManager;
private IIdentityManager idMgr;
private IIdentity userIdentity;
private List<String> screenLocations;
private IDisplayPortalServer portalServerRemote;
private IIdentity serverIdentity;
private ICtxBroker ctxBroker;
private Requestor requestor;
private boolean hasSession;
private IEventMgr evMgr;
private String currentUsedScreenIP = "";
private String currentUsedScreenLocation = "";
private static Logger LOG = LoggerFactory.getLogger(DisplayPortalClient.class);
private ServiceRuntimeSocketServer servRuntimeSocketThread;
private UserSession userSession;
private Integer serviceRuntimeSocketPort;
public DisplayPortalClient(){
this.screenLocations = new ArrayList<String>();
this.servRuntimeSocketThread = new ServiceRuntimeSocketServer(this);
this.serviceRuntimeSocketPort = this.servRuntimeSocketThread.setListenPort();
this.servRuntimeSocketThread.start();
}
public void Init(){
this.LOG.debug("Initialising DisplayPortalClient");
try {
this.serverIdentity = this.idMgr.fromJid("stuart.societies.local.macs.hw.ac.uk");
} catch(Exception e) {}
//services.getServer(myClientServiceID);
this.LOG.debug("Retrieved my server's identity: "+this.serverIdentity.getJid());
//
// ctxEvListener = new ContextEventListener(this, getCtxBroker(), userIdentity, requestor);
// retrieveScreenLocations();
/* String[] locs = this.portalServerRemote.getScreenLocations(serverIdentity);
this.LOG.debug("Retrieved screen locations from my server");
for (int i=0; i<locs.length; i++){
this.screenLocations.add(locs[i]);
this.LOG.debug("Screen location: "+i+": "+locs[i]);
}*/
//SERVICE REQUESTER NOT NEEDED - NOT A 3P SERVICE
this.requestor = new Requestor(userIdentity);
userSession = new UserSession(this.userIdentity.getJid(), this.serviceRuntimeSocketPort);
this.LOG.debug("DisplayPortalClient initialised");
//LISTEN TO NEW CONTEXT CHANGES
new ContextEventListener(this, ctxBroker, userIdentity, requestor);//.registerForLocationEvents();
//DOESN'T DO ANYTHING
//registerForSLMEvents();
}
//METHOD TO RETRIEVE SCREEN LOCATIONS FROM SERVER PORTAL
private void retrieveScreenLocations()
{
this.screenLocations.clear();
String[] locs = this.portalServerRemote.getScreenLocations(serverIdentity);
this.LOG.debug("Retrieved screen locations from my server");
for (int i=0; i<locs.length; i++){
this.screenLocations.add(locs[i]);
this.LOG.debug("Screen location: "+i+": "+locs[i]);
}
}
private void registerForSLMEvents() {
String eventFilter = "(&" +
"(" + CSSEventConstants.EVENT_NAME + "="+ServiceMgmtEventType.NEW_SERVICE+")" +
"(" + CSSEventConstants.EVENT_SOURCE + "=org/societies/service/lifecycle)" +
")";
this.evMgr.subscribeInternalEvent(this, new String[]{EventTypes.SERVICE_LIFECYCLE_EVENT}, eventFilter);
this.LOG.debug("Subscribed to "+EventTypes.SERVICE_LIFECYCLE_EVENT+" events");
}
private void unRegisterFromSLMEvents()
{
String eventFilter = "(&" +
"(" + CSSEventConstants.EVENT_NAME + "="+ ServiceMgmtEventType.NEW_SERVICE+")" +
"(" + CSSEventConstants.EVENT_SOURCE + "=org/societies/service/lifecycle)" +
")";
this.evMgr.unSubscribeInternalEvent(this, new String[]{EventTypes.SERVICE_LIFECYCLE_EVENT}, eventFilter);
//this.evMgr.subscribeInternalEvent(this, new String[]{EventTypes.SERVICE_LIFECYCLE_EVENT}, eventFilter);
this.LOG.debug("Unsubscribed from "+EventTypes.SERVICE_LIFECYCLE_EVENT+" events");
}
/*
* NOT USED
* (non-Javadoc)
* @see org.societies.api.osgi.event.EventListener#handleExternalEvent(org.societies.api.osgi.event.CSSEvent)
*/
@Override
public void handleExternalEvent(CSSEvent arg0) {
// TODO Auto-generated method stub
}
/*
* Used to receive SLM events and specifically, to know that this bundle has been started in osgi
* so that it can retrieve it's generated SRI.
* (non-Javadoc)
* @see org.societies.api.osgi.event.EventListener#handleInternalEvent(org.societies.api.osgi.event.InternalEvent)
*/
@Override
public void handleInternalEvent(InternalEvent event) {
// TODO Auto-generated method stub
}
private boolean matchesLocation(String location){
this.LOG.debug("User location length: "+location.length());
for (int i=0; i<screenLocations.size(); i++){
String scrLoc = screenLocations.get(i);
this.LOG.debug("Screen location length: "+scrLoc.length());
if (scrLoc.trim().equalsIgnoreCase(location.trim())){
this.LOG.debug(scrLoc+" matches "+location+". Returning true");
return true;
}
this.LOG.debug(scrLoc+" doesn't match "+location);
}
this.LOG.debug("return false");
return false;
}
public void updateUserLocation(String location){
//FOR EVERY UPDATE ON USER LOCATION, GET UPTO DATE SCREEN LOCATIONS
retrieveScreenLocations();
this.LOG.debug("location of user: "+location);
this.LOG.debug("Location of screens: ");
for (int i=0; i<screenLocations.size(); i++){
this.LOG.debug("Screen location: "+i+": "+screenLocations.get(i));
}
if (!location.trim().equalsIgnoreCase(currentUsedScreenLocation.trim())){
//if near a screen
if (this.matchesLocation(location)){
//check if the user is already using another screen
if (this.hasSession){
this.LOG.debug("Releasing previous screen session from: "+currentUsedScreenIP);
//release currently used screen
SocketClient sClient = new SocketClient(currentUsedScreenIP);
sClient.logOut(userSession);
this.LOG.debug("Sent logout msg to: "+currentUsedScreenIP);
this.portalServerRemote.releaseResource(serverIdentity, userIdentity.getJid(), currentUsedScreenIP);
this.LOG.debug("Released screen: "+currentUsedScreenIP);
}
this.LOG.debug("Requesting access to screen in location: "+location);
//request access
String reply = this.portalServerRemote.requestAccess(serverIdentity, userIdentity.getJid(), location);
//if access refused do nothing
if (reply=="REFUSED"){
this.LOG.debug("Refused access to screen.");
}
else //if access is granted
{
this.LOG.debug("Access to screen granted. IP Address is: "+reply);
//now setup new screen
SocketClient socketClient = new SocketClient(reply);
socketClient.startSession(userSession);
//TODO: send services TO DISPLAY
this.currentUsedScreenIP = reply;
this.currentUsedScreenLocation = location;
this.hasSession = true;
DisplayEvent dEvent = new DisplayEvent(this.currentUsedScreenIP, DisplayEventConstants.DEVICE_AVAILABLE);
InternalEvent iEvent = new InternalEvent(EventTypes.DISPLAY_EVENT, "displayUpdate", "org/societies/css/device", dEvent);
try {
this.evMgr.publishInternalEvent(iEvent);
} catch (EMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}//user is not near a screen
else{
this.LOG.debug("User not near screen");
//if he's using a screen
if (this.hasSession){
this.LOG.debug("User in session with portal GUI. Attempting to logout");
//release resource
this.portalServerRemote.releaseResource(serverIdentity, userIdentity.getJid(), currentUsedScreenLocation);
this.hasSession = false;
SocketClient socketClient = new SocketClient(this.currentUsedScreenIP);
socketClient.endSession(this.userSession.getUserIdentity());
this.currentUsedScreenIP = "";
this.currentUsedScreenLocation = "";
this.servRuntimeSocketThread.finalize();
DisplayEvent dEvent = new DisplayEvent(this.currentUsedScreenIP, DisplayEventConstants.DEVICE_UNAVAILABLE);
InternalEvent iEvent = new InternalEvent(EventTypes.DISPLAY_EVENT, "displayUpdate", "org/societies/css/device", dEvent);
try {
this.evMgr.publishInternalEvent(iEvent);
} catch (EMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
this.LOG.debug("User not in a session with the screen. Nothing to do.");
}
}
}else{
this.LOG.debug("Ignoring same value for symloc> new: "+location+" - current: "+this.currentUsedScreenLocation);
}
}
@Override
public void displayImage(String serviceName, String pathToFile){
if (this.hasSession){
BinaryDataTransfer dataTransfer = new BinaryDataTransfer(currentUsedScreenIP);
dataTransfer.sendImage(this.userIdentity.getJid(), pathToFile);
}
}
@Override
public void displayImage(String serviceName, URL remoteImageLocation){
if (this.hasSession){
SocketClient socketClient = new SocketClient(currentUsedScreenIP);
socketClient.sendImage(userSession, remoteImageLocation);
}
}
@Override
public void sendNotification(String serviceName, String text){
if (this.hasSession){
if (this.userSession.containsService(serviceName)){
SocketClient socketClient = new SocketClient(currentUsedScreenIP);
socketClient.sendText(serviceName, userSession, text);
}
}
}
@Override
public void registerDisplayableService(IDisplayableService service, String serviceName, URL executableLocation, boolean requiresKinect){
ServiceInfo sInfo = new ServiceInfo(service, serviceName, executableLocation.toString(), 0, requiresKinect);
this.userSession.addService(sInfo);
}
@Override
public void registerDisplayableService(IDisplayableService service, String serviceName, URL executableLocation, int servicePortNumber, boolean requiresKinect) {
ServiceInfo sInfo = new ServiceInfo(service, serviceName, executableLocation.toString(), servicePortNumber, requiresKinect);
this.userSession.addService(sInfo);
}
/*
* get/set methods
*/
/**
* @return the commManager
*/
public ICommManager getCommManager() {
return commManager;
}
/**
* @param commManager the commManager to set
*/
public void setCommManager(ICommManager commManager) {
this.commManager = commManager;
this.idMgr = commManager.getIdManager();
this.userIdentity = idMgr.getThisNetworkNode();
}
/**
* @return the ctxBroker
*/
public ICtxBroker getCtxBroker() {
return ctxBroker;
}
/**
* @param ctxBroker the ctxBroker to set
*/
public void setCtxBroker(ICtxBroker ctxBroker) {
this.ctxBroker = ctxBroker;
}
/**
* @return the portalServerRemote
*/
public IDisplayPortalServer getPortalServerRemote() {
return portalServerRemote;
}
/**
* @param portalServerRemote the portalServerRemote to set
*/
public void setPortalServerRemote(IDisplayPortalServer portalServerRemote) {
this.portalServerRemote = portalServerRemote;
}
/**
* @return the evMgr
*/
public IEventMgr getEvMgr() {
return evMgr;
}
/**
* @param evMgr the evMgr to set
*/
public void setEvMgr(IEventMgr evMgr) {
this.evMgr = evMgr;
}
public void notifyServiceStarted(String serviceName) {
if (this.userSession.containsService(serviceName)){
this.LOG.debug("Found service: "+serviceName+". Calling serviceStarted method");
ServiceInfo sInfo = this.userSession.getService(serviceName);
if (sInfo!=null){
IDisplayableService service = sInfo.getService();
if (service!=null){
service.serviceStarted(currentUsedScreenIP);
return;
}
}
}
this.LOG.debug("Could not find service: "+serviceName);
}
public void notifyServiceStopped(String serviceName) {
if (this.userSession.containsService(serviceName)){
this.LOG.debug("Found service: "+serviceName+". Calling serviceStopped method");
ServiceInfo sInfo = this.userSession.getService(serviceName);
if (sInfo!=null){
IDisplayableService service = sInfo.getService();
if (service!=null){
service.serviceStopped(currentUsedScreenIP);
return;
}
}
}
this.LOG.debug("Could not find service: "+serviceName);
}
public void notifyLogOutEvent() {
if (this.hasSession){
//release resource
this.portalServerRemote.releaseResource(serverIdentity, userIdentity.getJid(), currentUsedScreenLocation);
this.hasSession = false;
DisplayEvent dEvent = new DisplayEvent(this.currentUsedScreenIP, DisplayEventConstants.DEVICE_UNAVAILABLE);
this.currentUsedScreenIP = "";
this.currentUsedScreenLocation = "";
InternalEvent iEvent = new InternalEvent(EventTypes.DISPLAY_EVENT, "displayUpdate", "org/societies/css/device", dEvent);
try {
this.evMgr.publishInternalEvent(iEvent);
} catch (EMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}