package com.swingsane.business.scanning; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.jmdns.ServiceInfo; import org.apache.log4j.Logger; import au.com.southsky.jfreesane.OptionValueConstraintType; import au.com.southsky.jfreesane.RangeConstraint; import au.com.southsky.jfreesane.SaneDevice; import au.com.southsky.jfreesane.SaneException; import au.com.southsky.jfreesane.SaneOption; import au.com.southsky.jfreesane.SanePasswordProvider; import com.swingsane.i18n.Localizer; import com.swingsane.preferences.model.BooleanOption; import com.swingsane.preferences.model.ButtonOption; import com.swingsane.preferences.model.Constraints; import com.swingsane.preferences.model.FixedOption; import com.swingsane.preferences.model.GroupOption; import com.swingsane.preferences.model.IntegerOption; import com.swingsane.preferences.model.Option; import com.swingsane.preferences.model.OptionsOrderValuePair; import com.swingsane.preferences.model.OptionsOrderValuePair.SaneOptionType; import com.swingsane.preferences.model.SaneServiceIdentity; import com.swingsane.preferences.model.Scanner; import com.swingsane.preferences.model.StringOption; public class ScanServiceImpl implements IScanService { /** * Log4J logger. */ private static final Logger LOG = Logger.getLogger(ScanServiceImpl.class); /** * Password Provider for authenticating SANE sessions with password protected backends. */ private SanePasswordProvider passwordProvider; private SaneServiceIdentity saneServiceIdentity; @Override public final void configure(SaneDevice saneDevice, Scanner scanner) throws IOException { ArrayList<OptionsOrderValuePair> optionOrdering = scanner.getOptionOrdering(); for (OptionsOrderValuePair vp : optionOrdering) { if (!(vp.isActive())) { continue; } switch (vp.getSaneOptionType()) { case STRING: StringOption stringOption = scanner.getStringOptions().get(vp.getKey()); setDeviceStringOption(saneDevice, stringOption); break; case INTEGER: IntegerOption integerOption = scanner.getIntegerOptions().get(vp.getKey()); setDeviceIntegerOption(saneDevice, integerOption); break; case BOOLEAN: BooleanOption booleanOption = scanner.getBooleanOptions().get(vp.getKey()); setDeviceBooleanOption(saneDevice, booleanOption); break; case FIXED: FixedOption fixedOption = scanner.getFixedOptions().get(vp.getKey()); setDeviceFixedOption(saneDevice, fixedOption); break; case GROUP: // group's don't get configured. case BUTTON: // buttons don't get configured. default: break; } } } @Override public final Scanner create(SaneDevice saneDevice, ServiceInfo serviceInfo, String hostAddress) throws IOException, SaneException { Scanner scanner = new Scanner(); scanner.setServiceName(serviceInfo.getName()); scanner.setRemoteAddress(hostAddress); scanner.setRemotePortNumber(serviceInfo.getPort()); try { saneDevice.open(); scanner.setModel(saneDevice.getModel()); scanner.setVendor(saneDevice.getVendor()); scanner.setType(saneDevice.getType()); scanner.setName(saneDevice.getName()); try { setScannerOptions(saneDevice, scanner); } catch (IOException e) { LOG.warn(e, e); } } catch (IOException e) { LOG.warn(e, e); throw e; } catch (SaneException e) { LOG.warn(e, e); throw e; } finally { try { if (saneDevice.isOpen()) { saneDevice.close(); } } catch (IOException e) { LOG.warn(e, e); } } return scanner; } @Override public final Scanner create(SaneDevice saneDevice, String hostAddress, int portNumber, String description) throws IOException, SaneException { Scanner scanner = new Scanner(); scanner.setServiceName(hostAddress + ":" + portNumber); scanner.setRemoteAddress(hostAddress); scanner.setRemotePortNumber(portNumber); scanner.setDescription(description); try { saneDevice.open(); scanner.setModel(saneDevice.getModel()); scanner.setVendor(saneDevice.getVendor()); scanner.setType(saneDevice.getType()); scanner.setName(saneDevice.getName()); try { List<SaneOption> deviceOptions = saneDevice.listOptions(); for (SaneOption option : deviceOptions) { if (isOptionBlacklisted(option)) { continue; } scanner.addOption(optionInfo(option, 0)); } } catch (IOException e) { LOG.warn(e, e); } } catch (IOException e) { LOG.warn(e, e); throw e; } catch (SaneException e) { LOG.warn(e, e); throw e; } finally { try { if (saneDevice.isOpen()) { saneDevice.close(); } } catch (IOException e) { LOG.warn(e, e); } } return scanner; } @Override public final SanePasswordProvider getPasswordProvider() { return passwordProvider; } @Override public final SaneServiceIdentity getSaneServiceIdentity() { return saneServiceIdentity; } private boolean isOptionBlacklisted(final SaneOption saneOption) { String[] blacklist = new String[] { "monitor-button" }; for (String optionName : blacklist) { if (optionName.equalsIgnoreCase(saneOption.getName())) { return true; } } return false; } private Option optionInfo(SaneOption saneOption, int recursionLevel) throws IOException, SaneException { recursionLevel++; if (saneOption.isActive() && saneOption.isReadable() && saneOption.isWriteable()) { switch (saneOption.getType()) { case BOOLEAN: BooleanOption boolOption = new BooleanOption(); boolOption.setName(saneOption.getName()); boolOption.setDescription(saneOption.getDescription()); boolOption.setValue(saneOption.getBooleanValue()); OptionsOrderValuePair booleanValuePair = new OptionsOrderValuePair(); booleanValuePair.setKey(boolOption.getName()); booleanValuePair.setSaneOptionType(SaneOptionType.BOOLEAN); booleanValuePair.setActive(saneOption.isActive()); boolOption.setOptionsOrderValuePair(booleanValuePair); return boolOption; case INT: IntegerOption intOption = new IntegerOption(); intOption.setName(saneOption.getName()); intOption.setDescription(saneOption.getDescription()); intOption.setConstraintType(saneOption.getConstraintType().getWireValue()); if (saneOption.getConstraintType() == OptionValueConstraintType.RANGE_CONSTRAINT) { RangeConstraint rangeConstraint = saneOption.getRangeConstraints(); Constraints constraints = new Constraints(); constraints.setMinimumInteger(new Integer(rangeConstraint.getMinimumInteger())); constraints.setMaximumInteger(new Integer(rangeConstraint.getMaximumInteger())); constraints.setQuantumInteger(new Integer(rangeConstraint.getQuantumInteger())); intOption.setConstraints(constraints); } else if (saneOption.getConstraintType() == OptionValueConstraintType.VALUE_LIST_CONSTRAINT) { Constraints constraints = new Constraints(); constraints.setIntegerList(saneOption.getIntegerValueListConstraint()); intOption.setConstraints(constraints); } if (saneOption.getValueCount() > 1) { intOption.setValueList(saneOption.getIntegerArrayValue()); } else { intOption.setValue(saneOption.getIntegerValue()); } OptionsOrderValuePair integerValuePair = new OptionsOrderValuePair(); integerValuePair.setKey(intOption.getName()); integerValuePair.setSaneOptionType(SaneOptionType.INTEGER); integerValuePair.setActive(saneOption.isActive()); intOption.setOptionsOrderValuePair(integerValuePair); return intOption; case GROUP: if (recursionLevel <= 1) { // don't let it infinitely recurse. GroupOption groupOption = new GroupOption(); groupOption.setName(saneOption.getName()); groupOption.setDescription(saneOption.getDescription()); for (SaneOption saneOption2 : saneOption.getGroup().getOptions()) { groupOption.addOption(optionInfo(saneOption2, recursionLevel)); } OptionsOrderValuePair groupValuePair = new OptionsOrderValuePair(); groupValuePair.setKey(groupOption.getName()); groupValuePair.setSaneOptionType(SaneOptionType.GROUP); groupValuePair.setActive(saneOption.isActive()); groupOption.setOptionsOrderValuePair(groupValuePair); return groupOption; } break; case BUTTON: if (recursionLevel <= 1) { // don't let it infinitely recurse. ButtonOption buttonOption = new ButtonOption(); buttonOption.setName(saneOption.getName()); buttonOption.setDescription(saneOption.getDescription()); for (SaneOption saneOption2 : saneOption.getGroup().getOptions()) { buttonOption.addOption(optionInfo(saneOption2, recursionLevel)); } OptionsOrderValuePair buttonValuePair = new OptionsOrderValuePair(); buttonValuePair.setKey(buttonOption.getName()); buttonValuePair.setSaneOptionType(SaneOptionType.BUTTON); buttonValuePair.setActive(saneOption.isActive()); buttonOption.setOptionsOrderValuePair(buttonValuePair); return buttonOption; } break; case STRING: StringOption stringOption = new StringOption(); stringOption.setName(saneOption.getName()); stringOption.setDescription(saneOption.getDescription()); stringOption.setValue(saneOption.getStringValue()); stringOption.setConstraintType(saneOption.getConstraintType().getWireValue()); if (saneOption.getConstraintType() == OptionValueConstraintType.STRING_LIST_CONSTRAINT) { Constraints constraints = new Constraints(); constraints.setStringList(saneOption.getStringConstraints()); stringOption.setConstraints(constraints); } OptionsOrderValuePair stringValuePair = new OptionsOrderValuePair(); stringValuePair.setKey(stringOption.getName()); stringValuePair.setSaneOptionType(SaneOptionType.STRING); stringValuePair.setActive(saneOption.isActive()); stringOption.setOptionsOrderValuePair(stringValuePair); return stringOption; case FIXED: FixedOption fixedOption = new FixedOption(); fixedOption.setName(saneOption.getName()); fixedOption.setDescription(saneOption.getDescription()); fixedOption.setValue(saneOption.getFixedValue()); fixedOption.setConstraintType(saneOption.getConstraintType().getWireValue()); if (saneOption.getConstraintType() == OptionValueConstraintType.RANGE_CONSTRAINT) { RangeConstraint rangeConstraint = saneOption.getRangeConstraints(); Constraints constraints = new Constraints(); constraints.setMinimumFixed(new Double(rangeConstraint.getMinimumFixed())); constraints.setMaximumFixed(new Double(rangeConstraint.getMaximumFixed())); constraints.setQuantumFixed(new Double(rangeConstraint.getQuantumFixed())); fixedOption.setConstraints(constraints); } else if (saneOption.getConstraintType() == OptionValueConstraintType.VALUE_LIST_CONSTRAINT) { Constraints constraints = new Constraints(); constraints.setFixedList(saneOption.getFixedValueListConstraint()); fixedOption.setConstraints(constraints); } if (saneOption.getValueCount() > 1) { fixedOption.setValueList(saneOption.getFixedArrayValue()); } else { fixedOption.setValue(saneOption.getFixedValue()); } OptionsOrderValuePair fixedValuePair = new OptionsOrderValuePair(); fixedValuePair.setKey(fixedOption.getName()); fixedValuePair.setSaneOptionType(SaneOptionType.FIXED); fixedValuePair.setActive(saneOption.isActive()); fixedOption.setOptionsOrderValuePair(fixedValuePair); return fixedOption; default: LOG.warn(String.format(Localizer.localize("InvalidOptionTypeMessage"), saneOption.getType())); } } return null; } private void setDeviceBooleanOption(SaneDevice saneDevice, BooleanOption booleanOption) throws IOException { if (!(booleanOption.getOptionsOrderValuePair().isActive())) { return; } try { SaneOption saneOption = saneDevice.getOption(booleanOption.getName()); if (!(saneOption.isActive())) { return; } saneOption.setBooleanValue(booleanOption.getValue()); LOG.debug(booleanOption.getName() + " - " + (booleanOption.getValue() ? "true" : "false")); } catch (Exception e) { LOG.warn(e, e); } } private void setDeviceFixedOption(SaneDevice saneDevice, FixedOption fixedOption) throws IOException { if (!(fixedOption.getOptionsOrderValuePair().isActive())) { return; } try { SaneOption saneOption = saneDevice.getOption(fixedOption.getName()); if (!(saneOption.isActive())) { return; } if (fixedOption.getValueList() != null) { saneOption.setFixedValue(fixedOption.getValueList()); LOG.debug(fixedOption.getName() + " - " + fixedOption.getValueList()); } else { saneOption.setFixedValue(fixedOption.getValue()); LOG.debug(fixedOption.getName() + " - " + fixedOption.getValue()); } } catch (Exception e) { LOG.warn(e, e); } } private void setDeviceIntegerOption(SaneDevice saneDevice, IntegerOption integerOption) throws IOException { if (!(integerOption.getOptionsOrderValuePair().isActive())) { return; } try { SaneOption saneOption = saneDevice.getOption(integerOption.getName()); if (!(saneOption.isActive())) { return; } if (integerOption.getValueList() != null) { saneOption.setIntegerValue(integerOption.getValueList()); LOG.debug(integerOption.getName() + " - " + integerOption.getValueList()); } else { saneOption.setIntegerValue(integerOption.getValue()); LOG.debug(integerOption.getName() + " - " + integerOption.getValue()); } } catch (Exception e) { LOG.warn(e, e); } } private void setDeviceStringOption(SaneDevice saneDevice, StringOption stringOption) throws IOException { if (!(stringOption.getOptionsOrderValuePair().isActive())) { return; } try { SaneOption saneOption = saneDevice.getOption(stringOption.getName()); if (!(saneOption.isActive())) { return; } saneOption.setStringValue(stringOption.getValue()); LOG.debug(stringOption.getName() + " - " + stringOption.getValue()); } catch (Exception e) { LOG.warn(e, e); } } @Override public final void setPasswordProvider(SanePasswordProvider passwordProvider) { this.passwordProvider = passwordProvider; } @Override public final void setSaneServiceIdentity(SaneServiceIdentity identity) { saneServiceIdentity = identity; } @Override public final void setScannerOptions(SaneDevice saneDevice, Scanner scanner) throws IOException, SaneException { scanner.getOptionOrdering().clear(); List<SaneOption> deviceOptions = saneDevice.listOptions(); for (SaneOption option : deviceOptions) { if (isOptionBlacklisted(option)) { continue; } scanner.addOption(optionInfo(option, 0)); } } }