View Javadoc

1   // SendFax2.java - gnu.hylafax implementation of the sendfax utility
2   // $Id: SendFax2.java,v 1.3 2007/05/07 18:26:53 sjardine Exp $
3   //
4   // - basically gives an example for queuing a FAX job
5   //
6   // Copyright 2000, 2001, Joe Phillips <jaiger@innovationsw.com>
7   // Copyright 2001, Innovation Software Group, LLC - http://www.innovationsw.com
8   // Copyright 2006, John Yeary <jyeary@javanetwork.net>
9   //
10  // This library is free software; you can redistribute it and/or
11  // modify it under the terms of the GNU Library General Public
12  // License as published by the Free Software Foundation; either
13  // version 2 of the License, or (at your option) any later version.
14  //
15  // This library is distributed in the hope that it will be useful,
16  // but WITHOUT ANY WARRANTY; without even the implied warranty of
17  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  // Library General Public License for more details.
19  //
20  // You should have received a copy of the GNU Library General Public
21  // License along with this library; if not, write to the Free
22  // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  //
24  //
25  // for information on the HylaFAX FAX server see
26  //  http://www.hylafax.org/
27  //
28  // KNOWN ISSUES:
29  // - The password dialog is echoed to the screen, beware
30  // - not all symbolic pagesizes are supported yet (see Job.pagesizes)
31  // - can only queue a single job to the server per execution
32  //
33  // TODO make this class more flexible so it can be used by other programs rather than only called from the command line don't echo the password to the screen
34  //
35  
36  package gnu.hylafax.util;
37  
38  import gnu.hylafax.ClientProtocol;
39  import gnu.hylafax.HylaFAXClient;
40  import gnu.hylafax.Job;
41  import gnu.hylafax.Pagesize;
42  
43  import java.awt.Dimension;
44  import java.io.BufferedReader;
45  import java.io.FileInputStream;
46  import java.io.InputStreamReader;
47  import java.util.Iterator;
48  import java.util.Vector;
49  
50  import org.apache.commons.cli.CommandLine;
51  import org.apache.commons.cli.CommandLineParser;
52  import org.apache.commons.cli.GnuParser;
53  import org.apache.commons.cli.HelpFormatter;
54  import org.apache.commons.cli.Option;
55  import org.apache.commons.cli.OptionBuilder;
56  import org.apache.commons.cli.Options;
57  import org.apache.commons.cli.ParseException;
58  import org.apache.commons.logging.Log;
59  import org.apache.commons.logging.LogFactory;
60  
61  /***
62   * This class implements most of the sendfax program as supplied with the
63   * HylaFAX distribution. Not all options/features of the HylaFAX sendfax command
64   * are supported.
65   * <P>
66   * <b>Specifically:</b>
67   * <UL>
68   * <LI>only one Job with one destination can be queued per execution
69   * <LI>only HylaFAX <I>server</I> native file formats can be part of a job.
70   * i.e. no client-side document conversions are performed
71   * <LI>no built-in faxcover support
72   * </UL>
73   * The following command line options are supported.
74   * <P>
75   * 
76   * <PRE>
77   * 
78   * -h &lt;host&gt; specifiy server hostname -u &lt;user&gt; user to login to the
79   * server with -v set verbose mode -d &lt;number&gt; specify a destination FAX
80   * <number> -f &lt;sender&gt; user &lt;sender&gt; as the identity of the FAX
81   * sender -k &lt;time&gt; kill the job if it doesn't complete after the
82   * indicated <time> -t &lt;tries&gt; make no more than &lt;tries&gt; attempts to
83   * deliver the FAX -T &lt;dials&gt; maximum number of &lt;dials&gt; to attempt
84   * for each job -D enable delivery notification -R enable delivery and retry
85   * notification -N disable delivery and retry notification -P &lt;priority&gt;
86   * assign the &lt;priority&gt; priority to the job (default: 127) -l use low
87   * resolution (98 dpi) -m use medium resolution (196 dpi) -s &lt;size&gt;
88   * specify the symbolic page &lt;size&gt; (legal, us-let, a3, a4, etc.)
89   * 
90   * </PRE>
91   * 
92   * <P>
93   * Refer to the sendfax man page (from the HylaFAX distribution) for more
94   * information.
95   * <P>
96   * This program has been modified to remove dependencies on
97   * gnu.getopt(java-getopt) program, and has replaced the command line parser
98   * with <a href="http://jakarta.apache.org/commons/cli/">Apache Jakarta Commons
99   * CLI</a>
100  */
101 public class SendFax2 {
102 
103     private final static Log log = LogFactory.getLog(SendFax2.class);
104 
105 	private static Options options = new Options();
106 
107 	private static HelpFormatter hf = new HelpFormatter();
108 
109 	public static void main(String[] args) {
110 		String user = "fax"; // -u
111 		String host = "localhost"; // -h
112 		String destination = null; // -d
113 		String from = user; // -f
114 		String killtime = "000259"; // -k
115 		int maxdials = 12; // -T
116 		int maxtries = 3; // -t
117 		int priority = 127; // -P
118 		String notifyaddr = user; // -f
119 		int resolution = 98; // -l, -m
120 		Dimension pagesize; // -s
121 		String notify = "none";
122 		String pagechop = "default";
123 		int chopthreshold = 3;
124 		Vector documents = new Vector();
125 		boolean verbose = false;
126 		boolean from_is_set = false;
127 		pagesize = Pagesize.LETTER; // default pagesize is US Letter
128 		char opt;
129 
130 		// Define our command line options
131 		Option u = OptionBuilder.withArgName("user").hasArg().withDescription(
132 				"user to login to the server with").create('u');
133 
134 		Option h = OptionBuilder.withArgName("host").hasArg().withDescription(
135 				"specify the fax server hostname").create('h');
136 
137 		Option d = OptionBuilder.withArgName("number").hasArg()
138 				.withDescription("specify a destination FAX <number>").create(
139 						'd');
140 
141 		Option f = OptionBuilder.withArgName("sender").hasArg()
142 				.withDescription(
143 						"user <sender> as the identity of the FAX sender")
144 				.create('f');
145 
146 		Option k = OptionBuilder
147 				.withArgName("time")
148 				.hasArg()
149 				.withDescription(
150 						"kill the job if it doesn't complete after the indicated <time> (default: \"000259\", 2 hours, 59 minutes)")
151 				.create('k');
152 
153 		Option T = OptionBuilder
154 				.withArgName("dials")
155 				.hasArg()
156 				.withDescription(
157 						"maximum number of <dials> to attempt for each job (default: 12)")
158 				.create('T');
159 
160 		Option t = OptionBuilder
161 				.withArgName("tries")
162 				.hasArg()
163 				.withDescription(
164 						"make no more than <tries> attempts to deliver the FAX (default: 3)")
165 				.create('t');
166 
167 		Option P = OptionBuilder
168 				.withArgName("priority")
169 				.hasArg()
170 				.withDescription(
171 						"assign the <priority> priority to the job (default: 127)")
172 				.create('P');
173 
174 		Option s = OptionBuilder
175 				.withArgName("size")
176 				.hasArg()
177 				.withDescription(
178 						"specify the symbolic page <size> (legal, us-let, a3, a4, etc.)")
179 				.create('s');
180 
181 		Option l = OptionBuilder.withDescription("use low resolution (98 dpi)")
182 				.create('l');
183 
184 		Option m = OptionBuilder.withDescription(
185 				"use medium resolution (196 dpi)").create('m');
186 
187 		Option v = OptionBuilder.withDescription("set verbose mode")
188 				.create('v');
189 
190 		Option D = OptionBuilder
191 				.withDescription("enable delivery notification").create('D');
192 
193 		Option R = OptionBuilder.withDescription(
194 				"enable delivery and retry notification").create('R');
195 
196 		Option N = OptionBuilder.withDescription(
197 				"disable delivery and retry notification").create('N');
198 
199 		// Add the options to our list of options.
200 		options.addOption(u);
201 		options.addOption(h);
202 		options.addOption(d);
203 		options.addOption(f);
204 		options.addOption(k);
205 		options.addOption(T);
206 		options.addOption(t);
207 		options.addOption(P);
208 		options.addOption(l);
209 		options.addOption(m);
210 		options.addOption(s);
211 		options.addOption(v);
212 		options.addOption(D);
213 		options.addOption(R);
214 		options.addOption(N);
215 
216 		HylaFAXClient c = new HylaFAXClient();
217 		CommandLineParser parser = new GnuParser();
218 		CommandLine line = null;
219 
220 		try {
221 			line = parser.parse(options, args);
222 		} catch (ParseException ex) {
223 			ex.printStackTrace();
224 			System.exit(-1);
225 		}
226 
227 		// <<<<<<< PARSE using for each loop would be a better option for J5SE
228 		// 1.5+ (This would result in a dependency on J5SE 1.5+)
229 
230 		Iterator it = line.iterator();
231 		while (it.hasNext()) {
232 			Option o = (Option) it.next();
233 			switch (o.getOpt().charAt(0)) {
234 			case 'd':
235 				// destination
236 				destination = o.getValue();
237 				break;
238 			case 'f':
239 				// from address
240 				from_is_set = true;
241 				from = o.getValue();
242 				break;
243 			case 'k':
244 				// killtime
245 				killtime = o.getValue();
246 				break;
247 			case 'h':
248 				host = o.getValue();
249 				break;
250 			case 'l':
251 				// low-res
252 				resolution = Job.RESOLUTION_LOW;
253 				break;
254 			case 'm':
255 				// medium-res
256 				resolution = Job.RESOLUTION_MEDIUM;
257 				break;
258 			case 't':
259 				maxtries = Integer.parseInt(o.getValue());
260 				break;
261 			case 'T':
262 				maxdials = Integer.parseInt(o.getValue());
263 				break;
264 			case 'D':
265 				notify = Job.NOTIFY_DONE;
266 				break;
267 			case 'R':
268 				notify = Job.NOTIFY_REQUEUE;
269 				break;
270 			case 'N':
271 				notify = Job.NOTIFY_NONE;
272 				break;
273 			case 'P':
274 				priority = Integer.parseInt(o.getValue());
275 				break;
276 			case 's':
277 				pagesize = Pagesize.getPagesize(o.getValue());
278 				if (pagesize == null) {
279 					// no good
280 					System.err.println(o.getValue()
281 							+ " is not a valid pagesize value");
282 					usage();
283 					System.exit(-1);
284 				}
285 				break;
286 			case 'u':
287 				user = o.getValue();
288 				break;
289 			case 'v':
290 				// verbose mode
291 				verbose = true;
292 				break;
293 			case '?':
294 				usage();
295 				System.exit(-1);
296 				break;
297 			default:
298 				usage();
299 				System.exit(-1);
300 				// error
301 				break;
302 			}
303 		}
304 
305 		// validate some parameters
306 		if (!from_is_set) {
307 			from = user;
308 		}
309 
310 		// there should be a destination
311 		if (destination == null) {
312 			// destination is required
313 			System.err.println("A destination fax number is required.");
314 			usage();
315 			System.exit(-1);
316 		}
317 
318 		// make sure there is at least one file to send
319 		String files[] = line.getArgs();
320 
321 		if (files.length < 1) {
322 			// at least one document is required
323 			System.err.println("No files specified.");
324 			usage();
325 			System.exit(-1);
326 		}
327 
328 		// get down to business, send the FAX already
329 		try {
330 			c.open(host);
331 
332 			if (c.user(user)) {
333 				// need password
334 				System.out.print("Password:");
335 				BufferedReader input = new BufferedReader(
336 						new InputStreamReader(System.in));
337 				String password = input.readLine();
338 				c.pass(password);
339 			}
340 
341 			c.noop(); // for the heck of it
342 			c.tzone(ClientProtocol.TZONE_LOCAL);
343 
344 			// Send files up to server
345 
346 			for (int i = 0; i < files.length; i++) {
347 				FileInputStream file = new FileInputStream(files[i]);
348 				String remote_filename = c.putTemporary(file);
349 				documents.addElement(remote_filename);
350 			}
351 
352 			Job job = c.createJob(); // start a new job
353 
354 			// set job properties
355 			job.setFromUser(from);
356 			job.setNotifyAddress(from);
357 			job.setKilltime(killtime);
358 			job.setMaximumDials(maxdials);
359 			job.setMaximumTries(maxtries);
360 			job.setPriority(priority);
361 			job.setDialstring(destination);
362 			job.setVerticalResolution(resolution);
363 			job.setPageDimension(pagesize);
364 			job.setNotifyType(notify);
365 			job.setChopThreshold(chopthreshold);
366 
367 			// add documents to the job
368 			for (int i = 0; i < documents.size(); i++) {
369 				String document = (String) documents.elementAt(i);
370 				job.addDocument(document);
371 			}
372 
373 			c.submit(job); // submit the job to the scheduler
374 
375 		} catch (Exception e) {
376 			log.error(e.getMessage(), e);
377 		} finally {
378 			// disconnect from the server
379 			try {
380 				c.quit();
381 			} catch (Exception e) {
382 				// quit failed, not much we can do now
383 				log.error(e.getMessage(), e);
384 			}
385 		}
386 	}
387 
388 	/***
389 	 * print out usage information on this program
390 	 */
391 	public static void usage() {
392 		// Make a pretty help output for usage.
393 		hf
394 				.printHelp(
395 						"SendFax <options> file1 ...",
396 						null,
397 						options,
398 						"Files queued must be formats that the HylaFAX server can handle natively (PS, TIFF, etc.) as no client-side conversions are performed.");
399 	}
400 }