For bilingual support in an application I am working on, we are using Spring messaging which uses two files, ApplicationResources.properties and ApplicationResources_fr.properties. This works well.
Now I am trying to expand on this by making it a little more dynamic. The application will read key value pairs from the database and insert them, which gives me the following error:
java.io.FileNotFoundException: \ApplicationResources.properties (Access is denied)
I am able to check on the key value pairs so I know the path I am using is correct. I have also checked the files in Eclipse properties by right clicking, and by visiting the actual file on my system, and they are not read-only. I do not believe they are encrypted because I am able to open and view with notepad++.
Here is my testing code which shows I can view them
Properties test_prop = null;
InputStream is = null;
try {
test_prop = new Properties();
is = this.getClass().getResourceAsStream(en_path);
test_prop.load(is);
Set<Object> keys = test_prop.keySet();
boolean key_found = false;
for(Object k:keys) {
String key = (String)k;
if(key.equals("f12345"))
{
key_found=true;
break;
}
}
System.out.println("Language Properties Test in DAO:" + (key_found? "Key Found" : "Key not found"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Here is where I try to write to the file, and get the error:
ResultSet rs = null;
try (
Connection connection = jdbcTemplate.getDataSource().getConnection();
CallableStatement callableStatement = connection.prepareCall(test_prod_cur);
)
{
callableStatement.registerOutParameter(1, OracleTypes.CURSOR);
callableStatement.executeUpdate();
rs = (ResultSet) callableStatement.getObject(1);
while (rs.next())
{
String thead = rs.getString(1);
//System.out.println(thead + " " + rs.getString(2) + " " + rs.getString(3));
en_prop.setProperty(keyheader+thead, rs.getString(2));
fr_prop.setProperty(keyheader+thead, rs.getString(3));
}
}
catch (SQLException e)
{
System.out.println("SQLException - bilingual values - CLUDAOImpl");
System.out.println(e.getMessage());
}
//add to properties files
//*
try (OutputStream en_os = new FileOutputStream(en_path);)
{
en_prop.store(en_os, null);
} catch (IOException e) {
e.printStackTrace();
}
try(OutputStream fr_os = new FileOutputStream(en_path);)
{
fr_prop.store(fr_os, null);
} catch (IOException e) {
e.printStackTrace();
}
So the database query is successful, that was tested with the commented out system.out.println. It is the following lines that end up throwing the error:
en_prop.store(en_os, null);
fr_prop.store(fr_os, null);
Update: I did a search on the java.util.Properties which lead me to the javadocs on it and wow does that simplify many things. I can now grab a property value or check if the key exists in 6 lines of code (not counting try catch).
Properties prop = null;
InputStream is = null;
this.prop = new Properties();
is = this.getClass().getResourceAsStream(path);
prop.load(is);
this.prop.getProperty("key name"); //returns value of key, or null
this.prop.containsKey("key name"); //returns true if key exists
Update2: There is an issue using java.util.Properties and that is you lose all formatting of the original file, so white-space, comments, and ordering are all lost. In another answer someone suggested using Apache's Commons Configuration API. I plan on trying it out.
So I ended up creating a class to handle interactions with the ApplicationResources(_fr).properties files instead of doing it in the DAO. This was because I plan on using it in more places. I also started using methods from the java.util.Properties Javadocs which proved very helpful and simplified many areas.
Below is my new file write/properties store code.
try (
OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false);
OutputStream fr_os = new FileOutputStream(getClass().getResource(fr_path).getFile(), false);
)
{
en_prop.store(en_os, null);
fr_prop.store(fr_os, null);
} catch (IOException e) {
e.printStackTrace();
}
Lets compare the new and original OutputStreams:
OutputStream en_os = new FileOutputStream(getClass().getResource(en_path).getFile(),false); //new
OutputStream en_os = new FileOutputStream(en_path); //original, Access is Denied
This answer is incomplete for the following reasons.
I am unable to explain why the original method failed and resulted in a "Access is denied error".
More concerning reason to me, this doesnt actually alter the file I am expecting or wanting. I expected to alter the file that appears in my project navigator, but when viewed changes are not observed. If I use an absolute path (C:\...) and overwrite the file then I can alter it as expected, but this path would have to be changed as servers are changed and its bad programming and dangerous. This working method is altering some kind of temp or running file (as confirmed via the path as the file that shows the new values is in the tmp0 folder). After some testing, this temporary file is overwritten on startup only when the original file has been changed, otherwise the new values persist across application starting.
I am also unsure as to the scope of this file. I am unable to tell if all users interacting with the website would cause changes to the same file. If all users are interacting with the file, then potential leakage across sessions could occur. It is also possible that each session has isolated values and could lead to missing information. I suspect that all users are interacting with the same resource but have not performed the testing required to be absolutely positive about this. UPDATE: I have confirmed that all users interact with the same temporary file.
Related
In fact I am making a Minecraft plugin and I was wondering how some plugins (without using DB) manage to keep information even when the server is off.
For example if we make a grade plugin and we create a different list or we stack the players who constitute each. When the server will shut down and restart afterwards, the lists will become empty again (as I initialized them).
So I wanted to know if anyone had any idea how to keep this information.
If a plugin want to save informations only for itself, and it don't need to make it accessible from another way (a PHP website for example), you can use YAML format.
Create the config file :
File usersFile = new File(plugin.getDataFolder(), "user-data.yml");
if(!usersFile.exists()) { // don't exist
usersFile.createNewFile();
// OR you can copy file, but the plugin should contains a default file
/*try (InputStream in = plugin.getResource("user-data.yml");
OutputStream out = new FileOutputStream(usersFile)) {
ByteStreams.copy(in, out);
} catch (Exception e) {
e.printStackTrace();
}*/
}
Load the file as Yaml content :
YamlConfiguration config = YamlConfiguration.loadConfiguration(usersFile);
Edit content :
config.set(playerUUID, myVar);
Save content :
config.save(usersFile);
Also, I suggest you to make I/O async (read & write) with scheduler.
Bonus:
If you want to make ONE config file per user, and with default config, do like that :
File oneUsersFile = new File(plugin.getDataFolder(), playerUUID + ".yml");
if(!oneUsersFile.exists()) { // don't exist
try (InputStream in = plugin.getResource("my-def-file.yml");
OutputStream out = new FileOutputStream(oneUsersFile)) {
ByteStreams.copy(in, out); // copy default to current
} catch (Exception e) {
e.printStackTrace();
}
}
YamlConfiguration userConfig = YamlConfiguration.loadConfiguration(oneUsersFile);
PS: the variable plugin is the instance of your plugin, i.e. the class which extends "JavaPlugin".
You can use PersistentDataContainers:
To read data from a player, use
PersistentDataContainer p = player.getPersistentDataContainer();
int blocksBroken = p.get(new NamespacedKey(plugin, "blocks_broken"), PersistentDataType.INTEGER); // You can also use DOUBLE, STRING, etc.
The Namespaced key refers to the name or pointer to the data being stored. The PersistentDataType refers to the type of data that is being stored, which can be any Java primitive type or String. To write data to a player, use
p.set(new NamespacedKey(plugin, "blocks_broken"), PersistentDataType.INTEGER, blocksBroken + 1);
I want to hide the URL in the 1D barcode so when anyone scan it, it will directly take me to the product page.
Is it possible, I have generated barcode now when I am scanning it, it is showing me barcode number but not the URL.
try {
Code128Bean code128 = new Code128Bean();
code128.setHeight(15f);
code128.setModuleWidth(0.3);
code128.setQuietZone(10);
code128.doQuietZone(true);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BitmapCanvasProvider canvas = new BitmapCanvasProvider(baos, "image/x-png", 300, BufferedImage.TYPE_BYTE_BINARY, false, 0);
code128.generateBarcode(canvas, myString);
canvas.finish();
//write to png file
FileOutputStream fos = new FileOutputStream("C:\\Report\\"+image_name);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
// TODO: handle exception
}
}
String query="select * from itemdetails where barcodenumber='"+loc+"'";
ps = connection.prepareStatement(query);
rs=ps.executeQuery();
while(rs.next()){
Barcode_Image.createImage(rs.getString("websiteurl")+".png", rs.getString("barcodenumber"));
Barcode_PDF.createPDF(rs.getString("barcodenumber")+".pdf", rs.getString("barcodenumber"),rs.getString("websiteurl"));
System.out.println("Creating Barcode for "+rs.getString("barcodenumber"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(connection!=null){
try {
//connection.close();
}
catch (Exception e2) {
e2.printStackTrace();
}
}
if(ps!=null){
try {
//ps.close();
}
catch (Exception e2) {
e2.printStackTrace();
}
}
I would use QRCode for this.
Your barcode will be awesome long if you have long urls, which can be a problem depending what you want to do with it. You could use an url-shortener system, but again could be problematic.
Another problem is, that you need something triggering the call to the url.
Normally Barcode scanners are shipped with a software, which you can configure to do sth like this.
Scanning a barcode is just "reading" its content. A barcode scanner can be seen as another form of keyboard.
So after you've read the content you will need some piece of software, that opens the browser and calls the url.
And think about the potential consumers...when you see a barcode, normally you don't think this is something you should scan to go to get some extra info, but that's the case with for ex. a QR Code. When you see it, you know (normally) what to expect.
I suppose there are some mobile apps, that after scanning a barcode, if they check the scanned string, and it's an url, they will give you the opportunity to navigate to this url. In this case only consumers with this type of app will be able to visit the page.
i need some help. I have to retrieve whole jndi db options to a selectlist in a html file which means i need to access all jndi db names and get these values
Any idea ?
I had some trouble finding JNDI names in one of my WebLogic servers. I created a method that iterates through the JDNI tree structure, and prints all of them to the console. I am not sure that this is what you need, but here is the code I used for it:
private void printList(String directory){
try {
NamingEnumeration<NameClassPair> namings = context.list(directory);
System.out.println("************Printing " + directory + "**************");
while(namings.hasMoreElements()){
if(directory.equals("")) printList(namings.next().getName());
else printList(directory+"."+namings.next().getName());
}
System.out.println("Done printing " + directory);
} catch (NamingException e) {
// TODO Auto-generated catch block
System.out.println(directory);
}
}
you can pass a string of a desired directory, or an empty string, if you want all elements from the root. You'll need to import javax.naming.* (or -NamingEnumeration/-NameClassPair)
Almost forgot:
you'll first need to define a context for where the method should look for the directory:
Context context = null;
Hashtable<String, String> ht = new Hashtable<String, String>();
ht.put(Context.PROVIDER_URL, "your_host");
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
//this above needs to be changed to fit your desired system
ht.put(Context.SECURITY_PRINCIPAL, "your_user");
ht.put(Context.SECURITY_CREDENTIALS, "your_password");
try {
context = new InitialContext(ht);
// Use the context in your program
}
catch (NamingException e) {
e.printStackTrace();
}
I have a problem with a java based DXL import.
We want to maintain properties files via our Java framework. I am working with a temporary file on my filesystem (I am working on a local server). I am exporting the new properties file to my filesystem, generate a DXL file in the same folder and then try to import the DXL into my database.
I have done several options of the importer and we are creating the stream and the importer with sessionAsSignerWithFullAccess. The code is signed with the ID of the Server Admin who has Full Access to everything.
When importing the DXL I receive only the error message "DXL Import Operation failed", the error log of the importer says I am not authorized to perform this operation.
Do you have any idea what could be the problem? From my point of view I can't give my User any more rights on the server.
Here is the code for the import function:
private void importDXLFile(String filepath) {
String dxlPath = filepath.replaceAll(".properties", ".dxl");
DxlImporter importer = null;
Stream stream = null;
System.out.println("dxlPath: " + dxlPath);
try {
stream = BCCJsfUtil.getCurrentSessionAsSignerWithFullAccess(FacesContextEx.getCurrentInstance()).createStream();
if (!stream.open(dxlPath, "ISO-8859-1")) {
System.out.println("Cannot read " + dxlPath + " from server");
}
System.out.println("User: " + BCCJsfUtil.getCurrentSessionAsSignerWithFullAccess(FacesContextEx.getCurrentInstance()).getEffectiveUserName());
importer = BCCJsfUtil.getCurrentSessionAsSignerWithFullAccess(FacesContextEx.getCurrentInstance()).createDxlImporter();
importer.setReplaceDbProperties(false);
importer.setReplicaRequiredForReplaceOrUpdate(false);
importer.setDesignImportOption(DxlImporter.DXLIMPORTOPTION_REPLACE_ELSE_CREATE);
importer.setInputValidationOption(DxlImporter.DXLVALIDATIONOPTION_VALIDATE_NEVER);
importer.setExitOnFirstFatalError(false);
importer.importDxl(stream.readText(), BCCJsfUtil.getCurrentDatabase());
stream.close();
} catch (NotesException e) {
e.printStackTrace();
try {
System.out.println("Log: " + importer.getLog());
System.out.println("LogComment: " + importer.getLogComment());
} catch (NotesException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
As you can see I tried several options, hoping it would change anything, but it is always the same error message.
The generated DXL seems valid, as we can import it manually with Ytria.
I hope someone has an idea. Any help would be appreciated.
Thanks in advance.
Matthias
Please check your ACL settings:
Is "Maximum internet name and password" set to "Manager" or "Designer"?
We are using the new Java printing API which uses PrinterJob.printDialog(attributes) to display the dialog to the user.
Wanting to save the user's settings for the next time, I wanted to do this:
PrintRequestAttributeSet attributes = loadAttributesFromPreferences();
if (printJob.printDialog(attributes)) {
// print, and then...
saveAttributesToPreferences(attributes);
}
However, what I found by doing this is that sometimes (I haven't figured out how, yet) the attributes get some bad data inside, and then when you print, you get a white page of nothing. Then the code saves the poisoned settings into the preferences, and all subsequent print runs get poisoned settings too. Additionally, the entire point of the exercise, making the settings for the new run the same as the user chose for the previous run, is defeated, because the new dialog does not appear to use the old settings.
So I would like to know if there is a proper way to do this. Surely Sun didn't intend that users have to select the printer, page size, orientation and margin settings every time the application starts up.
Edit to show the implementation of the storage methods:
private PrintRequestAttributeSet loadAttributesFromPreferences()
{
PrintRequestAttributeSet attributes = null;
byte[] marshaledAttributes = preferences.getByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, null);
if (marshaledAttributes != null)
{
try
{
#SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
ObjectInput objectInput = new ObjectInputStream(new ByteArrayInputStream(marshaledAttributes));
attributes = (PrintRequestAttributeSet) objectInput.readObject();
}
catch (IOException e)
{
// Can occur due to invalid object data e.g. InvalidClassException, StreamCorruptedException
Logger.getLogger(getClass()).warn("Error trying to read print attributes from preferences", e);
}
catch (ClassNotFoundException e)
{
Logger.getLogger(getClass()).warn("Class not found trying to read print attributes from preferences", e);
}
}
if (attributes == null)
{
attributes = new HashPrintRequestAttributeSet();
}
return attributes;
}
private void saveAttributesToPreferences(PrintRequestAttributeSet attributes)
{
ByteArrayOutputStream storage = new ByteArrayOutputStream();
try
{
ObjectOutput objectOutput = new ObjectOutputStream(storage);
try
{
objectOutput.writeObject(attributes);
}
finally
{
objectOutput.close(); // side-effect of flushing the underlying stream
}
}
catch (IOException e)
{
throw new IllegalStateException("I/O error writing to a stream going to a byte array", e);
}
preferences.putByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, storage.toByteArray());
}
Edit: Okay, it seems like the reason it isn't remembering the printer is that it isn't in the PrintRequestAttributeSet at all. Indeed, the margins and page sizes are remembered, at least until the settings get poisoned at random. But the printer chosen by the user is not here:
[0] = {java.util.HashMap$Entry#9494} class javax.print.attribute.standard.Media -> na-letter
[1] = {java.util.HashMap$Entry#9501} class javax.print.attribute.standard.Copies -> 1
[2] = {java.util.HashMap$Entry#9510} class javax.print.attribute.standard.MediaPrintableArea -> (10.0,10.0)->(195.9,259.4)mm
[3] = {java.util.HashMap$Entry#9519} class javax.print.attribute.standard.OrientationRequested -> portrait
It appears that what you're looking for is the PrintServiceAttributeSet, rather than the PrintRequestAttributeSet.
Take a look at the PrintServiceAttribute interface, and see if the elements you need have been implemented as classes. If not, you can implement your own PrintServiceAttribute class(es).