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.io.File; 021import java.util.logging.Level; 022import java.util.logging.Logger; 023 024import org.simpleframework.xml.core.Persister; 025import org.syncany.config.Config; 026import org.syncany.config.ConfigException; 027import org.syncany.config.LocalEventBus; 028import org.syncany.config.to.PortTO; 029import org.syncany.operations.daemon.messages.AlreadySyncingResponse; 030import org.syncany.operations.daemon.messages.BadRequestResponse; 031import org.syncany.operations.daemon.messages.api.FolderRequest; 032import org.syncany.operations.daemon.messages.api.FolderRequestHandler; 033import org.syncany.operations.daemon.messages.api.Response; 034import org.syncany.operations.watch.WatchOperation; 035import org.syncany.operations.watch.WatchOperationOptions; 036import org.syncany.operations.watch.WatchOperationResult; 037 038import com.google.common.eventbus.Subscribe; 039 040/** 041 * The watch operation thread runs a {@link WatchOperation} in a thread. The 042 * underlying thred can be started using the {@link #start()} method, and stopped 043 * gracefully using {@link #stop()}. 044 * 045 * @author Philipp C. Heckel (philipp.heckel@gmail.com) 046 */ 047public class WatchRunner { 048 private static final Logger logger = Logger.getLogger(WatchRunner.class.getSimpleName()); 049 050 private Config config; 051 private PortTO portTO; 052 private Thread watchThread; 053 private WatchOperation watchOperation; 054 private WatchOperationResult watchOperationResult; 055 private LocalEventBus eventBus; 056 057 public WatchRunner(Config config, WatchOperationOptions watchOperationOptions, PortTO portTO) throws ConfigException { 058 this.config = config; 059 this.portTO = portTO; 060 this.watchOperation = new WatchOperation(config, watchOperationOptions); 061 062 this.eventBus = LocalEventBus.getInstance(); 063 this.eventBus.register(this); 064 } 065 066 public void start() { 067 watchThread = new Thread(new Runnable() { 068 @Override 069 public void run() { 070 try { 071 logger.log(Level.INFO, "STARTING watch at" + config.getLocalDir()); 072 watchOperationResult = null; 073 074 // Write port to portFile 075 File portFile = config.getPortFile(); 076 077 portFile.createNewFile(); 078 portFile.deleteOnExit(); 079 080 new Persister().write(portTO, portFile); 081 082 // Start operation (blocks!) 083 watchOperationResult = watchOperation.execute(); 084 085 logger.log(Level.INFO, "STOPPED watch at " + config.getLocalDir()); 086 } 087 catch (Exception e) { 088 logger.log(Level.SEVERE, "ERROR while running watch at " + config.getLocalDir(), e); 089 } 090 } 091 }, "WR/" + config.getLocalDir().getName()); 092 093 watchThread.start(); 094 } 095 096 public void stop() { 097 watchOperation.stop(); 098 config.getPortFile().delete(); 099 100 watchThread = null; 101 } 102 103 public boolean hasStopped() { 104 return watchOperationResult != null; 105 } 106 107 public boolean isSyncRunning() { 108 return watchOperation.isSyncRunning(); 109 } 110 111 @Subscribe 112 public void onRequestReceived(FolderRequest folderRequest) { 113 File requestRootFolder = new File(folderRequest.getRoot()); 114 boolean localDirMatches = requestRootFolder.equals(config.getLocalDir()); 115 116 if (localDirMatches) { 117 logger.log(Level.INFO, "Received " + folderRequest); 118 119 try { 120 if (!watchOperation.isSyncRunning() && !watchOperation.isSyncRequested()) { 121 watchOperation.pause(); 122 123 FolderRequestHandler handler = FolderRequestHandler.createFolderRequestHandler(folderRequest, config); 124 Response response = handler.handleRequest(folderRequest); 125 126 if (response != null) { 127 eventBus.post(response); 128 } 129 130 watchOperation.resume(); 131 } 132 else { 133 logger.log(Level.WARNING, "FolderRequest discarded : ", folderRequest); 134 eventBus.post(new AlreadySyncingResponse(folderRequest.getId(), "FolderRequest discarded.")); 135 } 136 } 137 catch (Exception e) { 138 logger.log(Level.FINE, "Failed to process request", e); 139 eventBus.post(new BadRequestResponse(folderRequest.getId(), "Invalid request.")); 140 } 141 } 142 } 143}