I use the apache tailer for read end of line, if there is adding new line inside file log the program will print just end of line, it's like "tail -f" from linux, i have the output tail to send with String.
Can i get the output tail and save to string for my code below ?
public class LogTailTest {
/**
* TailerListener implementation.
*/
static public class ShowLinesListener extends TailerListenerAdapter {
#Override
public void handle(String line) {
System.out.println(line);
}
}
public static void main(String args[]) {
TailerListener listener = new ShowLinesListener();
File file = new File("/home/ubuntu/Desktop/test.log");
Tailer tailer = new Tailer(file, listener, 10000, true, true);
tailer.run();
try {
Thread.sleep(1000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
tailer.stop();
}
}
When i run above program it's direct to output console
You define what to do every time a new line is tailed by your program. This behaviour is defined in the method handle of class ShowLinesListener:
#Override
public void handle(String line) {
System.out.println(line);
}
All you have to do is change this line
System.out.println(line);
to do what you want with it. As you are already using commons-io library (that's where the TailerListener and TailerListenerAdapter classes are defined), you can use FileUtils.writeStringtoFile method to write the contents of the line just tailed to another file.
Your class would look like this:
public class LogTailTest {
/**
* TailerListener implementation.
*/
static public class ShowLinesListener extends TailerListenerAdapter {
#Override
public void handle(String line) {
FileUtils.writeStringtoFile(new File("/path/to/file"),
line,
Charset.defaultCharset())
}
}
Related
i was trying to build a command line tool alike in java, for example, if i write down in console "dir c:/....", it will activate my Dir class and will get the "c:/...." path as a parameter to the Dir class, and doing so with hashmap.
i dont know how to pass parameters through the commandline and hashmap,
is it even possible?
every command has it's own class, which implements the main "Command" interface, with a doCommand() function.
after running the start() function in the CLI class, it should take commands and do the requested command.
Command Interface:
public interface Command {
public void doCommand();
}
my CLI class:
public class CLI {
BufferedReader in;
PrintWriter out;
HashMap<String, Command> hashMap;
Controller controller;
public CLI(Controller controller, BufferedReader in, PrintWriter out,
HashMap<String, Command> hashMap) {
this.in = in;
this.out = out;
this.hashMap = hashMap;
}
public void start() {
new Thread(new Runnable() {
#Override
public void run() {
try {
out.println("Enter a command please:");
String string = in.readLine();
while (!string.equals("exit")) {
Command command = hashMap.get(string);
command.doCommand();
string = in.readLine();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
}
lets take for example my DirCommmand, as i said before, which should recognize the "dir" string through my hashMap configuration, and should pass the next word as a string parameter for the path
public class DirCommand implements Command {
#Override
public void doCommand() {
System.out.println("doing dir command...");
}
}
and my hashmap configuration:
hashMap.put("dir", new DirCommand());
which sets in a diffrent class the hashMap configuration and pass it to the CLI class's hashMap object at the start of the project.
i would love for some help because i have no idea how to do so.
First of all, in order to pass the parameters to doCommand, what I would do is use a variable param list, like:
public interface Command {
public void doCommand(String... params);
}
Second, I would split the input string on spaces as:
String[] result = command.split(" ");
Finally, the command would be the result[0] and the rest you would pass to the doCommand method.
I'm playing around with my new toy, JCC 2.21, and am having trouble implementing callbacks in a python script. I have wrapped the following simple Java thread API and am calling it from python 2.7 (CPython), but when I call the JccTest.addJccTestListener(JccTestListener) method, the JVM reports a null argument.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class JccTest implements Runnable {
private final Object listenersLock = new Object();
private final List<JccTestListener> listeners = new ArrayList<JccTestListener>();
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicBoolean finished = new AtomicBoolean(false);
public void start() {
if (running.compareAndSet(false, true)) {
new Thread(this).start();
}
}
public void stop() {
finished.set(true);
}
public void addJccTestListener(JccTestListener l) {
if (l == null) {
throw new IllegalArgumentException("argument must be non-null");
}
synchronized (listenersLock) {
listeners.add(l);
}
}
public void removeJccTestListener(JccTestListener l) {
synchronized (listenersLock) {
listeners.remove(l);
}
}
#Override
public void run() {
System.out.println("Start");
while (!finished.get()) {
System.out.println("Notifiying listeners");
synchronized (listenersLock) {
for (JccTestListener l : listeners) {
System.out.println("Notifiying " + String.valueOf(l));
l.message("I'm giving you a message!");
}
}
System.out.println("Sleeping");
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
continue;
}
}
running.set(false);
System.out.println("Stop");
}
public static void main(String[] args) throws InterruptedException {
JccTest test = new JccTest();
test.addJccTestListener(new JccTestListener() {
#Override
public void message(String msg) {
// called from another thread
System.out.println(msg);
}
});
test.start();
Thread.sleep(10000);
test.stop();
}
}
public interface JccTestListener {
public void message(String msg);
}
Generated wrapper with:
python -m jcc --jar jcc-test.jar --python jcc_test --build --install
And then executed this script (equivalent to the main method of JccTest):
import jcc_test
import time, sys
jcc_test.initVM(jcc_test.CLASSPATH)
test = jcc_test.JccTest()
class MyListener(jcc_test.JccTestListener):
def __init__(self):
pass
def message(self, msg):
print msg
test.addJccTestListener(MyListener())
test.start()
time.sleep(10)
test.stop()
sys.exit(0)
Which results in:
"python.exe" jcc_test_test.py
Traceback (most recent call last):
File "jcc_test_test.py", line 16, in <module>
test.addJccTestListener(MyListener())
jcc_test.JavaError: java.lang.IllegalArgumentException: argument must be non-null
Java stacktrace:
java.lang.IllegalArgumentException: argument must be non-null
at com.example.jcc.JccTest.addJccTestListener(JccTest.java:32)
Besides the null listener instance, is doing something like this even possible with CPython? I've read that in its implementation only one thread may execute the python script at a time, which might (?) be a problem for me. Doing something like this with Jython was trivial.
I'm rather new to python so please be gentle.
Figured it out. You need to define a pythonic extension for a java class to make this work. The detailed procedure is described in JCC documentation (Writing Java class extensions in Python) and is rather simple.
First, code a class that implements your interface and add some magic markers that are recognized by JCC and affect what the wrapper generator will generate.
public class JccTestListenerImpl implements JccTestListener {
// jcc specific
private long pythonObject;
public JccTestListenerImpl() {}
#Override
public void message(String msg) {
messageImpl(msg);
}
// jcc specific
public void pythonExtension(long pythonObject) {
this.pythonObject = pythonObject;
}
// jcc specific
public long pythonExtension() {
return this.pythonObject;
}
// jcc specific
#Override
public void finalize() throws Throwable {
pythonDecRef();
}
// jcc specific
public native void pythonDecRef();
public native void messageImpl(String msg);
}
The markers are denoted by my comments and must appear verbatim in any class that is to be extended in python. My implementation delegates the interface method to a native implementation method, which will be extended in python.
Then generate the wrapper as usual:
python -m jcc --jar jcc-test.jar --python jcc_test --build --install
And finally make a python extension for the new class:
import jcc_test
import time, sys
jvm = jcc_test.initVM(jcc_test.CLASSPATH)
test = jcc_test.JccTest()
class MyListener(jcc_test.JccTestListenerImpl):
## if you define a constructor here make sure to invoke super constructor
#def __init__(self):
# super(MyListener, self).__init__()
# pass
def messageImpl(self, msg):
print msg
listener = MyListener()
test.addJccTestListener(listener)
test.start()
time.sleep(10)
test.stop()
sys.exit(0)
This now works as expected with callbacks coming in.
"python.exe" jcc_test_test.py
Start
Notifiying listeners
Notifiying com.example.jcc.JccTestListenerImpl#4b67cf4d
I'm giving you a message!
Sleeping
Notifiying listeners
Notifiying com.example.jcc.JccTestListenerImpl#4b67cf4d
I'm giving you a message!
Sleeping
Process finished with exit code 0
I am using Java logging to log the memory static in my file and use java.util.logging.FileHandler to implement rotating log. Now I have a situation where my manager wants to keep the initial logging file and rotate the rest of the file. Is there any way I can keep the initial log file but yet rotate the rest of the file.
public class TopProcessor extends Handler {
Handler handler;
public TopProcessor() throws IOException{
File dir = new File(System.getProperty("user.home"), "logs");
dir.mkdirs();
File fileDir = new File(dir,"metrics");
fileDir.mkdirs();
String pattern = "metrics-log-%g.json";
int count = 5;
int limit = 500000;
handler = new TopProcessorHandler(fileDir.getAbsolutePath()+File.separator+pattern, limit, count);
}
class TopProcessorHandler extends FileHandler{
public TopProcessorHandler(String pattern, int limit, int count)
throws IOException {
super(pattern, limit, count);
}
}
private void writeInformationToFile(String information) {
handler.publish(new LogRecord(Level.ALL, information));
}
#Override
public void close() {
handler.close();
}
#Override
public void flush() {
handler.flush();
}
#Override
public void publish(LogRecord record) {
handler.publish(record);
}
}
Create 2 files one initial log file and other rotating log file..You can merge two files when you want to read logs
When I received an exception such as IOException or RunTimeException, I can only know the line number in the class.
First of my question. Is it possible to retrieve the method name through exception?
Second, is it possible to retrieve the method and the parameter of this method by line number?
p.s. I need to know the exact method name and its parameters, because I want to distinguish the overloading methods. To distinguish overloading methods, all that I know is to determine its parameters.
try{
//your code here}
catch(Exception e){
for (StackTraceElement st : e.getStackTrace())
{
System.out.println("Class: " + st.getClassName() + " Method : "
+ st.getMethodName() + " line : " + st.getLineNumber());
}
}
as you can see in the code above, you can get the stackTrace and loop over it to get all the method names and line numbers, refer to this for more info http://download.oracle.com/javase/1.4.2/docs/api/java/lang/StackTraceElement.html
If you look at the stacktrace you can know in which line the error occurred.
When using an overriden method you get the exact class name, source file and line number, you just have to know how to read it.
From that page:
java.lang.NullPointerException
at MyClass.mash(MyClass.java:9) //<--- HERE!!!!
at MyClass.crunch(MyClass.java:6)
at MyClass.main(MyClass.java:3)
This says, the problem occurred in line 9 of file MyClass.java in the method mash, which was in turn invoked by the method crunch at line 6 of the same file which was invoked by main in line 3 of the same file.
Heres the source code:
class MyClass {
public static void main(String[] args) {
crunch(null); // line 3
}
static void crunch(int[] a) {
mash(a); // line 6
}
static void mash(int[] b) {
System.out.println(b[0]);//line 9, method mash.
}
}
Basically you just have to ... well read it!
Stacktraces are a bit hard to grasp the first time, but later they become a very powerful tool.
I hope this helps.
pass it the exception and it will print the parameter types of the methods along with the exception
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
public class Main
{
public static void main(String[] args)
{
new Main().run();
}
public void run(){
try
{
new Car().run(60, "Casino");
}
catch (Exception e)
{
detailedException(e);
}
try
{
new Engine().run(10);
}
catch (Exception e)
{
detailedException(e);
}
}
public void detailedException(Exception e)
{
try
{
StringBuilder buffer = new StringBuilder(e.getClass().getName()).append(" \"").append(e.getMessage()).append("\"\n");
for (var trace: e.getStackTrace())
{
buffer.append("\tat ").append(trace.getClassName()).append(".").append(trace.getMethodName()).append("(").append(trace.getFileName()).append(":").append(trace.getLineNumber()).append(")[");
Class<?> clazz = Class.forName(trace.getClassName());
ArrayList<Method> methods = new ArrayList<>(Arrays.asList(clazz.getMethods()));
methods.removeIf(m -> !m.getName().equals(trace.getMethodName()));
Method method = methods.get(0);
for (var param: method.getParameters())
{
buffer.append(param.getName()).append(":").append(param.getParameterizedType().getTypeName()).append(", ");
}
buffer.append("]->").append(method.getGenericReturnType().getTypeName()).append("\n");
}
System.err.println(buffer);
}
catch (Exception parseFailed){
e.printStackTrace();
}
}
}
class Car extends Engine
{
public void run(int when, String where) throws Exception
{
super.run(25);
}
}
class Engine
{
public String run(int For) throws Exception
{
throw new Exception("need more fuel");
}
}
I need to hack up a small tool. It should read a couple of files and convert them. Right now that works in my IDE. For the user, I'd like to add a small UI which simply shows the log output.
Do you know of a ready-to-use Swing appender for logback? Or something which redirects System.out to a little UI with nothing more than a text field and a "Close" button?
PS: I'm not looking for Chainsaw or Jigsaw or Lilith. I want the display of the log messages in the application, please.
You need to write a custom appender class like so:
public class MyConsoleAppender extends AppenderBase<ILoggingEvent> {
private Encoder<ILoggingEvent> encoder = new EchoEncoder<ILoggingEvent>();
private ByteArrayOutputStream out = new ByteArrayOutputStream();
public MyConsoleAppender() {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
setContext(lc);
start();
lc.getLogger("ROOT").addAppender(this);
}
#Override
public void start() {
try {
encoder.init(out);
} catch (IOException e) {}
super.start();
}
#Override
public void append(ILoggingEvent event) {
try {
encoder.doEncode(event);
out.flush();
String line = out.toString(); // TODO: append _line_ to your JTextPane
out.reset();
} catch (IOException e) {}
}
}
You can replace the EchoEncoder with a PatternLayoutEncoder (see CountingConsoleAppender example in the logback examples folder).
The encoder will write each event to a byte buffer, which you can then extract a string and write this to your JTextPane or JTextArea, or whatever you want.
I often rely on JTextArea#append(), as suggested in this example. Unlike most of Swing, the method happens to be thread safe.
Addendum: Console is a related example that redirects System.out and System.err to a JTextArea.
No warranty, but here's a sample that I just wrote:
/**
* A Logback appender that appends messages to a {#link JTextArea}.
* #author David Tombs
*/
public class JTextAreaAppender extends AppenderBase<ILoggingEvent>
{
private final JTextArea fTextArea;
private final PatternLayout fPatternLayout;
public JTextAreaAppender(final Context loggerContext, final JTextArea textArea)
{
fTextArea = textArea;
// Log the date, level, class name (no package), and the message.
fPatternLayout = new PatternLayout();
fPatternLayout.setPattern("%d{HH:mm:ss.SSS} %-5level - %msg");
fPatternLayout.setContext(loggerContext);
fPatternLayout.start();
// Make sure not to call any subclass methods right now.
super.setContext(loggerContext);
}
#Override
protected void append(final ILoggingEvent eventObject)
{
// Actual appending must be done from the EDT.
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run()
{
final String logStr = fPatternLayout.doLayout(eventObject);
// If the text area already has lines in it, append a newline first.
if (fTextArea.getDocument().getLength() > 0)
{
fTextArea.append("\n" + logStr);
}
else
{
fTextArea.setText(logStr);
}
}
});
}
}