This week's book giveaway is in the Cloud forum.
We're giving away four copies of The Business Blockchain and have William Mougayar on-line!
See this thread for details.
Win a copy of The Business Blockchain this week in the Cloud forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Muffin example (re-)visited -getting it working

 
Stig Val
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Getting the Java webstart kit from http://java.sun.com/products/javawebstart/download-jnlp.html...

Look at the only current muffin example...
http://java.sun.com/products/javawebstart/docs/developersguide.html

"Using a PersistenceService Service"

You notice that the example will not immediately compile... Fx. type error in "byte [] buf = new byte[fc.getLength()];" where .getLength() returns a long... (not a primitive int as expected by java compiler). Why catch on "Exception" and not the actually thrown exceptions... Well, make a person wonder if the writer ever actually produce a working example for himself?

Fixing and cleaning... (I can post the whole code if necessary - but let's just take a gentle approach first). I'm trying to read any existing muffins - and force creation of one anyway...


...
String urlName = "http://localhost:8888/servlets-examples/servlet/CookieServlet";

URL url;
try {
url = new URL(urlName);
}
catch(MalformedURLException mfe) {
mfe.printStackTrace();
url = null;
return;
}

PersistenceService persistanceService = null;
BasicService basicService = null;

try {
persistanceService = (PersistenceService)ServiceManager.lookup("javax.jnlp.PersistenceService");
basicService = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService");
} catch (UnavailableServiceException e) {
}
if (persistanceService != null && basicService != null) {

try {

// find all the muffins for our URL
URL codebase = basicService.getCodeBase();
//code works for me this far - but fails in the following...
String [] muffins = persistanceService.getNames(url);

int numberOfMuffins = ((muffins==null)?0:muffins.length);

if(numberOfMuffins>0) {
// get the attributes (tags) for each of these muffins.
// update the server's copy of the data if any muffins
// are dirty
int [] tags = new int[muffins.length];
URL [] muffinURLs = new URL[muffins.length];
for (int i = 0; i < muffins.length; i++) {
muffinURLs[i] = new URL(codebase.toString() + muffins[i]);
tags[i] = persistanceService.getTag(muffinURLs[i]);

// update the server if anything is tagged DIRTY
if (tags[i] == PersistenceService.DIRTY) {
//doUpdateServer(muffinURLs[i]);
}
}

// read in the contents of a muffin and then delete it
FileContents fc = persistanceService.get(muffinURLs[0]);
long maxsize = fc.getMaxLength();
byte [] buf = new byte[(int)fc.getLength()];
InputStream is = fc.getInputStream();
long pos = 0;
while((pos = is.read(buf, (int)pos, (int)(buf.length - pos))) > 0) {
// just loop
}
is.close();

persistanceService.delete(muffinURLs[0]);

// re-create the muffin and repopulate its data
persistanceService.create(muffinURLs[0], maxsize);
fc = persistanceService.get(muffinURLs[0]);

// don't append
OutputStream os = fc.getOutputStream(false);
os.write(buf);
os.close();

}
} catch (IOException e) {
e.printStackTrace();
}

try {
// well, just try and create the muffin and repopulate its data
persistanceService.create(url, 50);
FileContents fc = persistanceService.get(url);

// don't append
OutputStream os = fc.getOutputStream(false);
os.write("1234567890test1234567890test00".getBytes());
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}


Trying this code produces (why can't you cutn'paste from the webstart 1.2 console.. only a "Clear" button and hotkeys doesn't work..):

java.net.MalformedURLException: Access to persistant storage denied for URL localhost:8888/servlets-examples/servlet/CookieServlet/
at com.sun.jnlp.PersistanceServiceImpl.throwAccessDenied(Unknown Source)
at com.sun.jnlp.PersistanceServiceImpl.checkAccessDenied(Unknown Source)
at com.sun.jnlp.PersistanceServiceImpl.getNames(Unknown Source)
at CookieClient.main(CookieClient.java:91)
...
java.net.MalformedURLException: Access to persistant storage denied for URL localhost:8888/servlets-examples/servlet/CookieServlet/
at com.sun.jnlp.PersistanceServiceImpl.throwAccessDenied(Unknown Source)
at com.sun.jnlp.PersistanceServiceImpl.checkAccessDenied(Unknown Source)
at com.sun.jnlp.PersistanceServiceImpl.getNames(Unknown Source)
at CookieClient.main(CookieClient.java:144)
...

91: the place where I do the "persistanceService.getNames(url);"
144: the place with persistanceService.create(url, 50)

Obviously it appears to be some missing security permission...

OK, I did! sign the .jar file with a self-generated signature.
OK, my servlet "CookieServlet" actually exists and works. The url works fine from the browser url (.get(..) method).
OK, I did a

Policy.setPolicy( new Policy() {
public PermissionCollection
getPermissions(CodeSource codesource) {
Permissions perms = new Permissions();
perms.add(new AllPermission());
return(perms);
}
public void refresh() {}
});

just before the denied actions.... Hmm... I'll probably figure it out eventually - but a hint would surely save me for a lot of time

StigV
 
Stig Val
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK after lots of work with muffins... And being way past problems above...

I discover an error in the Sun official muffin handling. Don't know if this is WinXP only. Problems basicly relates to the fact that Muffins are stored in two files: PM<muffinname>, PU<muffinname>

Both files should be deleted when deleting a muffin entry. However, Sun does not implement proper file handling if one file is locked by the operating system. And it just happens so, that this happens in my M$ XP...

Check out:


Files dissassebled from Sun JDK 1.4.2_05 (latest & greatest)


jawaws.jar: com.sun.jnlp.PersistenceServiceImpl (distribution decompiled)

public void delete(URL url)
throws MalformedURLException, IOException
{
if(_muffincache == null)
return;
checkAccess(url);
try
{
AccessController.doPrivileged(url. new PrivilegedExceptionAction() {

public Object run()
throws MalformedURLException, IOException
{
DiskCacheEntry diskcacheentry = _muffincache.getMuffinEntry('P', url);
if(diskcacheentry == null)
{
throw new FileNotFoundException(url.toString());
} else
{
_muffincache.removeMuffinEntry(diskcacheentry);
return null;
}
}

private final URL val$url;
private final PersistenceServiceImpl this$0;


throws IOException
{
this$0 = final_persistenceserviceimpl;
url = URL.this;
}
});
}





jawaws.jar: com.sun.javaws.cache.Diskcache (distribution decompiled)


public void removeMuffinEntry(DiskCacheEntry diskcacheentry)
{
char c = diskcacheentry.getType();
URL url = diskcacheentry.getLocation();
String s = diskcacheentry.getVersionId();
deleteEntry(c, 'M', url, s);
deleteEntry(c, 'U', url, s);
>
>1) big mistake not to check that everything went well
> In WinXP it happens so... that PU may be deleted while PM is
> locked by another process. This leaves only PM - which
> is a flawed muffin entry, which blocks creation of other
> muffin - but on the other hand cannot be read because PU is
> missing.
>
> Jeez, Sun... why didn't you make it one file - or add proper
> synchronization around handling the two files...
>

}


private void deleteEntry(char c, char c1, URL url, String s)
{
File file = null;
try
{
if(c1 == 'B')
file = getMappedImage(c, c1, url, s, false);
else
file = getFileFromCache(c, c1, url, s, false);
deleteFile(file);
}
catch(IOException ioexception)
{
Debug.ignoredException(ioexception);
}
if(file != null && file.exists() && c == 'R' && c1 == 'M')
addOrphan(url, file);
}







jawaws.jar: com.sun.javaws.cache.Diskcache (distribution decompiled)

public void insertMuffinEntry(URL url, File file, int i, long l)
throws IOException
{
File file1 = getFileFromCache('P', 'M', url, null, false);
if(file1.exists())
{
file.delete();
throw new IOException("insert failed in cache: target already exixts");
>
>1) spelling error - just make you wonder...
>2) checks for PM file and ignores existance of PU
> if PU deleted and PM remain alone, it's not a valid entry anyway...
>
>
>

}
if(!file.renameTo(file1))
{
throw new IOException("rename failed in cache");
} else
{
putMuffinAttributes(url, i, l);
return;
}
}

SOLUTION: move all stuff into one file ("PX" ?) or add error handling. Sure, we could fix the problem for Sun (or anybody) but it is really necessary to get the fix out in an official Sun release... But considering the size of the bug-parade, it just doesn't seem realistic for me...

CONCLUSION: Muffins are prone to errors and not really a mature technology yet with sufficient error-handling. Sure, Microsoft OS creates the problem -but webstart doesn't seem to be able to handle it!

Thanks for yor attention. Sorry for any mistakes I _may_ have made. Hope it helps others.


StigV / 2004-07-21 / topsecurity.dk / cryptography.dk
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic