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.exec;
018    
019    import org.apache.camel.Consumer;
020    import org.apache.camel.Processor;
021    import org.apache.camel.Producer;
022    import org.apache.camel.component.exec.impl.DefaultExecBinding;
023    import org.apache.camel.component.exec.impl.DefaultExecCommandExecutor;
024    import org.apache.camel.component.exec.impl.ExecParseUtils;
025    import org.apache.camel.impl.DefaultEndpoint;
026    import org.apache.camel.util.ObjectHelper;
027    
028    /**
029     * The endpoint utilizes an {@link ExecCommandExecutor} to execute a system
030     * command when it receives message exchanges.
031     *
032     * @see ExecBinding
033     * @see ExecCommandExecutor
034     * @see ExecCommand
035     * @see ExecResult
036     */
037    public class ExecEndpoint extends DefaultEndpoint {
038    
039        /**
040         * Indicates that no {@link #timeout} is used.
041         */
042        public static final long NO_TIMEOUT = Long.MAX_VALUE;
043    
044        private String executable;
045    
046        private String args;
047    
048        private String workingDir;
049    
050        private long timeout;
051    
052        private String outFile;
053    
054        private ExecCommandExecutor commandExecutor;
055    
056        private ExecBinding binding;
057    
058        private boolean useStderrOnEmptyStdout;
059    
060        public ExecEndpoint(String uri, ExecComponent component) {
061            super(uri, component);
062            this.timeout = NO_TIMEOUT;
063            this.binding = new DefaultExecBinding();
064            this.commandExecutor = new DefaultExecCommandExecutor();
065        }
066    
067        public Producer createProducer() throws Exception {
068            return new ExecProducer(this);
069        }
070    
071        public Consumer createConsumer(Processor processor) throws Exception {
072            throw new UnsupportedOperationException("Consumer not supported for ExecEndpoint!");
073        }
074    
075        public boolean isSingleton() {
076            return true;
077        }
078    
079        /**
080         * @return the executable to be executed; that is the remaining part of the
081         *         endpoint URI
082         * @see ExecBinding#EXEC_COMMAND_EXECUTABLE
083         */
084        public String getExecutable() {
085            return executable;
086        }
087    
088        /**
089         * Sets the executable to be executed. The executable must not be empty or
090         * <code>null</code>.
091         * 
092         * @param executable Sets the executable to be executed.
093         */
094        public void setExecutable(String executable) {
095            ObjectHelper.notEmpty(executable, "executable");
096            this.executable = executable;
097        }
098    
099        /**
100         * The arguments may be one or many whitespace-separated tokens, that can be
101         * quoted with ", e.g. <code>args="arg 1" arg2"</code> will use two arguments
102         * <code>arg 1</code> and <code>arg2</code>. To include the quotes use
103         * <code>""</code><br>
104         * , e.g. <code>args=""arg 1"" arg2</code> will use the arguments
105         * <code>"arg 1"</code> and <code>arg2</code>.
106         * 
107         * @return the arguments of the executable application, as configured from
108         *         the endpoint URI.
109         * @see ExecBinding#EXEC_COMMAND_ARGS
110         * @see ExecParseUtils#splitToWhiteSpaceSeparatedTokens(String)
111         */
112        public String getArgs() {
113            return args;
114        }
115    
116        /**
117         * Sets the arguments of the executable application
118         * 
119         * @param args Returns <code>null</code> value if no arguments are
120         *            configured in the endpoint URI
121         * @see #getArgs()
122         * @see ExecBinding#EXEC_COMMAND_ARGS
123         */
124        public void setArgs(String args) {
125            this.args = args;
126        }
127    
128        /**
129         * @return the working directory of the executable, or <code>null</code> is
130         *         such is not set.
131         * @see ExecBinding#EXEC_COMMAND_WORKING_DIR
132         */
133        public String getWorkingDir() {
134            return workingDir;
135        }
136    
137        /**
138         * Sets the working directory of the executable.
139         * 
140         * @param dir the working directory of the executable. <code>null</code>
141         *            values indicates that the current working directory will be
142         *            used.
143         */
144        public void setWorkingDir(String dir) {
145            this.workingDir = dir;
146        }
147    
148        /**
149         * @return The returned value is always a positive <code>long</code>. The
150         *         default value is {@link ExecEndpoint#NO_TIMEOUT}
151         * @see ExecBinding#EXEC_COMMAND_TIMEOUT
152         */
153        public long getTimeout() {
154            return timeout;
155        }
156    
157        /**
158         * Sets the timeout.
159         * 
160         * @param timeout The <code>timeout</code> must be a positive long
161         * @see ExecBinding#EXEC_COMMAND_TIMEOUT
162         */
163        public void setTimeout(long timeout) {
164            if (timeout <= 0) {
165                throw new IllegalArgumentException("The timeout must be a positive long!");
166            }
167            this.timeout = timeout;
168        }
169    
170        /**
171         * @return <code>null</code> if no out file is set, otherwise returns the
172         *         value of the outFile
173         * @see ExecBinding#EXEC_COMMAND_OUT_FILE
174         */
175        public String getOutFile() {
176            return outFile;
177        }
178    
179        /**
180         * @param outFile a not-empty file path
181         * @see ExecBinding#EXEC_COMMAND_OUT_FILE
182         */
183        public void setOutFile(String outFile) {
184            ObjectHelper.notEmpty(outFile, "outFile");
185            this.outFile = outFile;
186        }
187    
188        /**
189         * @return The command executor used to execute commands. Defaults to
190         *         {@link org.apache.camel.component.exec.impl.DefaultExecCommandExecutor}
191         */
192        public ExecCommandExecutor getCommandExecutor() {
193            return commandExecutor;
194        }
195    
196        /**
197         * Sets a custom executor to execute commands.
198         * 
199         * @param commandExecutor a not-null instance of {@link ExecCommandExecutor}
200         */
201        public void setCommandExecutor(ExecCommandExecutor commandExecutor) {
202            ObjectHelper.notNull(commandExecutor, "commandExecutor");
203            this.commandExecutor = commandExecutor;
204        }
205    
206        public ExecBinding getBinding() {
207            return binding;
208        }
209    
210        public void setBinding(ExecBinding binding) {
211            ObjectHelper.notNull(binding, "binding");
212            this.binding = binding;
213        }
214    
215        public boolean isUseStderrOnEmptyStdout() {
216            return useStderrOnEmptyStdout;
217        }
218    
219        public void setUseStderrOnEmptyStdout(boolean useStderrOnEmptyStdout) {
220            this.useStderrOnEmptyStdout = useStderrOnEmptyStdout;
221        }
222    }