dynamically setting classpath - java

I am writing a calculator that loads all the classes needed through maven dependencies dynamically.such as slf4j,...
but i have a problem.since i don't want to set my class path to manifest,my customClassLoader does it itself.
but my logger is a private static final field and JVM want to load it before i call my customClassLoader and i get error!what can i do?
public class Calculator{
private List<String> expressions = new ArrayList<String>() ;
private List<String> results = new ArrayList<String>();
private final Logger logger = LoggerFactory.getLogger(Calculator.class);
public Calculator(){
//System.out.println("HELLO");
OperatorsCatalog catalog = new OperatorsCatalog();
}
public void calculate(String inputaddress){
//this.loadAddedClasses();
try{
logger.debug("Start to read the input file");
this.read(inputaddress);
logger.info("Input file is read");
for(int i = 0;i<expressions.size();i++){
ExpressionCalculator e = new ExpressionCalculator(expressions.get(i),OperatorsCatalog.getKnownOperators());
e.evaluate();
results.add(e.getResult());
}
logger.info("All evaluations ended");
logger.debug("Writing to file started");
this.write();
}
catch(FileNotFoundException e){
logger.warn("Can not find Input file",e);
}
catch(IOException er){
logger.warn(er.getMessage());
}
}
public void read(String inputaddress)throws FileNotFoundException,IOException{
CustomReader reader = new CustomReader();
expressions =reader.read(inputaddress);
}
public void write(){
CustomWriter writer = new CustomWriter();
writer.write(results);
}
/*public void loadAddedClasses(){
CustomClassLoader classloader = new CustomClassLoader();
classloader.loadClasses();
}*/
public static void main(String args[]) {
System.out.println("HELLO");
CustomClassLoader classloader = new CustomClassLoader();
classloader.loadClasses();
Calculator calculator = new Calculator();
calculator.calculate(args[0]);
}
}

Related

LOG4J2 Use multiple config files using java

