001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.file.remote; 018 019 import java.io.IOException; 020 021 import org.apache.camel.Exchange; 022 import org.apache.camel.Processor; 023 import org.apache.camel.component.file.GenericFile; 024 import org.apache.camel.component.file.GenericFileConsumer; 025 import org.apache.camel.component.file.GenericFileOperationFailedException; 026 import org.apache.camel.util.FileUtil; 027 028 /** 029 * Base class for remote file consumers. 030 */ 031 public abstract class RemoteFileConsumer<T> extends GenericFileConsumer<T> { 032 protected boolean loggedIn; 033 034 public RemoteFileConsumer(RemoteFileEndpoint<T> endpoint, Processor processor, RemoteFileOperations<T> operations) { 035 super(endpoint, processor, operations); 036 this.setPollStrategy(new RemoteFilePollingConsumerPollStrategy()); 037 } 038 039 @Override 040 @SuppressWarnings("unchecked") 041 public RemoteFileEndpoint<T> getEndpoint() { 042 return (RemoteFileEndpoint<T>) super.getEndpoint(); 043 } 044 045 protected RemoteFileOperations getOperations() { 046 return (RemoteFileOperations) operations; 047 } 048 049 protected boolean prePollCheck() throws Exception { 050 if (log.isTraceEnabled()) { 051 log.trace("prePollCheck on " + getEndpoint().getConfiguration().remoteServerInformation()); 052 } 053 try { 054 if (getEndpoint().getMaximumReconnectAttempts() > 0) { 055 // only use recoverable if we are allowed any re-connect attempts 056 recoverableConnectIfNecessary(); 057 } else { 058 connectIfNecessary(); 059 } 060 } catch (Exception e) { 061 loggedIn = false; 062 063 // login failed should we thrown exception 064 if (getEndpoint().getConfiguration().isThrowExceptionOnConnectFailed()) { 065 throw e; 066 } 067 } 068 069 if (!loggedIn) { 070 String message = "Cannot connect/login to: " + remoteServer() + ". Will skip this poll."; 071 log.warn(message); 072 return false; 073 } 074 075 return true; 076 } 077 078 @Override 079 protected void postPollCheck() { 080 if (log.isTraceEnabled()) { 081 log.trace("postPollCheck on " + getEndpoint().getConfiguration().remoteServerInformation()); 082 } 083 if (getEndpoint().isDisconnect()) { 084 log.trace("postPollCheck disconnect from: {}", getEndpoint()); 085 disconnect(); 086 } 087 } 088 089 @Override 090 protected void processExchange(Exchange exchange) { 091 // mark the exchange to be processed synchronously as the ftp client is not thread safe 092 // and we must execute the callbacks in the same thread as this consumer 093 exchange.setProperty(Exchange.UNIT_OF_WORK_PROCESS_SYNC, Boolean.TRUE); 094 super.processExchange(exchange); 095 } 096 097 @Override 098 protected void doStop() throws Exception { 099 super.doStop(); 100 disconnect(); 101 } 102 103 protected void disconnect() { 104 // eager indicate we are no longer logged in 105 loggedIn = false; 106 107 // disconnect 108 try { 109 if (getOperations().isConnected()) { 110 if (log.isDebugEnabled()) { 111 log.debug("Disconnecting from: {}", remoteServer()); 112 } 113 getOperations().disconnect(); 114 } 115 } catch (GenericFileOperationFailedException e) { 116 // ignore just log a warning 117 log.warn("Error occurred while disconnecting from " + remoteServer() + " due: " + e.getMessage() + ". This exception will be ignored."); 118 } 119 } 120 121 protected void recoverableConnectIfNecessary() throws Exception { 122 try { 123 connectIfNecessary(); 124 } catch (Exception e) { 125 if (log.isDebugEnabled()) { 126 log.debug("Could not connect to: " + getEndpoint() + ". Will try to recover.", e); 127 } 128 loggedIn = false; 129 } 130 131 // recover by re-creating operations which should most likely be able to recover 132 if (!loggedIn) { 133 log.debug("Trying to recover connection to: {} with a fresh client.", getEndpoint()); 134 setOperations(getEndpoint().createRemoteFileOperations()); 135 connectIfNecessary(); 136 } 137 } 138 139 protected void connectIfNecessary() throws IOException { 140 if (!loggedIn) { 141 if (log.isDebugEnabled()) { 142 log.debug("Not connected/logged in, connecting to: {}", remoteServer()); 143 } 144 loggedIn = getOperations().connect((RemoteFileConfiguration) endpoint.getConfiguration()); 145 if (loggedIn) { 146 log.info("Connected and logged in to: " + remoteServer()); 147 } 148 } 149 } 150 151 /** 152 * Returns human readable server information for logging purpose 153 */ 154 protected String remoteServer() { 155 return ((RemoteFileEndpoint) endpoint).remoteServerInformation(); 156 } 157 158 @Override 159 protected boolean isMatched(GenericFile<T> file, String doneFileName) { 160 // ftp specific as we need to cater for stepwise 161 if (getEndpoint().getConfiguration().isStepwise()) { 162 // stepwise enabled, so done file should always be without path 163 doneFileName = FileUtil.stripPath(doneFileName); 164 } 165 166 return super.isMatched(file, doneFileName); 167 } 168 }