Hello I am using Apache Commons FTP Client and I want to show the FTP Commands that the FTP Client uses so like when I use changeWorkingDirectory it should show me the FTP Command that it used like: CODEOFCOMMAND CHD .....
or when I upload a File it should show me: CODEOFCOMMAND PUT ....
Is there any possibility to do this ?
You can find it in the Apache Commons Net FAQ :
Q: How do I debug FTP applications?
A: You can add a protocol command listener; for example:
ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
- Its one of the most important aspect of Object Oriented Programming to hide the implementation from the implementer (In this case the Programmer).
- And as you are using Apache's commons library for the ftp, you are permitted to use the functionality, were as the implementation is hidden.
Here for the people that also need it:
First do:
redirectSystemStreams();
ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
but because I am using a JTextArea in a GUI and I need the output there I hat to redirect the output I did it by creating these Methods (Replace txtLog with your TextArea):
private void updateTextArea(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
txtLog.append(text);
}
});
}
private void redirectSystemStreams() {
OutputStream out = new OutputStream() {
#Override
public void write(int b) throws IOException {
updateTextArea(String.valueOf((char) b));
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextArea(new String(b, off, len));
}
#Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
}
Related
I am wondering if BufferedOutputStream offers any way to provide the count of bytes it has written. I am porting code from C# to Java. The code uses Stream.Position to obtain the count of written bytes.
Could anyone shed some light on this? This is not a huge deal because I can easily add a few lines of code to track the count. It would be nice if BufferedOutputStream already has the function.
For text there is a LineNumberReader, but no counting the progress of an OutputStream. You can add that with a wrapper class, a FilterOutputStream.
public class CountingOutputStream extends FilterOutputStream {
private long count;
private int bufferCount;
public CountingOutputStream(OutputStream out) {
super(out);
}
public long written() {
return count;
}
public long willBeWritten() {
return count + bufferCount;
}
#Override
public void flush() {
count += bufferCount;
bufferCount = 0;
super.flush();
}
public void write​(int b)
throws IOException {
++bufferCount;
super.write(b);
}
#Override
public void write(byte[] b, int off, int len)
throws IOException {
bufferCount += len;
super.write(b, off, len);
}
#Override
public void write(byte[] b, int off, int len)
throws IOException {
bufferCount += len;
super.write(b, off, len);
}
}
One could also think using a MemoryMappedByteBuffer (a memory mapped file) for a better speed/memory behavior. Created from a RandomAccessFile or FileChannel.
If all is too circumstantial, use the Files class which has many utilities, like copy. It uses Path - a generalisation of (disk I/O) File -, for files from the internet, files inside zip files, class path resources and so on.
I have the following code:
private void replaceStdIo(SocketChannel socketChannel) throws IOException {
socketChannel.configureBlocking(blockingMode);
InputStream in = new RedirectorInputStream();
PrintStream out = new PrintStream(new RedirectorOutputStream(), false, charsetEncoding);
System.setIn(in);
System.setErr(out);
System.setOut(out);
}
It is part of a bigger Telnet Class which I use to get Info out of my Server. Current problem is that I have a Logger. I want to output everything of the logger into the Telnet Console, but only System.out.print works.
System.err should also work, but for some reason it is not?
This is the Console output in the IDE:
14:06:42:0723.: From ConsoleIn.java -> Found the Commandinput FINEST in
setDebugLevel(FINEST)
14:06:42:0725.: From Debug.java -> Set debugLevel to FINEST
But this does not get printed out in the Telnet Console on the PC, only everything with System.out. Does anyone have any idea why?
I fixed my issue by creating a new Handler. As it turns out, the old consoleHandler blocked the interception of System.err . By creating my own, new Handler and taking out consoleHandler it ended up working.
The new, working Code:
telnetHandler = new Handler() {
#Override
public void publish(LogRecord record) {
System.err.println(record.getMessage());
}
#Override
public void flush() {
System.err.flush();
}
#Override
public void close() throws SecurityException {
System.err.close();
}
};
I would like to stream out logs via api endpoint /logs for dropwizard.
It is harder than what I thought. Dropwizard would read in the configuration via config.yml and keep those information as private. And I have no idea where would I be able to find the logger that logs everything?
Am I missing something?
Is there another way to do this?
This is a streaming example, you can also read up on this here:
calling flush() on Jersey StreamingOutput has no effect
And
Example of using StreamingOutput as Response entity in Jersey
The code:
public class StreamingTest extends io.dropwizard.Application<Configuration> {
#Override
public void run(Configuration configuration, Environment environment) throws Exception {
environment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0);
environment.jersey().register(Streamer.class);
}
public static void main(String[] args) throws Exception {
new StreamingTest().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
}
#Path("/log")
public static class Streamer {
#GET
#Produces("application/octet-stream")
public Response test() {
return Response.ok(new StreamingOutput() {
#Override
public void write(OutputStream output) throws IOException, WebApplicationException {
while (true) {
output.write("Test \n".getBytes());
output.flush();
try {
Thread.sleep(1000); // simulate waiting for stream
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).build();
}
}
}
Which does what you want.
A few points The line evironment.jersey().property(ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER, 0); is important. It tells the server not to buffer the output before returning it to the caller.
Additionally, you need to explicitly flush out the output by calling output.flush();
However, this seems to be the wrong way to ship logs. Have you ever looked into i.e. logstash? Or network based appenders that stream the logs directly to where you need them to be?
Hope that helps,
--artur
This is a followup to anonymous file streams reusing descriptors
As per my previous question, I can't depend on code like this (happens to work in JDK8, for now):
RandomAccessFile r = new RandomAccessFile(...);
FileInputStream f_1 = new FileInputStream(r.getFD());
// some io, not shown
f_1 = null;
f_2 = new FileInputStream(r.getFD());
// some io, not shown
f_2 = null;
f_3 = new FileInputStream(r.getFD());
// some io, not shown
f_3 = null;
However, to prevent accidental errors and as a form of self-documentation, I would like to invalidate each file stream after I'm done using it - without closing the underlying file descriptor.
Each FileInputStream is meant to be independent, with positioning controlled by the RandomAccessFile. I share the same FileDescriptor to prevent any race conditions arising from opening the same path multiple times. When I'm done with one FileInputStream, I want to invalidate it so as to make it impossible to accidentally read from it while using the second FileInputStream (which would cause the second FileInputStream to skip data).
How can I do this?
notes:
the libraries I use require compatibiity with java.io.*
if you suggest a library (I prefer builtin java semantics if at all possible), it must be commonly available (packaged) for linux (the main target) and usable on windows (experimental target)
but, windows support isn't a absolutely required
Edit: in response to a comment, here is my workflow:
RandomAccessFile r = new RandomAccessFile(String path, "r");
int header_read;
int header_remaining = 4; // header length, initially
byte[] ba = new byte[header_remaining];
ByteBuffer bb = new ByteBuffer.allocate(header_remaining);
while ((header_read = r.read(ba, 0, header_remaining) > 0) {
header_remaining -= header_read;
bb.put(ba, 0, header_read);
}
byte[] header = bb.array();
// process header, not shown
// the RandomAccessFile above reads only a small amount, so buffering isn't required
r.seek(0);
FileInputStream f_1 = new FileInputStream(r.getFD());
Library1Result result1 = library1.Main.entry_point(f_1)
// process result1, not shown
// Library1 reads the InputStream in large chunks, so buffering isn't required
// invalidate f_1 (this question)
r.seek(0)
int read;
while ((read = r.read(byte[4096] buffer)) > 0 && library1.continue()) {
library2.process(buffer, read);
}
// the RandomAccessFile above is read in large chunks, so buffering isn't required
// in a previous edit the RandomAccessFile was used to create a FileInputStream. Obviously that's not required, so ignore
r.seek(0)
Reader r_1 = new BufferedReader(new InputStreamReader(new FileInputStream(r.getFD())));
Library3Result result3 = library3.Main.entry_point(r_2)
// process result3, not shown
// I'm not sure how Library3 uses the reader, so I'm providing buffering
// invalidate r_1 (this question) - bonus: frees the buffer
r.seek(0);
FileInputStream f_2 = new FileInputStream(r.getFD());
Library1Result result1 = library1.Main.entry_point(f_2)
// process result1 (reassigned), not shown
// Yes, I actually have to call 'library1.Main.entry_point' *again* - same comments apply as from before
// invalidate f_2 (this question)
//
// I've been told to be careful when opening multiple streams from the same
// descriptor if one is buffered. This is very vague. I assume because I only
// ever use any stream once and exclusively, this code is safe.
//
A pure Java solution might be to create a forwarding decorator that checks on each method call whether the stream is validated or not. For InputStream this decorator may look like this:
public final class CheckedInputStream extends InputStream {
final InputStream delegate;
boolean validated;
public CheckedInputStream(InputStream stream) throws FileNotFoundException {
delegate = stream;
validated = true;
}
public void invalidate() {
validated = false;
}
void checkValidated() {
if (!validated) {
throw new IllegalStateException("Stream is invalidated.");
}
}
#Override
public int read() throws IOException {
checkValidated();
return delegate.read();
}
#Override
public int read(byte b[]) throws IOException {
checkValidated();
return read(b, 0, b.length);
}
#Override
public int read(byte b[], int off, int len) throws IOException {
checkValidated();
return delegate.read(b, off, len);
}
#Override
public long skip(long n) throws IOException {
checkValidated();
return delegate.skip(n);
}
#Override
public int available() throws IOException {
checkValidated();
return delegate.available();
}
#Override
public void close() throws IOException {
checkValidated();
delegate.close();
}
#Override
public synchronized void mark(int readlimit) {
checkValidated();
delegate.mark(readlimit);
}
#Override
public synchronized void reset() throws IOException {
checkValidated();
delegate.reset();
}
#Override
public boolean markSupported() {
checkValidated();
return delegate.markSupported();
}
}
You can use it like:
CheckedInputStream f_1 = new CheckedInputStream(new FileInputStream(r.getFD()));
// some io, not shown
f_1.invalidate();
f_1.read(); // throws IllegalStateException
Under unix you could generally avoid such problems by dup'ing a file descriptor.
Since java does not not offer such a feature one option would be a native library which exposes that. jnr-posix does that for example. On the other hand jnr depends on a lot more jdk implementation properties than your original question.
I have a prolog file (Expert System) that I consult from Java using Jpl libraries (org.jpl7.*) and I have an UI where I want to show the output of prolog's queries.
This is my Custom Output Stream that should redirect every console content into my interface (jTextAreaOUTPUT is the place where i redirect the content)
public class CustomOutputStream extends OutputStream {
private JTextArea jTextAreaOUTPUT;
public CustomOutputStream(JTextArea textArea) {
jTextAreaOUTPUT = textArea;
}
#Override
public void write(int b) throws IOException {
// redirects data to the text area
jTextAreaOUTPUT.append(String.valueOf((char)b));
// scrolls the text area to the end of data
jTextAreaOUTPUT.setCaretPosition(jTextAreaOUTPUT.getDocument().getLength());
}
}
This are some lines I have in my Interface Class: this calls the Custom Output Stream methond:
PrintStream printStream = new PrintStream(new CustomOutputStream(jTextAreaOUTPUT), true, "UTF-8");
// keeps reference of standard output stream
PrintStream standardOut = System.out;
System.setOut(printStream);
System.setErr(printStream);
For some strange reasons it doesn't work whith this prolog file (I tried with other and It works): UI freezes and content keeps showing in java console (eclipse).
The Expert System file works with write instruction in Prolog (e.g. write('Lorem Ipsum') )
Why standardOut in never used ? Is it ok declared this way?
Is there a way to force redirect for all the text that should be written in eclipse console?
I also tried to use " write Stream " method in prolog, but (only for this prolog file, maybe due to recursion) UI freezes even though outpus is written on a txt file.
You might need to override the other write functions in outputstream write(byte[] b), write(byte[] b, int off, int len) if the writer doesn't write one character at a time
To override the other write functions of OutputStream just provide similar code to the single character function you already wrote:
public class CustomOutputStream extends OutputStream {
private JTextArea jTextAreaOUTPUT;
public CustomOutputStream(JTextArea textArea) {
jTextAreaOUTPUT = textArea;
}
#Override
public void write(int b) throws IOException {
// redirects data to the text area
jTextAreaOUTPUT.append(String.valueOf((char) b));
// scrolls the text area to the end of data
jTextAreaOUTPUT.setCaretPosition(jTextAreaOUTPUT.getDocument().getLength());
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
// redirects data to the text area
jTextAreaOUTPUT.append(new String(b, off, len));
// scrolls the text area to the end of data
jTextAreaOUTPUT.setCaretPosition(jTextAreaOUTPUT.getDocument().getLength());
}
#Override
public void write(byte[] b) throws IOException {
write(b,0,b.length);
}
}