/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.sync.engine.document.library.handler; import com.liferay.sync.engine.document.library.event.Event; import com.liferay.sync.engine.document.library.event.GetSyncContextEvent; import com.liferay.sync.engine.document.library.util.FileEventManager; import com.liferay.sync.engine.document.library.util.ServerEventUtil; import com.liferay.sync.engine.model.SyncAccount; import com.liferay.sync.engine.model.SyncFile; import com.liferay.sync.engine.model.SyncSite; import com.liferay.sync.engine.service.SyncAccountService; import com.liferay.sync.engine.service.SyncFileService; import com.liferay.sync.engine.service.SyncSiteService; import com.liferay.sync.engine.util.ConnectionRetryUtil; import java.io.FileNotFoundException; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NoHttpResponseException; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpResponseException; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpHostConnectException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Shinn Lok */ public class BaseHandler implements Handler<Void> { public BaseHandler(Event event) { _event = event; } @Override public String getException(String response) { return null; } @Override public void handleException(Exception e) { if (_event.isCancelled()) { return; } SyncAccount syncAccount = SyncAccountService.fetchSyncAccount( getSyncAccountId()); if (!ConnectionRetryUtil.retryInProgress(getSyncAccountId()) && _logger.isDebugEnabled()) { _logger.debug("Handling exception {}", e.toString()); } if (e instanceof HttpResponseException) { HttpResponseException hre = (HttpResponseException)e; int statusCode = hre.getStatusCode(); if (statusCode == HttpStatus.SC_UNAUTHORIZED) { if (_logger.isDebugEnabled()) { _logger.debug( "Authentication failed. Retrying in {} seconds.", syncAccount.getAuthenticationRetryInterval()); } syncAccount.setState(SyncAccount.STATE_DISCONNECTED); syncAccount.setUiEvent( SyncAccount.UI_EVENT_AUTHENTICATION_EXCEPTION); SyncAccountService.update(syncAccount); ServerEventUtil.retryServerConnection( getSyncAccountId(), syncAccount.getAuthenticationRetryInterval(), TimeUnit.SECONDS); return; } } if (e instanceof ClientProtocolException || e instanceof ConnectTimeoutException || e instanceof HttpHostConnectException || e instanceof NoHttpResponseException || e instanceof SocketException || e instanceof SocketTimeoutException || e instanceof SSLException || e instanceof UnknownHostException) { retryServerConnection(SyncAccount.UI_EVENT_CONNECTION_EXCEPTION); } else if (e instanceof FileNotFoundException) { SyncFile syncFile = (SyncFile)getParameterValue("syncFile"); String message = e.getMessage(); if (message.contains("The process cannot access the file")) { if (_logger.isTraceEnabled()) { _logger.trace( "Retrying event {} for sync file {}", _event, syncFile); } _scheduledExecutorService.schedule(_event, 1, TimeUnit.SECONDS); } else if (syncFile.getVersion() == null) { SyncFileService.deleteSyncFile(syncFile, false); } } else { _logger.error(e.getMessage(), e); } } @Override public boolean handlePortalException(String exception) throws Exception { return false; } @Override public Void handleResponse(HttpResponse httpResponse) { try { if (_event.isCancelled()) { return null; } StatusLine statusLine = httpResponse.getStatusLine(); if ((statusLine.getStatusCode() != HttpStatus.SC_OK) && (statusLine.getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT)) { _logger.error("Status code {}", statusLine.getStatusCode()); throw new HttpResponseException( statusLine.getStatusCode(), statusLine.getReasonPhrase()); } if (_logger.isTraceEnabled()) { Class<?> clazz = getClass(); SyncFile syncFile = (SyncFile)getParameterValue("syncFile"); if (syncFile != null) { _logger.trace( "Handling response {} file path {}", clazz.getSimpleName(), syncFile.getFilePathName()); } else { _logger.trace( "Handling response {}", clazz.getSimpleName()); } } doHandleResponse(httpResponse); } catch (Exception e) { handleException(e); } finally { processFinally(); removeEvent(); } return null; } @Override public void processFinally() { } @Override public void processResponse(String response) throws Exception { } @Override public void removeEvent() { FileEventManager.removeEvent(_event); } protected void doHandleResponse(HttpResponse httpResponse) throws Exception { } protected SyncFile getLocalSyncFile() { SyncFile localSyncFile = (SyncFile)getParameterValue("syncFile"); if (localSyncFile == null) { return null; } return SyncFileService.fetchSyncFile(localSyncFile.getSyncFileId()); } protected Map<String, Object> getParameters() { return _event.getParameters(); } protected Object getParameterValue(String key) { return _event.getParameterValue(key); } protected long getSyncAccountId() { return _event.getSyncAccountId(); } protected void handleSiteDeactivatedException() { SyncSite syncSite = (SyncSite)getParameterValue("syncSite"); if (syncSite == null) { SyncFile syncFile = (SyncFile)getParameterValue("syncFile"); syncSite = SyncSiteService.fetchSyncSite( syncFile.getRepositoryId(), getSyncAccountId()); } if (syncSite != null) { if (_logger.isDebugEnabled()) { _logger.debug( "Sync site {} was deactivated or removed.", syncSite.getName()); } syncSite.setUiEvent(SyncSite.UI_EVENT_SYNC_SITE_DEACTIVATED); SyncSiteService.update(syncSite); SyncSiteService.deleteSyncSite(syncSite.getSyncSiteId()); } } protected boolean isEventCancelled() { return _event.isCancelled(); } protected void retryEvent() { if (isEventCancelled()) { return; } removeEvent(); _event.run(); } protected void retryServerConnection(int uiEvent) { if (!(_event instanceof GetSyncContextEvent) && ConnectionRetryUtil.retryInProgress(getSyncAccountId())) { return; } SyncAccount syncAccount = SyncAccountService.fetchSyncAccount( getSyncAccountId()); int retryCount = ConnectionRetryUtil.getRetryCount(getSyncAccountId()); if (retryCount > 0) { syncAccount.setState(SyncAccount.STATE_DISCONNECTED); syncAccount.setUiEvent(uiEvent); SyncAccountService.update(syncAccount); if (_logger.isDebugEnabled()) { _logger.debug( "Attempting to reconnect to {}. Retry #{}.", syncAccount.getUrl(), retryCount); } } ServerEventUtil.retryServerConnection( getSyncAccountId(), ConnectionRetryUtil.incrementRetryDelay(getSyncAccountId()), TimeUnit.MILLISECONDS); } private static final Logger _logger = LoggerFactory.getLogger( BaseHandler.class); private static final ScheduledExecutorService _scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private final Event _event; }