While there are several questions regarding tray selection out there, none of them relate to my problem.
Here's the code I'm using to print:
private static void finalPrint(PDDocument pdoc, boolean pbStationary)
throws BigBangJewelException
{
PrintService lrefSvc;
PrinterJob lrefPJob;
Media lrefMedia;
HashPrintRequestAttributeSet lobjSet;
lrefSvc = getPrinter();
lrefPJob = PrinterJob.getPrinterJob();
try
{
lrefPJob.setPrintService(lrefSvc);
lrefPJob.setPageable(pdoc);
lrefMedia = null;
if ( pbStationary )
lrefMedia = getTray(lrefSvc);
if ( lrefMedia != null )
{
lobjSet = new HashPrintRequestAttributeSet();
lobjSet.add(lrefMedia);
lrefPJob.print(lobjSet);
}
else
lrefPJob.print();
}
catch (Throwable e)
{
throw new BigBangJewelException(e.getMessage(), e);
}
}
private static PrintService getPrinter()
throws BigBangJewelException
{
String lstrPrinter;
PrintService[] larrServices;
int i;
try
{
lstrPrinter = (String)Engine.getUserData().get("Printer");
larrServices = PrinterJob.lookupPrintServices();
for ( i = 0; i < larrServices.length; i++ )
{
if (larrServices[i].getName().indexOf(lstrPrinter) != -1)
return larrServices[i];
}
}
catch (Throwable e)
{
throw new BigBangJewelException(e.getMessage(), e);
}
throw new BigBangJewelException("Impressora definida (" + lstrPrinter + ") não encontrada.");
}
private static Media getTray(PrintService prefSvc)
{
Media[] larrMedia;
String lstrAux;
int i;
larrMedia = (Media[])prefSvc.getSupportedAttributeValues(Media.class, null, null);
if ( larrMedia == null )
return null;
for ( i = 0; i < larrMedia.length; i++ )
{
lstrAux = larrMedia[i].toString().toLowerCase();
if (lstrAux.contains("tray") && lstrAux.contains("3"))
{
return larrMedia[i];
}
}
return null;
}
The baffling thing is, this code used to work. The machine had a bunch of Xerox printers defined, and the code would correctly identify the wanted printer, and the wanted tray, and everything worked wonderfully.
Then, one day, overnight, it stopped working. It still finds the right printer, but now, it always prints to tray 1.
The only thing that changed was that an extra HP printer was added to the machine.
I can confirm that the code is finding the tray and sending it to the print job, but it's getting ignored.
Again, there are many questions out there regarding this issue, but my problem is that the code worked well for four years, then stopped working for no apparent reason.
Can anyone shed any light on this subject?
Edit: New information: Uninstalling the HP printer made the Xerox printers work right again. Why would installing one driver affect Java's ability to communicate with a different driver?
Edit 2: Further information: If we install the HP global printer driver instead of the specific printer driver, everything works correctly. I'll leave the question unanswered to see if anyone can come up with a good explanation before the bounty expires, then I'm going to put this edit in an answer and accept it.
If I got you question correctly, you the content of lobjSet is unchanged, yet it the print result is different, with the new driver installed.
I checked the code for PnterJob.print(PrintRequestAttributeSet) and was surprised that it completely ignores the attribute set.
So I looked at where the PrintService is coming from, the code is a little lengthy, but I guess it interacts somehow with the installed printer drivers to create appropriate instances. So the new driver changes this, returning a different PrintService. There is no way I can tell in what exact way this thing changes, but if you can recreate both scenarios (and it seems you can), it should be fairly easy to use a debugger to find the exact place where the behavior of the code changes.
The solution to our particular situation was to change the printer drivers for the HP printer.
Originally, we had installed the specific driver for the printer in question, which caused this behavior. Installing HP's global driver instead made the problem go away.
Unfortunately, we do not know why. Jens Schauder's answer contains clues as to how to go about finding out.
Related
I have written a function which takes in a BufferedImage and compares it to a pre-existing image in my hard drive checking if they are same or not.
public boolean checkIfSimilarImages(BufferedImage imgA, File B) {
DataBuffer imgAdata = imgA.getData().getDataBuffer();
int sizeA = imgAdata.getSize();
BufferedImage imgB = null;
try {
imgB = ImageIO.read(B);
} catch (IOException ex) {
Logger.getLogger(SupportClass.class.getName()).log(Level.SEVERE, null, ex);
}
DataBuffer imgBdata = imgB.getData().getDataBuffer();
int sizeB = imgBdata.getSize();
if(sizeA == sizeB) {
for(int i = 0; i < sizeA; i++) {
if (imgAdata.getElem(i) != imgBdata.getElem(i)) {
return false;
}
}
}
return true;
}
This throws IOException "Cant read input file". Idk why this is happening. I am calling the function like this...
while(support.checkIfSimilarImages(currentDisplay, new File(pathToOriginalImage)) == false) {
System.out.println("Executing while-loop!");
bot.delay(3000);
currentDisplay = bot.createScreenCapture(captureArea);
}
where,
String pathToOriginalImage = "C:\\Users\\Chandrachur\\Desktop\\Home.jpg";
I can see that the path is valid. But as I am testing it for File.exists() or File.canRead() or File.absoluteFile().exists() inside the checkIfSimilarImages function and everything is returning false.
I have researched my question here and tried out these suggestions:
It is not only for this location, I have tried a variety of other locations but in vain. Also it is not a problem where I have hidden file extensions and the actual file might be Home.jpg.jpg .
The only thing that might be is that permissions might be different. I dont really know how to verify this, but there is no reason it should have some permission which is not readable by java. It is just another normal jpg file.
Can it be because I am passing the file object reference into a function so in this process somehow the reference is getting modified or something. I just dont know. I am running out of possibilities to test for...
The whole stack trace is as follows:
javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1301)
at battlesbot.SupportClass.checkIfSimilarImages(SupportClass.java:77)
at battlesbot.AutomatedActions.reachHomeScreen(AutomatedActions.java:72)
at battlesbot.BattlesBot.main(BattlesBot.java:22)
Exception in thread "main" java.lang.NullPointerException
at battlesbot.SupportClass.checkIfSimilarImages(SupportClass.java:81)
at battlesbot.AutomatedActions.reachHomeScreen(AutomatedActions.java:72)
at battlesbot.BattlesBot.main(BattlesBot.java:22)
C:\Users\Chandrachur\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 11 seconds)
I am on Windows 10, IDE is NetBeans.
UPDATE:
Huge thanks to #k5_ . He told me to paste this in path and it worked.
"C:/Users/Chandrachur/Desktop/Home.jpg";
It seems some invisible characters were in the path. But I still don't understand what that means.
Usually this kind of problem lies with access problem or typos in the filename.
In this case there were some invisible unicode characters x202A in the filename. The windows dialog box, the file path was copied from, uses them for direction of writing (left to right).
One way of displaying them would be this loop, it has 4 invisible characters at the start of the String. You would also see them in a debugger.
String x = "C:\\Users\\Chandrachur\\Desktop\\Home.jpg";
for(char c : x.toCharArray()) {
System.out.println( c + " " + (int) c);
}
I'm using grph library for a university project (www.i3s.unice.fr/~hogie/grph/)
but i have a problem only on Linux with that library, when i create a new Graph object, i receive the following exception:
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.elendev.wesproject.graph.GraphFactory.main(GraphFactory.java:19)
Caused by: java.lang.NullPointerException
at toools.os.OperatingSystem.getLocalOS(OperatingSystem.java:47)
at grph.Grph.setCompilationDirectory(Grph.java:353)
at grph.Grph.<clinit>(Grph.java:246)
... 1 more
I tried to call directly getLocalOS function, with:
System.out.println(toools.os.OperatingSystem.getLocalOS());
and i receive the same exception. I cannot find information about that library, and the project launched on a macbook works perfectly.
The operating system i'm currently using is gentoo linux 32bit.
And the jdk version is: 1.7.0_65
Any idea of what could be the problem?
Not sure whether this can count as an answer, but it could at least help to solve the issue:
The exception comes from the toools.os.OperatingSystem.getLocalOS method. Although the .JAR file from the website that you mentioned has a whopping 39 megabytes, the source code of this class is not contained in it.
There seems to be no information available about this class at all. Neither Google nor Maven finds anything related to the toools package. One has to assume that it is an abandoned utility class that passed away a long time ago.
However, the method in question can be disassembled to the following code:
public static OperatingSystem getLocalOS()
{
if (localOS == null)
{
if (new RegularFile("/etc/passwd").exists())
{
if (new Directory("/proc").exists())
{
if (new RegularFile("/etc/fedora-release").exists()) {
localOS = new FedoraLinux();
} else if (ExternalProgram.commandIsAvailable("ubuntu-bug")) {
localOS = new UbuntuLinux();
} else {
localOS = new Linux();
}
}
else if (new Directory("/Applications").exists()) {
localOS = new MacOSX();
} else {
localOS = new Unix();
}
}
else if (System.getProperty("os.name").startsWith("Windows")) {
localOS = new Windows();
} else {
localOS = new OperatingSystem();
}
localOS.name = System.getProperty("os.name");
localOS.version = System.getProperty("os.version");
}
return localOS;
}
From this, you can possibly derive the conditions that must be met in order to properly detect your OS as a linux OS. Particularly, when there is a file named /etc/passwd, and a directory /proc, this should be sufficient to identify the OS as a Linux. You may want to give it a try...
The filesystem AirportHDD is mounted (AFP) from the beginning and the file exists when I start this little program.
I tried to figure out the whole day why the following is not working, but couldnt find any solution:
public static void main(String[] arguments)
{
while(1==1)
{
File f=new File(
"/Volumes/AirportHDD/test/lock.csv");
System.out.println(f.exists());
AmySystem.sleep(100);
}
}
the output is:
true, true, ...
as soon as I remove the file from a different computer (AirportHDD is a mounted harddisk over network) then the output keeps saying:
true, true, ...
when I open the finder and goto this directory the output changes to: false, false, ...
when the file is added again (via another pc) the output is still:
false, false, ...
but if you open the finder again and click on the directory and finder shows the existing file, the output changes suddenly to: false, true, true, true, ...
NOTE:
also all other file operations like opening for read are failing as long as java 'thinks' the file is not there
if the program itself is creating and deleting the files then problem is not occurring
just found out while testing that with samba sharing everything is ok, but with AFP it just wont work
is there a way to tell java to do the same thing as finder, like a refresh, or do not try to cache, whatever?
I think you might be looking for the WatchService. Oracle was also kind enough to provide a tutorial.
Because the longevity of these links aren't guaranteed, I'll edit in an example code in a couple of minutes. I just wanted to let you know I think I found something in case you want to start looking at it for yourself.
UPDATE
Following the linked tutorial, I came up with code like this. I'm not sure it'll work (don't have time to test it), but it might be enough to get you started. The WatchService also has a take() method that will wait for events, which means you could potentially assume the file's existence (or lack thereof) based on the last output you gave. That will really depend on what this program will be interacting with.
If this works, good. If not, maybe we can figure out how to fix it based on whatever errors you're getting. Or maybe someone else will come along and give a better version of this code (or better option altogether) if they're more acquainted with this than I am.
public static void main(String[] arguments) {
Path path = Paths.get("/Volumes/AirportHDD/test/lock.csv");
WatchService watcher = FileSystems.getDefault().newWatchService();
WatchKey key = null;
try {
key = path.register(watcher,
ENTRY_CREATE,
ENTRY_DELETE);
} catch (IOException x) {
System.err.println(x);
}
while(true) {//I tend to favor this infinite loop, but that's just preference.
key = watcher.poll();
if(key != null) {
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == OVERFLOW || kind == ENTRY_DELETE) {
System.out.println(false);
}
else if (kind == ENTRY_CREATE) {
System.out.println(true);
}
}//for(all events)
}//if(file event occured)
else {
File f=new File(path);
System.out.println(f.exists());
}//else(no file event occured)
AmySystem.sleep(100);
}//while(true)
}//main() method
Here is a JUnit test that shows the problem
The problem still happens using Samba on OSX Mavericks. A possible reason
is explaned by the statement in:
http://appleinsider.com/articles/13/06/11/apple-shifts-from-afp-file-sharing-to-smb2-in-os-x-109-mavericks
It aggressively caches file and folder properties and uses opportunistic locking to enable better caching of data.
Please find below a checkFile that will actually attempt to read a few bytes and forcing a true file access to avoid the caching misbehaviour ...
JUnit test:
/**
* test file exists function on Network drive
* #throws Exception
*/
#Test
public void testFileExistsOnNetworkDrive() throws Exception {
String testFileName="/Volumes/bitplan/tmp/testFileExists.txt";
File testFile=new File(testFileName);
testFile.delete();
for (int i=0;i<10;i++) {
Thread.sleep(50);
System.out.println(""+i+":"+OCRJob.checkExists(testFile));
switch (i) {
case 3:
// FileUtils.writeStringToFile(testFile, "here we go");
Runtime.getRuntime().exec("/usr/bin/ssh phobos /usr/bin/touch "+testFileName);
break;
}
}
}
checkExists source code:
/**
* check if the given file exists
* #param f
* #return true if file exists
*/
public static boolean checkExists(File f) {
try {
byte[] buffer = new byte[4];
InputStream is = new FileInputStream(f);
if (is.read(buffer) != buffer.length) {
// do something
}
is.close();
return true;
} catch (java.io.IOException fnfe) {
}
return false;
}
The problem is the network file system AFP. With the use of SAMBA everything works like expected.
Maybe the OS returns the wrong file info in OSX with the use of AFP in these scenarios.
I am attempting to do what I would have guessed would be pretty simple, but as it turns out is not. I have an ACR122 NFC reader and a bunch of Mifare Classic and Mifare Ultralight tags, and all I want to do is read and write a mime-type and a short text string to each card from a Java application. Here's what I've got working so far:
I can connect to my reader and listen for tags
I can detect which type of tag is on the reader
On the Mifare Classic tags I can loop through all of the data on the tag (after programming the tag from my phone) and build an ascii string, but most of the data is "junk" data
I can determine whether or not there is an Application directory on the tag.
Here's my code for doing that:
Main:
public static void main(String[] args){
TerminalFactory factory = TerminalFactory.getDefault();
List<CardTerminal> terminals;
try{
TerminalHandler handler = new TerminalHandler();
terminals = factory.terminals().list();
CardTerminal cardTerminal = terminals.get(0);
AcsTerminal terminal = new AcsTerminal();
terminal.setCardTerminal(cardTerminal);
handler.addTerminal(terminal);
NfcAdapter adapter = new NfcAdapter(handler.getAvailableTerminal(), TerminalMode.INITIATOR);
adapter.registerTagListener(new CustomNDEFListener());
adapter.startListening();
System.in.read();
adapter.stopListening();
}
catch(IOException e){
}
catch(CardException e){
System.out.println("CardException: " + e.getMessage());
}
}
CustomNDEFListener:
public class CustomNDEFListener extends AbstractCardTool
{
#Override
public void doWithReaderWriter(MfClassicReaderWriter readerWriter)
throws IOException{
NdefMessageDecoder decoder = NdefContext.getNdefMessageDecoder();
MadKeyConfig config = MfConstants.NDEF_KEY_CONFIG;
if(readerWriter.hasApplicationDirectory()){
System.out.println("Application Directory Found!");
ApplicationDirectory directory = readerWriter.getApplicationDirectory();
}
else{
System.out.println("No Application Directory Found, creating one.");
readerWriter.createApplicationDirectory(config);
}
}
}
From here, I seem to be at a loss as for how to actually create and interact with an application. Once I can create the application and write Record objects to it, I should be able to write the data I need using the TextMimeRecord type, I just don't know how to get there. Any thoughts?
::Addendum::
Apparently there is no nfc-tools tag, and there probably should be. Would someone with enough rep be kind enough to create one and retag my question to include it?
::Second Addendum::
Also, I am willing to ditch NFC-Tools if someone can point me in the direction of a library that works for what I need, is well documented, and will run in a Windows environment.
Did you checked this library ? It is well written, how ever has poor documentation. Actually no more than JavaDoc.
I have a file that works just fine if I use the command lp filename.
The file is an ESC/P file for a receipt impact printer. That has linux native CUPS drivers and all that works.
Im trying to use the javax.print API so that I can have a finer grained control over the printing and hopefully keep it cross-platform compatible, though Linux is the target platform.
I've tried every DocFlavor combination known to man and every type of data type (InputStream, byte[], Reader etc.)
It either just ignores the print() command all together or just flips out a blank sheet of paper. Running lp filename prints it perfect, so how do I get javax.print to just do the functional equivalent of lp filename?
I'm not set on using javax.print I can use other "things" and might start investigating cups4J but it seems it would limit me to Linux/*nix only, which is OK for now but would rather have a cross platform solution.
I could just issue the lp system command on the file but, I need finer grained control. These aren't receipts we're printing, they are tickets and the tickets range from $5.00 to to thousands of dollars. Currently if we detect a printing issue, we void the transaction and if anything printed, its invalid, we don't take reprints lightly and most of the time charge to print a new copy if the customer looses his copy. Oh the reason for doing this is we're changing the POS system from Windows to Linux and the printers from direct access over serial ports to CUPS managed over USB. Here's my code that doesn't work. Any help is appreciated.
try {
// Find the default service
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
// Create the print job
DocPrintJob job = service.createPrintJob();
InputStream in = new FileInputStream("/home/bart/real.escp");
Doc docNew = new SimpleDoc(in,flavor,null);
// Monitor print job events; for the implementation of PrintJobWatcher,
// see Determining When a Print Job Has Finished
PrintJobWatcher pjDone = new PrintJobWatcher(job);
// Print it
job.print(docNew, null);
// Wait for the print job to be done
pjDone.waitForDone();
// It is now safe to close the input stream
in.close();
} catch (PrintException e) {
} catch (IOException e) {
}
I am fine with cups4j.
First get your printer.
try {
CupsClient client = new CupsClient("addressOfTheCupsServer", 631);
List<CupsPrinter> printers = client.getPrinters();
if (printers.size() == 0) {
throw new RuntimeException("Cant list Printer");
}
for (CupsPrinter cupsPrinter : printers) {
if (cupsPrinter.getName().equals("NameOfPrinter")) {
selectedPrinter = cupsPrinter;
}
}
}catch (Exception ignored){
ignored.printStackTrace();
}
}
Then create a printjob and send it to the printer
PrintJob printJob = new PrintJob.Builder(inputStream).jobName("Jobname").build();
PrintRequestResult result = selectedPrinter.print(printJob);