can log4j2 use multiple config files. I wanna run my project and load one default config file - logger.xml and after that to check if there is a second configuration from another file logger_1.xml and to add it and not to override the first one.
Here is some dummy code. In short I wanna fill up the arrayList with file paths and then to load all of them.
public class LoggerConfiguratorManager
{
public static final String LOG4J_PATH = "etc/confs/logger.xml";
private static LoggerContext context = null;
private static final ConfigurationFactory factory = XmlConfigurationFactory.getInstance();
private static ConfigurationSource configurationSource = null;
private static Configuration configuration = null;
private static final ArrayList<String> registred_logger = new ArrayList<>();
private static void loadLoggerConfig(String logger_path)
{
InputStream is = null;
try
{
if(logger_path.endsWith(".xml"))
is = new FileInputStream(logger_path);
else
{
final ZipFile archive = new ZipFile(logger_path);
final ZipEntry logger_entry = archive.getEntry(LOG4J_PATH);
if(logger_entry == null) throw new IOException("Cannot find 'logger.xml' in " + logger_path);
is = archive.getInputStream(logger_entry);
}
configurationSource = new ConfigurationSource(is);
configuration = factory.getConfiguration(configurationSource);
}
catch(IOException ex)
{
System.err.println("=============================================================================");
System.err.println("=============================== LOGGER CONFIG ===============================");
System.err.println("=============================================================================");
System.err.println("=== [ERROR] " + ex);
}
finally
{
if (configurationSource != null)
{
context = Configurator.initialize(null, configurationSource);
context.start(configuration);
try { is.close(); } catch(IOException ex) { }
}
}
}
public static void load()
{
registred_logger.add(Globals.getClassLocation(LoggerConfiguratorManager.class));
for(final String conf : registred_logger)
loadLoggerConfig(conf);
}
public static void regLoggerConf(String conf_path) { registred_logger.add(conf_path); }
I would suggest doing instead:
public class LoggerConfiguratorManager {
private static final String LOG4J_PATH = "etc/confs/log4j2.xml";
private static final StringBuffer paths = new StringBuffer(LOG4J_PATH);
public static void registerConfiguration(String confPath) {
paths.append(",").append(confPath);
}
public static void initLog4j() {
Configurator.initializer("My Config", null, paths.toString(), null);
}
}
For a full working example please see https://github.com/rgoers/CompositeConfigurationExample.

calling class from another class

I am calling class guibuilder from my class batchrun. code for batchrun is :-
public class batchrun {
public static String md5gen(String a) throws NoSuchAlgorithmException
{
MessageDigest m= MessageDigest.getInstance("MD5");
m.reset();
m.update(a.getBytes());
byte[] digest=m.digest();
BigInteger bigInt = new BigInteger(1,digest);
String hashtext = bigInt.toString(16);
while(hashtext.length() < 32 ){
hashtext = "0"+hashtext;
}
return hashtext;
}
private static String getInputAsString(InputStream is)
{
try(java.util.Scanner s = new java.util.Scanner(is))
{
return s.useDelimiter("\\A").hasNext() ? s.next() : "";
}
}
public static void main(String[] args) throws InterruptedException {
try {
guibuilder.main(args);
guibuilder gb=new guibuilder();
String fg=guibuilder.antd;
String arg1=gb.arg;
String userinp1=gb.userinp;
System.out.println("FG="+fg+" arg1="+arg1+" userinp="+userinp1);
Process pan = Runtime.getRuntime().exec(new String[] {"C:\\test1.bat",arg1,fg});
pan.waitFor();
String extra="\\";
extra+=userinp1;
String patha=fg+extra;
ProcessBuilder pb = new ProcessBuilder("adb","shell","getprop","ro.csc.sales_code");
Process p=pb.start();
p.waitFor();
String stdout = getInputAsString(p.getInputStream());
String newstring=stdout.substring(0,3);;
String fn=fg+"\\"+newstring+".txt";
ZipFile zipFile = new ZipFile(patha);
Enumeration<?> enu = zipFile.entries();
int flag=0;
String so="so";
File file = new File(fn);
FileOutputStream fos = new FileOutputStream(file);
PrintStream ps = new PrintStream(fos);
System.setOut(ps);
while (enu.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry) enu.nextElement();
String name = zipEntry.getName();
long size= zipEntry.getSize();
String extension= name.substring(name.lastIndexOf(".")+1,name.length());
if(extension.equals(so))
{
String plaintext=name+size;
String md5result=md5gen(plaintext);
System.out.println(name+" "+size+" "+md5result);
++flag;
}
}
if(flag==0)
System.out.println("fail");
}catch (IOException ex){
System.out.println(ex.getMessage());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The code for guibuilder is
public class guibuilder {
private JFrame frame;
public static String antd;
public static String arg;
public static String userinp;
/**
* Launch the application.
* #return
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
guibuilder window = new guibuilder();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public guibuilder() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnExtract = new JButton("Extract");
btnExtract.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.dispose();
fchooser fc1=new fchooser();
antd=fc1.demo();
arg=JOptionPane.showInputDialog("Enter the apk path");
userinp=JOptionPane.showInputDialog("Enter the apk name");
}
});
btnExtract.setBounds(69, 55, 89, 23);
frame.getContentPane().add(btnExtract);
JButton btnCompare = new JButton("Compare");
btnCompare.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.dispose();
newjframe n = new newjframe();
n.setVisible(true);
}
});
btnCompare.setBounds(261, 55, 89, 23);
frame.getContentPane().add(btnCompare);
}
}
I want the program to wait for the execution of guibuilder before continuing with the code from batchrun. But in this code, i have not even selected the files in guibuilder and the program continues execution and System.out.println("FG="+fg+" arg1="+arg1+" userinp="+userinp1); this line is printed before i choose anything in guibuilder.
Your code shows that your java project has two main classes. one in batchrun class another is in guibuilder class. [from your statement guibuilder.main(args)]
Use only one main class in your project. This may fix your problem.
I think your guibuilder class has structure like this
class guibuilder{
...... //global variables
public static void main(String[] args){
......... //statments
}
}
Don't use two main method in a single project.
you need to structure your guibuilder class like this (shown below)
class guibuilder{
...... //global variables
public static void buildGui(){//you can use any method name here
......... //statments
}
}
to invoke this method from another class just use this statement
guibuilder.buildGui()
or, another way
class guibuilder{
...... //global variables
public void buildGui(){//you can use any method name here
......... //statments
}
}
to invoke this method from another class use this statement
guibuilder gui=new guibuilder();
gui.buildGui();

Serialized Object File Output is empty

I am trying to create a file that stores high scores for a game that I am making. I am using a serializer to write my arrays into a file. The file is created upon running my code but the file is empty (0 bytes). I'm not getting any errors. Can anyone tell me why the file does not contain my data?
public class BestTimes implements Serializable
{
BestTimes[] beginner = new BestTimes[2];
public static void main(String args[]) throws IOException {
BestTimes bestTimes = new BestTimes();
bestTimes.outputToFile();
}
public BestTimes() {
beginner[0] = new BestTimes(1, "John", 10.5);
beginner[1] = new BestTimes(2, "James", 20.3);
}
public int ranking;
public String playerName;
public double time;
public BestTimes(int r, String p, double t)
{
ranking = r;
playerName = p;
time = t;
}
public void outputToFile() throws IOException {
try(FileOutputStream f = new FileOutputStream("bestTimes.txt")) {
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject(beginner);
s.flush();
s.close();
} finally {
FileOutputStream f = new FileOutputStream("bestTimes.txt");
f.close();
}
}
}
Of course it's empty. You created a new one in the finally block.
Just remove that code.

How to use ArrayList while adding something to another Class's constructor ?

I'm try to create one simple reservation system, we'll read a file, then we'll add Train, Bus, etc., then we'll writer everything to output.
import java.io.*;
import java.util.*;
public class Company
{
private static ArrayList<Bus> bus = new ArrayList<Bus>();
static int buscount = 0, traincount = 0;
public static void main (String[] args) throws IOException
{
FileParser();
}
public Company()
{
}
public static void FileParser()
{
try {
File file = new File(); //i fill this later
File file2 = new File(); // i fill this later
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(file2);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
String line;
while ((line = br.readLine()) != null)
{
String[] splitted = line.split(",");
if(splitted[0].equals("ADDBUS"))
{
bus.add(buscount) = Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]);
}
}
}
catch (FileNotFoundException fnfe) {
}
catch (IOException ioe) {
}
}
}
I try to read the file line by line. For example one of the line is "ADDBUS,78KL311,10,140,54" I split the line for "," then i try to add every pieces of array to Bus' class' constructor but i couldn't figured it out.
My Bus Class is like `
public class Bus extends Vehicle{
private String command;
private String busName;
private String busPlate;
private String busAge;
private String busSpeed;
private String busSeat;
public Bus(String command, String busname, String busplate, String busage, String busspeed, String busseat)
{
this.command = command;
this.busName = busname;
this.busPlate = busplate;
this.busAge = busage;
this.busSpeed = busspeed;
this.busSeat = busseat;
}
public String getBusName() {
return busName;
}
public void setBusName(String busName) {
this.busName = busName;
}
public String getBusPlate() {
return busPlate;
}
public void setBusPlate(String busPlate) {
this.busPlate = busPlate;
}
public String getBusAge() {
return busAge;
}
public void setBusAge(String busAge) {
this.busAge = busAge;
}
public String getBusSpeed() {
return busSpeed;
}
public void setBusSpeed(String busSpeed) {
this.busSpeed = busSpeed;
}
public String getBusSeat() {
return busSeat;
}
public void setBusSeat(String busSeat) {
this.busSeat = busSeat;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
}
can someone show me a way to solve this problem?
Thank you,
You are missing the keyword new to create a new instance of the class:
bus.add(new Bus(...));
You can add items to ArrayList like this
bus.add( new Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
you were missing new keyword before Bus constructor call. Then you can increment the counter (or do whatever)
bus.add( new Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
buscount++;
try to add new Bus(...)
bus.add( new
Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
As I understand if you want to call constructor you need to call new Bus(parms).
when you say new it will call constructor of your class
when you say this() again it going to call enclosing class' constructor
if you say super() it will call super class' constructor.
if you want it into a map order by counter you can use this:
Map(Integer, Bus) busPosition = new HashMap<>();
busPosition.put(buscount, new
Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));

How to access files within folders within jar files?

I have looked at How to access resources in JAR file? and How do I copy a text file from a jar into a file outside of the jar? and many other questiions but couldnt actually get an answer. What I'm trying to do is copy contents of a file in res/CDC.txt that is in jar, to somewhere out of a jar. Now, on my computer it works but when I try it on different computer I get FileNotFoundException. So, I figured out why it works on mine. I have a CLASSPATH set to .;D:\myname\Java\JavaFiles where all my java files are located in packages. In "JavaFiles" directory there is also "res/CDC.txt". So, when I start my application, it first checks the current directory myapp.jar is located in for "res/CDC.txt", and then it checks "JavaFiles" and finds it. Other computers do not have it. So, this was my initial code:
public final class CT
{
//Other fields
private static CT ct;
private NTSystem nts;
private File f1;
private File f6;
private PrintWriter pw1;
private BufferedReader br1;
//Other fields
public static void main(String[] args)
{
try
{
showMessage("Executing program...");
ct = new CT();
ct.init();
ct.create();
ct.insertData();
//Other code
showMessage("Program executed!");
}
catch(Exception e)
{
showMessage("An exception occured! Program closed.");
e.printStackTrace();
System.exit(0);
}
}
private void init()
throws IOException
{
//Other initialization
nts = new NTSystem();
f1 = new File("C:\\Users\\" + nts.getName() + "\\blahblah");
f6 = new File("res\\CDC.txt");
br1 = new BufferedReader(new FileReader(f6));
//Other initialization
showMessage("Initialized");
}
private void create()
throws IOException
{
//Makes sure file/dir exists, etc
pw1 = new PrintWriter(new BufferedWriter(new FileWriter(f1)), true);
//Other Stuff
showMessage("Created");
}
private void insertData()
throws IOException
{
String line = br1.readLine();
while(line != null)
{
pw1.println(line);
line = br1.readLine();
}
//Other stuff
showMessage("Data inserted");
}
private static void showMessage(String msg)
{
System.out.println(msg);
}
}
which I changed to
public final class CT
{
//Other fields
private static CT ct;
private NTSystem nts;
private byte[] buffer;
private File f1;
private URL url1;
private FileOutputStream fos1;
private InputStream is1;
//Other fields
public static void main(String[] args)
{
try
{
showMessage("Executing program...");
ct = new CT();
ct.init();
ct.create();
ct.insertData();
//Other code
showMessage("Program executed!");
}
catch(Exception e)
{
showMessage("An exception occured! Program closed.");
e.printStackTrace();
System.exit(0);
}
}
private void init()
throws IOException
{
//Other initialization
nts = new NTSystem();
buffer = new byte[4096];
f1 = new File("C:\\Users\\" + nts.getName() + "\\blahblah");
url1 = getClass().getClassLoader.getResource("res\\CDC.txt"); //Also tried url1 = ct.getClass().getClassLoader.getResource("res\\CDC.txt"); or url1 = this.getClass().getClassLoader.getResource("res\\CDC.txt"); or url1 = CT.getClass().getClassLoader.getResource("res\\CDC.txt");
is1 = url1.openStream();
//Other initialization
showMessage("Initialized");
}
private void create()
throws IOException
{
//Makes sure file/dir exists, etc
pw1 = new PrintWriter(new BufferedWriter(new FileWriter(f1)), true);
//Other Stuff
showMessage("Created");
}
private void insertData()
throws IOException
{
int read = is1.read(buffer);
while(line != null)
{
fos1.write(buffer, 0, read);
read = is1.read(buffer);
}
//Other stuff
showMessage("Data inserted");
}
private static void showMessage(String msg)
{
System.out.println(msg);
}
}
And this time I always get NullPointerException. So, how to read folders and files that are within jar?
Thanks
You will want to use getSystemResourceAsStream() to read the contents from files in a jar.
This of course is assuming the file is actually on the classpath of the other users computers.

Categories

Resources