001/* 002 * Syncany, www.syncany.org 003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package org.syncany.operations.daemon; 019 020import java.util.logging.Level; 021import java.util.logging.Logger; 022 023import org.syncany.config.LocalEventBus; 024import org.syncany.operations.daemon.messages.ConfirmUserInteractionExternalEvent; 025import org.syncany.operations.daemon.messages.ConfirmUserInteractionExternalEventResponse; 026import org.syncany.operations.daemon.messages.GetPasswordUserInteractionExternalEvent; 027import org.syncany.operations.daemon.messages.GetPasswordUserInteractionExternalEventResponse; 028import org.syncany.plugins.UserInteractionListener; 029 030import com.google.common.eventbus.Subscribe; 031 032/** 033 * This implementation of a {@link UserInteractionListener} uses the {@link LocalEventBus} 034 * to broadcast interaction requests to subscribers and waits synchronously for a corresponding 035 * event response. All methods wait until the response event arrives by sending the current 036 * thread to sleep via {@link #wait()}, and waking it up via {@link #notify()}. 037 * 038 * @see UserInteractionListener 039 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 040 */ 041public class EventUserInteractionListener implements UserInteractionListener { 042 private static final Logger logger = Logger.getLogger(EventUserInteractionListener.class.getSimpleName()); 043 044 private LocalEventBus eventBus; 045 private Object waitObject; 046 private Object userResponse; 047 048 public EventUserInteractionListener() { 049 this.eventBus = LocalEventBus.getInstance(); 050 this.eventBus.register(this); 051 this.waitObject = new Object(); 052 } 053 054 @Override 055 public boolean onUserConfirm(String header, String message, String question) { 056 logger.log(Level.INFO, "User confirmation needed for '" + header + "'. Sending message."); 057 eventBus.post(new ConfirmUserInteractionExternalEvent(header, message, question)); 058 059 ConfirmUserInteractionExternalEventResponse userConfirmation = (ConfirmUserInteractionExternalEventResponse) waitForUserResponse(); 060 return userConfirmation.getResult(); 061 } 062 063 @Override 064 public String onUserPassword(String header, String message) { 065 logger.log(Level.INFO, "User password needed. Sending message."); 066 eventBus.post(new GetPasswordUserInteractionExternalEvent()); 067 068 GetPasswordUserInteractionExternalEventResponse userConfirmation = (GetPasswordUserInteractionExternalEventResponse) waitForUserResponse(); 069 return userConfirmation.getPassword(); 070 } 071 072 @Override 073 public String onUserNewPassword() { 074 throw new RuntimeException("onUserNewPassword() not implemented for WebSocket init/connect."); 075 } 076 077 @Subscribe 078 public void onConfirmUserInteractionExternalManagementRequest(ConfirmUserInteractionExternalEventResponse response) { 079 userResponse = response; 080 fireUserResponseReady(); 081 } 082 083 @Subscribe 084 public void onGetPasswordUserInteractionExternalManagementRequest(GetPasswordUserInteractionExternalEventResponse response) { 085 userResponse = response; 086 fireUserResponseReady(); 087 } 088 089 private Object waitForUserResponse() { 090 try { 091 synchronized (waitObject) { 092 waitObject.wait(); 093 } 094 095 return userResponse; 096 } 097 catch (InterruptedException e) { 098 logger.log(Level.SEVERE, "User interaction listener interrupted.", e); 099 return null; 100 } 101 } 102 103 private void fireUserResponseReady() { 104 synchronized (waitObject) { 105 waitObject.notify(); 106 } 107 } 108}