📄 hylafaxclienthelper.java
字号:
/**
* JHylaFax - A java client for HylaFAX.
*
* Copyright (C) 2005 by Steffen Pingel <steffenp@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package net.sf.jhylafax.fax;
import gnu.hylafax.Job;
import gnu.inet.ftp.ServerResponseException;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.TimeZone;
import net.sf.jhylafax.Settings;
import net.sf.jhylafax.fax.FaxJob.JobType;
import net.sf.jhylafax.fax.FaxJob.PageChopping;
import net.sf.jhylafax.fax.Modem.Volume;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Provides static methods to handle the server communication.
*
* @author Steffen Pingel
*/
public class HylaFAXClientHelper extends Thread {
/**
* The format used for docq, contains all valid tokens except %p.
*
* <p>Note: %a, %c, %m adds a line break, therefore it needs to be last.
*/
public final static String FILEFMT = "__FILEFMT |%d |%f |%g |%i |%l |%o |%p |%q |%r |%s |%m ";
/**
* The format used for sendq and doneq, contains all valid tokens except %T,
* %Z, %z.
*
* <p>Note: %s may contain line breaks, therefore it is last
*/
public final static String JOBFMT = "__JOBFMT |%a |%b |%c |%e |%f |%g |%h |%i |%j |%k |%l |%m |%n |%o |%p |%q |%r |%t |%u |%v |%w |%x |%y |%z"
+ " |%A |%B |%C |%D |%E |%F |%G |%H |%I |%J |%K |%L |%M |%N |%O |%P |%Q |%R |%S |%U |%V |%W |%X |%Y |%Z |%s ";
private final static Log logger = LogFactory.getLog(HylaFAXClientHelper.class);
/**
* The format used for modem status, contains all valid tokens.
*/
public final static String MODEMFMT = "__MODEMFMT |%h |%l |%m |%n |%r |%s |%t |%v |%z ";
/**
* The format strings need an additional space to avoid empty tokens.
*/
protected final static String QUEUE_SEPARATOR = "|";
/**
* The format used for recvq, contains all valid tokens except %m, %t.
*
* <p>%q has been removed as well since it causes some versions of HylaFAX
* to segfault (#1496477).
*/
//public final static String RCVFMT = "__RCVFMT |%Y |%a |%b |%d |%e |%f |%h |%i |%j |%l |%n |%o |%p |%q |%r |%s |%w |%z ";
public final static String RCVFMT = "__RCVFMT |%Y |%a |%b |%d |%e |%f |%h |%i |%j |%l |%n |%o |%p |%r |%s |%w |%z ";
private static DateFormat fileDateFormat = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", Locale.ENGLISH);
public static void applyParameter(Job faxJob, FaxJob job) throws ServerResponseException, IOException
{
//faxJob.setChopThreshold(3);
faxJob.setDialstring(job.getNumber());
if (job.getSender() != null && job.getSender().trim().length() > 0) {
faxJob.setFromUser(job.getSender());
}
faxJob.setKilltime("000259");
faxJob.setMaximumDials(job.getMaxDials());
faxJob.setMaximumTries(job.getMaxDials());
if (job.getNotifyAdress() != null && job.getNotifyAdress().trim().length() > 0) {
faxJob.setNotifyAddress(job.getNotifyAdress());
}
if (job.getNotify() != null) {
faxJob.setNotifyType(job.getNotify());
}
faxJob.setPageChop(Job.CHOP_DEFAULT);
faxJob.setPageWidth(job.getPageWidth());
faxJob.setPageLength(job.getPageLength());
faxJob.setPriority(job.getPriority());
faxJob.setProperty("SENDTIME", calculateTime(job.getSendTime(), Settings.TIMEZONE.getValue()));
faxJob.setVerticalResolution(job.getVerticalResolution());
}
public static String calculateTime(Date sendTime, String timeZoneID) {
if (sendTime == null) {
return "NOW";
}
else {
long date = sendTime.getTime();
TimeZone tz = TimeZone.getTimeZone(timeZoneID);
// tz.setStartRule(Calendar.MARCH, -1, Calendar.SUNDAY, 2*60*60*1000);
// tz.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);
date -= tz.getRawOffset();
if (tz.inDaylightTime(sendTime)) {
date -= 3600 * 1000;
}
return new SimpleDateFormat("yyyyMMddHHmm").format(new Date(date));
}
}
private static JobType getJobType(char c)
{
switch (c) {
case 'P':
return JobType.PAGER;
default: // 'F'
return JobType.FACSIMILE;
}
}
private final static String getNotify(char notify) {
switch (notify) {
case 'D' :
return Job.NOTIFY_DONE;
case 'Q' :
return Job.NOTIFY_REQUEUE;
case 'A' :
return Job.NOTIFY_ALL;
default :
return Job.NOTIFY_NONE;
}
}
private static PageChopping getPageChopping(char c)
{
switch (c) {
case 'D':
return PageChopping.DISABLED;
case 'A':
return PageChopping.ALL;
case 'L':
return PageChopping.LAST;
default: // ' '
return PageChopping.DEFAULT;
}
}
public final static FaxJob.State getState(char state) {
switch (state) {
case 'T' :
return FaxJob.State.SUSPENDED;
case 'P' :
return FaxJob.State.PENDING;
case 'S' :
return FaxJob.State.SLEEPING;
case 'B' :
return FaxJob.State.BLOCKED;
case 'W' :
return FaxJob.State.WAITING;
case 'D' :
return FaxJob.State.DONE;
case 'R' :
return FaxJob.State.RUNNING;
case 'F' :
return FaxJob.State.FAILED;
default : // '?'
return FaxJob.State.UNDEFINED;
}
}
private static Volume getVolume(char c)
{
// TODO add switch
return Volume.OFF;
}
public final static void initializeFromSettings(FaxJob job) {
job.setSender(Settings.FULLNAME.getValue());
job.setNotifyAdress(Settings.EMAIL.getValue());
job.setMaxDials(Settings.MAXDIALS.getValue());
job.setMaxTries(Settings.MAXTRIES.getValue());
job.setNotify(Settings.NOTIFICATION.getValue().getCommand());
job.setPageLength(Settings.PAPER.getValue().getHeight());
job.setPageWidth(Settings.PAPER.getValue().getWidth());
job.setPriority(Settings.PRIORITY.getValue());
job.setResolution(Settings.RESOLUTION.getValue().getLinesPerInch());
}
public static boolean isPostscript(String filename) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
try {
return in.readLine().startsWith("%!");
}
finally {
try {
in.close();
} catch (IOException e) {
}
}
}
static int parseDuration(String s)
{
StringTokenizer t = new StringTokenizer(s, ":");
int duration = 0;
while (t.hasMoreTokens()) {
int n = Integer.parseInt(t.nextToken());
duration = duration * 60 + n;
}
return duration;
}
public final static Document parseFileFmt(String response) {
StringTokenizer st = new StringTokenizer(response, QUEUE_SEPARATOR);
StringTokenizer jf = new StringTokenizer(FILEFMT, QUEUE_SEPARATOR);
Document file = new Document();
while (st.hasMoreElements() && jf.hasMoreElements()) {
char c = jf.nextToken().charAt(1);
String s = st.nextToken().trim();
if (s.length() > 0) {
try {
// parse
switch (c) {
case 'a':
file.setLastAccessTime(fileDateFormat.parse(s));
break;
case 'c':
file.setCreationTime(fileDateFormat.parse(s));
break;
case 'd':
file.setDeviceNumber(Integer.parseInt(s, 8));
break;
case 'f':
file.setFilename(s);
break;
case 'g':
file.setGroupID(Integer.parseInt(s));
break;
case 'i':
file.setInodeNumber(Long.parseLong(s));
break;
case 'l':
file.setLinkCount(Integer.parseInt(s));
break;
case 'm':
file.setLastModificationTime(fileDateFormat.parse(s));
break;
case 'o':
file.setOwner(s);
break;
case 'p': // Fax-style protection flags (no group bits)
// 'q' is used instead
break;
case 'q':
file.setPermissions(s);
break;
case 'r':
file.setRootDeviceNumber(Integer.parseInt(s));
break;
case 's':
file.setFilesize(Long.parseLong(s));
break;
case 'u':
file.setOwnerID(Integer.parseInt(s));
break;
}
}
catch (NumberFormatException e) {
logger.info("Error parsing respone", e);
}
catch (ParseException e) {
logger.info("Error parsing response", e);
}
}
}
return file;
}
public final static Object parseFmt(String response) {
if (logger.isDebugEnabled()) logger.debug("Received: " + response);
if (response.trim().length() == 0) {
// work around a bug in HylaFax
return null;
}
if (response.startsWith("__JOBFMT")) {
return parseJobFmt(response);
}
else if (response.startsWith("__RCVFMT")) {
return parseRcvFmt(response);
}
else if (response.startsWith("__FILEFMT")) {
return parseFileFmt(response);
}
else if (response.startsWith("__MODEMFMT")) {
return parseModemFmt(response);
}
else {
logger.error("Invalid response: " + response);
return null;
}
}
public final static FaxJob parseJobFmt(String response) {
StringTokenizer st = new StringTokenizer(response, QUEUE_SEPARATOR);
StringTokenizer jf = new StringTokenizer(JOBFMT, QUEUE_SEPARATOR);
FaxJob job = new FaxJob();
while (st.hasMoreElements() && jf.hasMoreElements()) {
char c = jf.nextToken().charAt(1);
String s = st.nextToken().trim();
if (s.length() > 0) {
try {
switch (c) {
case 'a' :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -