View Javadoc
1   /**
2    * Copyright 2010-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.common.util.channel.model;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.InputStream;
20  import java.util.List;
21  
22  import org.codehaus.plexus.util.cli.StreamConsumer;
23  import org.kuali.common.util.Assert;
24  import org.kuali.common.util.Encodings;
25  import org.kuali.common.util.Str;
26  import org.kuali.common.util.stream.NoOpStreamConsumer;
27  
28  import com.google.common.base.Optional;
29  import com.google.common.collect.ImmutableList;
30  
31  public final class CommandContext {
32  
33  	private final byte[] command;
34  	private final Optional<InputStream> stdin;
35  	private final Optional<Integer> timeout;
36  	private final StreamConsumer stdout;
37  	private final StreamConsumer stderr;
38  	private final List<Integer> successCodes;
39  	private final boolean ignoreExitValue;
40  
41  	public static class Builder {
42  
43  		private static final int SUCCESS = 0;
44  		private static final String UTF8 = Encodings.UTF8;
45  
46  		// Required
47  		private final byte[] command;
48  
49  		// Optional
50  		private Optional<InputStream> stdin = Optional.absent(); // Don't supply anything to stdin by default
51  		private Optional<Integer> timeout = Optional.absent(); // Default is to wait forever
52  		private StreamConsumer stdout = NoOpStreamConsumer.INSTANCE; // Ignore anything produced on stdout, by default
53  		private StreamConsumer stderr = NoOpStreamConsumer.INSTANCE; // Ignore anything produced on stderr, by default
54  		private List<Integer> successCodes = ImmutableList.of(SUCCESS); // Expect zero as an exit value
55  		private boolean ignoreExitValue = false; // Set this to true if you want to ignore the exit value of the process
56  
57  		/**
58  		 * Pass this command to a remote server as a sequence of bytes encoded using UTF-8
59  		 */
60  		public Builder(String command) {
61  			this(command, UTF8);
62  		}
63  
64  		/**
65  		 * Pass this command to a remote server as a sequence of bytes encoded using the indicated encoding
66  		 */
67  		public Builder(String command, String encoding) {
68  			this(Str.getBytes(command, encoding));
69  		}
70  
71  		public Builder(byte[] command) {
72  			this.command = command;
73  		}
74  
75  		/**
76  		 * Convert the string into a <code>byte[]</code> using UTF-8 encoding
77  		 */
78  		public Builder stdin(String stdin) {
79  			return stdin(stdin, UTF8);
80  		}
81  
82  		/**
83  		 * Convert the string into a <code>byte[]</code> using the indicated encoding
84  		 */
85  		public Builder stdin(String stdin, String encoding) {
86  			Assert.noBlanks(stdin, encoding);
87  			byte[] bytes = Str.getBytes(stdin, encoding);
88  			return stdin(new ByteArrayInputStream(bytes));
89  		}
90  
91  		public Builder stdin(InputStream stdin) {
92  			this.stdin = Optional.of(stdin);
93  			return this;
94  		}
95  
96  		public Builder timeout(int timeout) {
97  			this.timeout = Optional.of(timeout);
98  			return this;
99  		}
100 
101 		public Builder stdout(StreamConsumer stdout) {
102 			this.stdout = stdout;
103 			return this;
104 		}
105 
106 		public Builder stderr(StreamConsumer stderr) {
107 			this.stderr = stderr;
108 			return this;
109 		}
110 
111 		public Builder ignoreExitValue(boolean ignoreExitValue) {
112 			this.ignoreExitValue = ignoreExitValue;
113 			return this;
114 		}
115 
116 		public Builder successCodes(List<Integer> successCodes) {
117 			this.successCodes = successCodes;
118 			return this;
119 		}
120 
121 		public CommandContext build() {
122 			Assert.noNulls(command, stdin, timeout, stdout, stderr, successCodes);
123 			if (timeout.isPresent()) {
124 				Assert.notNegative(timeout.get());
125 			}
126 			this.successCodes = ImmutableList.copyOf(successCodes);
127 			return new CommandContext(this);
128 		}
129 
130 	}
131 
132 	private CommandContext(Builder builder) {
133 		this.command = builder.command;
134 		this.stdin = builder.stdin;
135 		this.timeout = builder.timeout;
136 		this.stderr = builder.stderr;
137 		this.stdout = builder.stdout;
138 		this.successCodes = builder.successCodes;
139 		this.ignoreExitValue = builder.ignoreExitValue;
140 
141 	}
142 
143 	public byte[] getCommand() {
144 		return command;
145 	}
146 
147 	public Optional<InputStream> getStdin() {
148 		return stdin;
149 	}
150 
151 	public Optional<Integer> getTimeout() {
152 		return timeout;
153 	}
154 
155 	public StreamConsumer getStdout() {
156 		return stdout;
157 	}
158 
159 	public StreamConsumer getStderr() {
160 		return stderr;
161 	}
162 
163 	public List<Integer> getSuccessCodes() {
164 		return successCodes;
165 	}
166 
167 	public boolean isIgnoreExitValue() {
168 		return ignoreExitValue;
169 	}
170 
171 }