/** * 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 org.societies.useragent.comms; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.comm.xmpp.datatypes.Stanza; import org.societies.api.comm.xmpp.exceptions.CommunicationException; import org.societies.api.comm.xmpp.exceptions.XMPPError; import org.societies.api.comm.xmpp.interfaces.ICommManager; import org.societies.api.comm.xmpp.interfaces.IFeatureServer; import org.societies.api.identity.IIdentity; import org.societies.api.identity.IIdentityManager; import org.societies.api.identity.InvalidFormatException; import org.societies.api.internal.schema.useragent.feedback.UserFeedbackAccessControlEvent; import org.societies.api.internal.schema.useragent.feedback.UserFeedbackHistoryRequest; import org.societies.api.internal.schema.useragent.feedback.UserFeedbackPrivacyNegotiationEvent; import org.societies.api.internal.useragent.model.ExpProposalContent; import org.societies.api.internal.useragent.model.ImpProposalContent; import org.societies.api.personalisation.model.Action; import org.societies.api.personalisation.model.IAction; import org.societies.api.schema.privacytrust.privacy.model.privacypolicy.ResponseItem; import org.societies.api.schema.servicelifecycle.model.ServiceResourceIdentifier; import org.societies.api.schema.useragent.feedback.ExpFeedbackResultBean; import org.societies.api.schema.useragent.feedback.ImpFeedbackResultBean; import org.societies.api.schema.useragent.feedback.UserFeedbackBean; import org.societies.api.schema.useragent.monitoring.UserActionMonitorBean; import org.societies.useragent.api.feedback.IInternalUserFeedback; import org.societies.useragent.api.monitoring.IInternalUserActionMonitor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; public class UACommsServer implements IFeatureServer { private static final Logger log = LoggerFactory.getLogger(UACommsServer.class); public static final List<String> NAMESPACES = Collections.unmodifiableList( Arrays.asList("http://societies.org/api/schema/useragent/monitoring", "http://societies.org/api/schema/useragent/feedback", "http://societies.org/api/internal/schema/useragent/feedback")); public static final List<String> PACKAGES = Collections.unmodifiableList( Arrays.asList("org.societies.api.schema.useragent.monitoring", "org.societies.api.schema.useragent.feedback", "org.societies.api.internal.schema.useragent.feedback")); //PRIVATE VARIABLES private ICommManager commsMgr; private IInternalUserActionMonitor internalUserActionMonitor; private IInternalUserFeedback feedback; private IIdentityManager idManager; //PROPERTIES public ICommManager getCommsMgr() { return commsMgr; } public void setCommsMgr(ICommManager commsMgr) { this.commsMgr = commsMgr; } public void setInternalUserActionMonitor(IInternalUserActionMonitor internalUserActionMonitor) { this.internalUserActionMonitor = internalUserActionMonitor; } public void setFeedback(IInternalUserFeedback feedback) { this.feedback = feedback; } //METHODS public UACommsServer() { } public void initService() { //REGISTER OUR CommsManager WITH THE XMPP Communication Manager try { getCommsMgr().register(this); } catch (CommunicationException e) { log.error("Error registering with comms manager", e); } idManager = commsMgr.getIdManager(); } @Override public List<String> getJavaPackages() { return PACKAGES; } @Override public List<String> getXMLNamespaces() { return NAMESPACES; } /* * USER ACTION MONITOR METHODS */ @Override public void receiveMessage(Stanza stanza, Object payload) { log.info(String.format("receiveMessage() \n Stanza=%s\n Payload=%s", stanza != null ? stanza.toString() : "null", payload != null ? payload.toString() : "null")); // log.info("UACommsServer received message with no return type!!!"); //CHECK WHICH END BUNDLE TO BE CALLED THAT I MANAGE if (payload instanceof UserActionMonitorBean) { this.receiveMessage(stanza, (UserActionMonitorBean) payload); } } private void receiveMessage(Stanza stanza, UserActionMonitorBean monitorBean) { //---- UAM Bundle --- log.info("Message received for UAM - processing"); switch (monitorBean.getMethod()) { case MONITOR: try { String senderDeviceId = monitorBean.getSenderDeviceId(); IIdentity owner = idManager.fromJid(monitorBean.getIdentity()); ServiceResourceIdentifier serviceId = monitorBean.getServiceResourceIdentifier(); String serviceType = monitorBean.getServiceType(); String parameterName = monitorBean.getParameterName(); String value = monitorBean.getValue(); IAction action = new Action(serviceId, serviceType, parameterName, value); log.info("Sending remote message to local UAM"); internalUserActionMonitor.monitorFromRemoteNode(senderDeviceId, owner, action); break; } catch (InvalidFormatException e) { log.error("Error receiving message", e); } } } /* * USER FEEDBACK METHODS */ @Override public Object getQuery(Stanza stanza, Object payload) throws XMPPError { log.info(String.format("getQuery() \n Stanza=%s\n Payload=%s", stanza != null ? stanza.toString() : "null", payload != null ? payload.toString() : "null")); log.info("UACommsServer received message with a return type!!!"); Object result = null; if (payload instanceof UserActionMonitorBean) { this.receiveMessage(stanza, (UserActionMonitorBean) payload); result = true; } else if (payload instanceof UserFeedbackBean) { result = this.getQuery(stanza, (UserFeedbackBean) payload); } else if (payload instanceof UserFeedbackHistoryRequest) { result = this.getQuery(stanza, (UserFeedbackHistoryRequest) payload); } return result; } private UserFeedbackHistoryRequest getQuery(Stanza stanza, UserFeedbackHistoryRequest requestBean) { List<UserFeedbackBean> userFeedbackBeans; List<UserFeedbackPrivacyNegotiationEvent> userFeedbackPrivacyNegotiationEvents; List<UserFeedbackAccessControlEvent> userFeedbackAccessControlEvents; switch (requestBean.getRequestType()) { case BY_COUNT: try { userFeedbackBeans = feedback.listStoredFeedbackBeans(requestBean.getHowMany()); } catch (Exception ex) { log.warn("Error loading UF beans from repository", ex); userFeedbackBeans = new ArrayList<UserFeedbackBean>(); } userFeedbackPrivacyNegotiationEvents = new ArrayList<UserFeedbackPrivacyNegotiationEvent>(); // TODO: fill this list userFeedbackAccessControlEvents = new ArrayList<UserFeedbackAccessControlEvent>(); // TODO: fill this list break; // case BY_DATE: // result = feedback.listStoredFeedbackBeans(requestBean.getSinceWhen()); // userFeedbackPrivacyNegotiationEvents = new ArrayList<UserFeedbackPrivacyNegotiationEvent>(); // TODO: fill this list // userFeedbackAccessControlEvents = new ArrayList<UserFeedbackAccessControlEvent>(); // TODO: fill this list // break; case OUTSTANDING: try { userFeedbackBeans = feedback.listIncompleteFeedbackBeans(); } catch (Exception ex) { log.warn("Error loading UF beans from repository", ex); userFeedbackBeans = new ArrayList<UserFeedbackBean>(); } try { userFeedbackPrivacyNegotiationEvents = feedback.listIncompletePrivacyRequests(); } catch (Exception ex) { log.warn("Error loading PPNs from repository", ex); userFeedbackPrivacyNegotiationEvents = new ArrayList<UserFeedbackPrivacyNegotiationEvent>(); } try { userFeedbackAccessControlEvents = feedback.listIncompleteAccessRequests(); } catch (Exception ex) { log.warn("Error loading ACs from repository", ex); userFeedbackAccessControlEvents = new ArrayList<UserFeedbackAccessControlEvent>(); } break; default: log.warn("Invalid requestBean.requestType: " + requestBean.getRequestType().name()); return null; } // check to make sure none of our repositories have returned null if (userFeedbackBeans == null) userFeedbackBeans = new ArrayList<UserFeedbackBean>(); if (userFeedbackPrivacyNegotiationEvents == null) userFeedbackPrivacyNegotiationEvents = new ArrayList<UserFeedbackPrivacyNegotiationEvent>(); if (userFeedbackAccessControlEvents == null) userFeedbackAccessControlEvents = new ArrayList<UserFeedbackAccessControlEvent>(); // NB: Hibernate will return a persistent list, which is no good to us requestBean.setUserFeedbackBean(new ArrayList<UserFeedbackBean>(userFeedbackBeans)); requestBean.setUserFeedbackPrivacyNegotiationEvent(new ArrayList<UserFeedbackPrivacyNegotiationEvent>(userFeedbackPrivacyNegotiationEvents)); requestBean.setUserFeedbackAccessControlEvent(new ArrayList<UserFeedbackAccessControlEvent>(userFeedbackAccessControlEvents)); // NB: Now get rid of all the hibernate mess inside the beans for (UserFeedbackBean bean : requestBean.getUserFeedbackBean()) { bean.setOptions(new ArrayList<String>(bean.getOptions())); // persistent list // bean.setRequestDate(new Date(bean.getRequestDate().getTime())); // java.sql.Timestamp } for (UserFeedbackPrivacyNegotiationEvent event : requestBean.getUserFeedbackPrivacyNegotiationEvent()) { event.getResponsePolicy().setResponseItems(new ArrayList<ResponseItem>(event.getResponsePolicy().getResponseItems())); // persistent list // bean.setRequestDate(new Date(bean.getRequestDate().getTime())); // java.sql.Timestamp } for (UserFeedbackAccessControlEvent event : requestBean.getUserFeedbackAccessControlEvent()) { event.setResponseItems(new ArrayList<ResponseItem>(event.getResponseItems())); // persistent list // bean.setRequestDate(new Date(bean.getRequestDate().getTime())); // java.sql.Timestamp } if (log.isDebugEnabled()) log.debug("About to transmit {} UserFeedbackBeans, {} UserFeedbackPrivacyNegotiationEvents, {} UserFeedbackAccessControlEvents", new Object[]{userFeedbackBeans.size(), userFeedbackPrivacyNegotiationEvents.size(), userFeedbackAccessControlEvents.size()} ); // TODO: Debugging - remove me log.warn("Setting lists to null for debugging purposes - be sure to remove me before production"); requestBean.setUserFeedbackBean(null); // requestBean.setUserFeedbackPrivacyNegotiationEvent(null); // requestBean.setUserFeedbackAccessControlEvent(null); return requestBean; } private Object getQuery(Stanza stanza, UserFeedbackBean feedbackBean) { //---- User Feedback Bundle ---- log.info("Message received for User Feedback - processing"); Object resultBean = null; switch (feedbackBean.getMethod()) { case GET_EXPLICIT_FB: try { String requestId = feedbackBean.getRequestId(); int expType = feedbackBean.getType(); String expProposalText = feedbackBean.getProposalText(); List<String> tmp = feedbackBean.getOptions(); String[] options = new String[tmp.size()]; //create array of options int i = 0; for (String nextOption : tmp) { options[i] = nextOption; i++; } log.debug("Sending remote message to local User Feedback - explicit"); ExpProposalContent expContent = new ExpProposalContent(expProposalText, options); List<String> result = feedback.getExplicitFBforRemote(expType, expContent).get(); //create response bean ExpFeedbackResultBean expResultBean = new ExpFeedbackResultBean(); expResultBean.setRequestId(requestId); expResultBean.setFeedback(result); resultBean = expResultBean; } catch (InterruptedException e) { log.error("Error creating response bean", e); } catch (ExecutionException e) { log.error("Error creating response bean", e); } break; case GET_IMPLICIT_FB: try { String requestId = feedbackBean.getRequestId(); int impType = feedbackBean.getType(); String impProposalText = feedbackBean.getProposalText(); int timeout = feedbackBean.getTimeout(); log.debug("Sending remote message to local User Feedback - implicit"); ImpProposalContent impContent = new ImpProposalContent(impProposalText, timeout); Boolean result = feedback.getImplicitFBforRemote(impType, impContent).get(); //create response bean ImpFeedbackResultBean impResultBean = new ImpFeedbackResultBean(); impResultBean.setRequestId(requestId); impResultBean.setAccepted(result); resultBean = impResultBean; } catch (InterruptedException e) { log.error("Error creating response bean", e); } catch (ExecutionException e) { log.error("Error creating response bean", e); } break; } return resultBean; } @Override public Object setQuery(Stanza stanza, Object payload) throws XMPPError { log.info(String.format("setQuery() \n Stanza=%s\n Payload=%s", stanza != null ? stanza.toString() : "null", payload != null ? payload.toString() : "null")); return null; } }