Update Tiddlywiki Java Saver

, , , , ,

I was poking around the TiddlyWiki Trac site and noticed a new ticket #253 opened on my Java saving code.

Apparently one or more of Gentoo Linux, the Linux JVM, or Opera for Linux require the saving code (and probably the loading code too) to be wrapping in a PrivilegedAction class into order to execute, regardless of Java security policy settings.

The ticket included some code, but sorry "thomaskammeyer", I don't like your style! eek

Here's my new Java code:
import java.io.*;
import java.security.*;

public class TiddlySaver extends java.applet.Applet {
  class PrivilegedLoad implements PrivilegedAction {
    private String filename;
    private String charset;

    public PrivilegedLoad(String filename, String charset) {
      this.filename = filename;
      this.charset  = charset;
    }

    public Object run() {
      try {
        if (charset.length() == 0) {
          StringBuffer data = new StringBuffer();
          BufferedReader r = new BufferedReader(new FileReader(filename));
          String line;
          while ((line = r.readLine()) != null) data.append(line).append("\n");
          r.close();
          return data.toString();
        } else {
          File f = new File(filename);
          FileInputStream i = new FileInputStream(f);
          byte[] b = new byte[(f.length() > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)f.length()];
          int offset = 0;
          int num = 0;
          while (offset < b.length && (num = i.read(b, offset, b.length - offset)) >= 0) {
            offset += num;
          }
          i.close();
          return new String(b, 0, offset, charset);
        }
      } catch (Exception x) {
        x.printStackTrace();
        return null;
      }
    }
  }

  class PrivilegedSave implements PrivilegedAction {
    private String filename;
    private String charset;
    private String data;

    public PrivilegedSave(String filename, String charset, String data) {
      this.filename = filename;
      this.charset  = charset;
      this.data     = data;
    }

    public Object run() {
      try {
        File f = new File(filename).getCanonicalFile();
        f.getParentFile().mkdirs();
        if (charset.length() == 0) {
          int e, s = 0;
          BufferedWriter w = new BufferedWriter(new FileWriter(f));
          do {
            e = data.indexOf('\n', s);
            if (e == -1) e = data.length();
            w.write(data, s, e - s);
            w.newLine();
            s = e + 1;
          } while (s < data.length());
          w.close();
          return Boolean.TRUE;
        } else {
          FileOutputStream o = new FileOutputStream(f);
          o.write(data.getBytes(charset));
          o.close();
          return Boolean.TRUE;
        }
      } catch (Exception x) {
        x.printStackTrace();
        return Boolean.FALSE;
      }
    }
  }

  public String loadFile(String filename, String charset) {
    return (String)AccessController.doPrivileged(new PrivilegedLoad(filename, charset));
  }
  public int saveFile(String filename, String charset, String data) {
    return ((Boolean)AccessController.doPrivileged(new PrivilegedSave(filename, charset, data))).booleanValue() ? 1 : 0;
  }
}
Here's the above compiled into a new JAR: TiddlySaver.jar
To Jeremy: If you're reading this, the build script needs a small change: The jar command needs to refer to all class files, i.e. "TiddlySaver*.class".

I've tested this on my WinXP machine using the standard policy and it worked fine, but could not test on MacOS or any flavour of Linux.

I'm Never Upgrading Linux Again!Merry Christmas!

Comments

LuanaLuaCaron Monday, February 25, 2008 12:26:34 AM

Hi Andrew, I was wondering if you can help me...
I am new to Opera but have been using TiddlyWikis for a long time as lab journals.
I saw your java solution to enable Opera to save TiddlyWikis, but I could not make it work.
I am using Opera 9.36 and TiddlyWiki 2.3.0 on windows XP.

I set the following .java.policy file:
grant codeBase "file:C:/Documents and Settings/Owner/My Documents/wikis/*" { permission java.io.FilePermission "C:${/}Documents and Settings${/}Owner${/}My Documents${/}wikis${/}*", "read,write";
};
Saved on C:/Documents and Settings/Owner.

And put a copy of your TiddlySaver.jar on my wikis folder.
Any clue on what I am missing?

Andrew Gregory Monday, February 25, 2008 3:36:35 AM

As an example, here's what I have in my .java.policy:
grant codeBase "file:${user.home}/My Documents/tiddlywiki-folder/*" {
  permission java.io.FilePermission "${user.home}${/}My Documents${/}tiddlywiki-folder", "read,write";
  permission java.io.FilePermission "${user.home}${/}My Documents${/}tiddlywiki-folder${/}-", "read,write";
};

LuanaLuaCaron Wednesday, February 27, 2008 3:57:12 PM


It works now, and I guess it was working before, it is just that I was not aware of the 3-min delay...
Thank you!

Andrew Gregory Thursday, February 28, 2008 2:07:11 AM

The applet code just takes a second or two, but if it cannot be loaded, TiddlyWiki falls back to my original LiveConnect code, which takes an age to run. Check your Java console for error messages.

LuanaLuaCaron Friday, February 29, 2008 2:43:13 PM

You are right, my Java console is filled with errors... Not that I know how to fix them. But, one thing I found is that your applet is not reading my .java.policy file. Any clues on what is going on?

Andrew Gregory Saturday, March 1, 2008 2:32:51 AM

No applet (mine included) reads the policy file - it's the Java Runtime that does that. If your runtime isn't reading the policy file then it must be one of:

1. In the wrong folder (C:\Documents and Settings\your-username-here\)
2. The wrong name (.java.policy) - if you have Windows "hide extensions of known files types" turned on, then the file might really be named ".java.policy.txt". Open your policy file in Notepad, then resave it with double-quotes around the file name. That forces Windows to save using the exact name specified and it won't add a default extension.
3. The policy file data is malformed in some way. eg misplaced curly brace, missing semi-colon, etc. Every permission line must end with a semi-colon and the closing brace of every grant must have a semi-colon after it. See http://java.sun.com/j2se/1.5.0/docs/guide/security/PolicyFiles.html

LuanaLuaCaron Saturday, March 1, 2008 11:44:11 PM

Hi Andrew, appearently I had a bad combination of TiddlySaver.jar file + a mask as firefox network settings... Once I realized my mistake and re-downloaded the .jar file, it worked perfectly.

Thank you very much!
(and sorry for bothering you so many times rolleyes )

Andrew Gregory Sunday, March 2, 2008 3:20:08 AM

No problem. Glad you got it sorted out! up

Write a comment

You must be logged in to write a comment. If you're not a registered member, please sign up.

February 2012
S M T W T F S
January 2012March 2012
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29