We watched the penultimate episode of The Wire season 3 last night (on Netflix DVD). Omar and Brother Mazon doin' what they do. I love it!
Thursday, March 24, 2011
Friday, March 18, 2011
Seafood Watch Pocket Guide
I was just listening to Barton Seaver's TED Talk, and he mentioned Monterey Bay Aquarium's seafood pocket guide, so I checked it out. The guide recommends ocean-friendly seafood choices. What a great idea! Just print a guide out, keep it in my wallet, and check it the next time I buy seafood at a restaurant or the grocery.
By the way - a great way to organize podcasts in iTunes is to setup a "smart playlist"
where:
"Genre contains Podcast AND Plays is 0".
Thursday, March 10, 2011
Facebooking the bLog
I got the brain wave today to add a Facebook Like button to the bLog, and spent a couple hours banging my head against the dev docs before I tracked down Yaniv Kessler's bLog laying the whole thing out. Thanks, Yaniv!
Of course, as I'm implementing Yaniv's instructions I come across this block in the bLog's design template:
<b:includable id='shareButtons' var='post'> ...Freakin' blogger has a config checkbox that turns on a bunch of social-sharing buttons. Just call me Reuben "day late, dollar short" Pasquini.
Wednesday, March 09, 2011
Cookie Monster loves cookies!!!
C is for cookie - the peoples dessert; anyone can make it. The hardest part of making a cookie is creaming the butter, and that just requires muscles or machines - no brains needed. That's good enough for me.
Of course, some cookies are better than others. Everyone has his opinion, but here's some tips for how I like my chocolate chip cookies. These ideas evolved over years of criticism from Joanne complaining that I don't make the cookies right, but she's mostly happy now.
- First, only make half the recipe. The recipe on the back of the bag of chocolate chips calls for half a pound of butter, and makes about 36 cookies. Who wants 36 cookies ? Just halve the recipe, and make 9 at a time. The dough stays good in the fridge for 5 days or so. I usually start with the ghirardelli's recipe, and go from there.
- Next, only use half the chips. Whoever sold that bag of chips wants to stuff you full of chocolate, but I like a cookie with some chips, not chips with some cookie. So when making half the ghirardelli recipe, only use 1/2 cup of chips - not a full cup. That was Joanne's idea.
- I'm a nuts guy. I like a half cup of chopped pecans (walnuts are ok too) to go with the half cup of chips. Joanne doesn't like nuts, but I make the cookies, so nuts are in. I'm the man!
- Cover the dough, and let it sit in the fridge for a half a day. I don't know why, but the cookies are better. That's a tip from an old NY Times article.
- Joanne likes her cookies "crispy" - cooked all the way through - brown on top - no goo in the middle. Cook chocolate chip cookies at 375 degrees (ghiradelli got that right), but go for 12-13 minutes depending. Just keep an eye on the cookies after 10 minutes - pretend you're the Oracle in the Matrix. I used to be a crispy on the outside goo in the middle guy, but I've been converted.
- Most people like a warm from the oven cookie, but I actually like a cookie best an hour or two after it comes out of the oven. Somehow the cookie settles down chemically after an hour - not too hot, holds together well, nice texture - good "mouth feel" (isn't that a disgusting phrase?). At any rate - let the cookie cool a little bit on the sheet, then on a rack - outside of dogs' reach (very important). You'll just piss yourself off if you don't wait, and you try to pickup a cookie off the sheet, and it just collapses under it's own weight, because it's still goo, but you shove the goo into your mouth, and burn your mouth, because it's too hot. Not that I ever did that ...
Tuesday, March 08, 2011
Moving glassfish install
When I setup a new server virtual machine it's not unusual for me to install something in one place, then decide later that I don't like that layout, and start moving directories around. That almost always causes me trouble, and I ran into problems today when I moved a working glassfish install from /A to /B - after the move glassfish hung on startup. Fortunately, I was able to figure it out. Here's the trick if there are any other frickjacks out there that also like to pointlessly make things hard for themselves - just erase the felix osgi bundle cache files under glassfish/domains/domain1/osgi-cache/felix/. Those files cache the path to osgi bundle jars at the time of the last glassfish startup.
Sunday, March 06, 2011
little plans
Last week I updated the littleware project site with a fresh binary code drop - including the first little distro zip bundle download. The little distro unzips into littleware/client, littleware/server, and littleware/webapp folders. The server runs an embedded derby (javadb) database and exports littleware's API services via RMI to standalone and web clients. There are more details on the getting started page.
C:\Users\pasquini\Apps\littleware\server\bin > .\littleServer.bat Mar 5, 2011 2:56:10 PM littleware.base.DynamicEnum registerMemberIfNecessary FINE: Registering new new DynamicEnum type: littleware.asset.AssetType Mar 5, 2011 2:56:11 PM littleware.base.DynamicEnum registerMemberIfNecessary FINE: Registering new new DynamicEnum type: littleware.security.auth.ServiceType Mar 5, 2011 2:56:11 PM littleware.bootstrap.AbstractLittleBootstrap bootstrap FINE: Check bootstrap module: littleware.apps.filebucket.server.BucketServerModule Mar 5, 2011 2:56:11 PM littleware.bootstrap.AbstractLittleBootstrap bootstrap FINE: Check bootstrap module: littleware.apps.tracker.server.TrackerServerModule Mar 5, 2011 2:56:11 PM littleware.bootstrap.AbstractLittleBootstrap bootstrap FINE: Check bootstrap module: littleware.bootstrap.server.AssetServerModule Mar 5, 2011 2:56:11 PM littleware.bootstrap.AbstractLittleBootstrap bootstrap FINE: Check bootstrap module: littleware.bootstrap.server.SimpleServerBuilder$Bootstrap$1 Mar 5, 2011 2:56:11 PM littleware.bootstrap.server.AssetServerModule configure INFO: Configuring JPA in standalone (hibernate) mode ... Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadProperties FINE: Attempting to load properties for: littleware.properties, true Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadProperties FINE: Loaded props: 2 Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadPropsFromFile INFO: Loading config\littleware.properties Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadProperties FINE: Attempting to load properties for: littleware_jdbc.properties, true Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadProperties FINE: Loaded props: 2 Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadPropsFromFile INFO: Loading config\littleware_jdbc.properties Mar 5, 2011 2:56:11 PM littleware.db.DbGuice bindDataSource INFO: Binding DataSource datasource.littleware to jdbc:derby:littleware Mar 5, 2011 2:56:11 PM littleware.asset.server.db.jpa.AbstractGuice configure FINE: Configuring JPA database access Mar 5, 2011 2:56:11 PM littleware.base.PropertiesLoader loadProperties FINE: Attempting to load properties for: littleware.properties, false Mar 5, 2011 2:56:12 PM littleware.base.PropertiesLoader loadProperties FINE: Attempting to load properties for: littleware.properties, false 15 [main] INFO org.hibernate.cfg.annotations.Version - Hibernate Annotations 3.5.0-Final 37 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.5.0-Final 39 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found 44 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist 52 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling 183 [main] INFO org.hibernate.annotations.common.Version - Hibernate Commons Annotations 3.2.0.Final 202 [main] INFO org.hibernate.ejb.Version - Hibernate EntityManager 3.5.0-Final 316 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: littleware.asset.server.db.jpa .AssetEntity 376 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity littleware.asset.server.db.jpa.AssetEntity on t able asset 468 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: littleware.asset.server.db.jpa .AssetAttribute 469 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity littleware.asset.server.db.jpa.AssetAttribute o n table asset_attr 480 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: littleware.asset.server.db.jpa .AssetDate 481 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity littleware.asset.server.db.jpa.AssetDate on tab le asset_date 484 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: littleware.asset.server.db.jpa .AssetLink 488 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity littleware.asset.server.db.jpa.AssetLink on tab le asset_link 495 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: littleware.asset.server.db.jpa .TransactionEntity 498 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity littleware.asset.server.db.jpa.TransactionEntit y on table littleTran 506 [main] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: littleware.asset.server.db.jpa .AssetTypeEntity 510 [main] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity littleware.asset.server.db.jpa.AssetTypeEntity on table x_asset_type 586 [main] INFO org.hibernate.cfg.annotations.CollectionBinder - Mapping collection: littleware.asset.server.db.jpa.Asse tEntity.attributeSet -> asset_attr 586 [main] INFO org.hibernate.cfg.annotations.CollectionBinder - Mapping collection: littleware.asset.server.db.jpa.Asse tEntity.dateSet -> asset_date 587 [main] INFO org.hibernate.cfg.annotations.CollectionBinder - Mapping collection: littleware.asset.server.db.jpa.Asse tEntity.linkSet -> asset_link 600 [main] INFO org.hibernate.cfg.AnnotationConfiguration - Hibernate Validator not found: ignoring 675 [main] INFO org.hibernate.cfg.search.HibernateSearchEventListenerRegister - Unable to find org.hibernate.search.even t.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled. 684 [main] INFO org.hibernate.connection.ConnectionProviderFactory - Initializing connection provider: org.hibernate.ejb .connection.InjectedDataSourceConnectionProvider 688 [main] INFO org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider - Using provided datasource 2821 [main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: Apache Derby, version: 10.5.3.0 - (802917) 2821 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC driver: Apache Derby Embedded JDBC Driver, version: 10.5.3.0 - (802917) 2867 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.DerbyDialect 2886 [main] INFO org.hibernate.transaction.TransactionFactoryFactory - Transaction strategy: org.hibernate.transaction.J DBCTransactionFactory 2889 [main] INFO org.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended) 2889 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic flush during beforeCompletion(): disabled 2895 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic session close at end of transaction: disabled 2903 [main] INFO org.hibernate.cfg.SettingsFactory - Scrollable result sets: enabled 2904 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC3 getGeneratedKeys(): disabled 2911 [main] INFO org.hibernate.cfg.SettingsFactory - Connection release mode: auto 2914 [main] INFO org.hibernate.cfg.SettingsFactory - Default batch fetch size: 1 2916 [main] INFO org.hibernate.cfg.SettingsFactory - Generate SQL with comments: disabled 2919 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL updates by primary key: disabled 2923 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL inserts for batching: disabled 2926 [main] INFO org.hibernate.cfg.SettingsFactory - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory 2934 [main] INFO org.hibernate.hql.ast.ASTQueryTranslatorFactory - Using ASTQueryTranslatorFactory 2935 [main] INFO org.hibernate.cfg.SettingsFactory - Query language substitutions: {} 2936 [main] INFO org.hibernate.cfg.SettingsFactory - JPA-QL strict compliance: enabled 2939 [main] INFO org.hibernate.cfg.SettingsFactory - Second-level cache: enabled 2942 [main] INFO org.hibernate.cfg.SettingsFactory - Query cache: disabled 2944 [main] INFO org.hibernate.cfg.SettingsFactory - Cache region factory : org.hibernate.cache.impl.NoCachingRegionFact ory 2947 [main] INFO org.hibernate.cfg.SettingsFactory - Optimize cache for minimal puts: disabled 2949 [main] INFO org.hibernate.cfg.SettingsFactory - Structured second-level cache entries: disabled 2963 [main] INFO org.hibernate.cfg.SettingsFactory - Statistics: disabled 2963 [main] INFO org.hibernate.cfg.SettingsFactory - Deleted entity synthetic identifier rollback: disabled 2965 [main] INFO org.hibernate.cfg.SettingsFactory - Default entity-mode: pojo 2967 [main] INFO org.hibernate.cfg.SettingsFactory - Named query checking : enabled 2968 [main] INFO org.hibernate.cfg.SettingsFactory - Check Nullability in Core (should be disabled when Bean Validation is on): enabled 3054 [main] INFO org.hibernate.impl.SessionFactoryImpl - building session factory 3447 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not binding factory to JNDI, no JNDI name configured Mar 5, 2011 2:56:16 PM littleware.asset.server.db.jpa.SimpleJpaTransaction endDbUpdate FINE: Transaction complete, rollback: false Mar 5, 2011 2:56:17 PM littleware.bootstrap.server.AssetServerModule$Activator start INFO: Looking for RMI registry on port: 1239 Mar 5, 2011 2:56:17 PM littleware.bootstrap.server.AssetServerModule$Activator start INFO: littleware RMI start ok Mar 5, 2011 2:56:17 PM littleware.bootstrap.AbstractLittleBootstrap bootstrap FINE: Waiting for OSGi startup ... Mar 5, 2011 2:56:17 PM littleware.bootstrap.AbstractLittleBootstrap$SetupActivator$1 frameworkEvent FINE: Triggering startup barrier ... < littleware RMI server bootstrap < hit any key to shutdown >
The littleware/client folder currently just holds the lgo (littleware go) tool - which is a launcher for a small suite of littleware.lgo.LgoCommand derived tools that include a Swing-based GUI for browsing the littleware node tree database, and the command line version of the Voyager to Vufind harvester tool we developed at Auburn.
C:\Users\pasquini\Apps\littleware\client\bin > ./lgo.bat help Mar 5, 2011 3:07:40 PM littleware.security.auth.client.ClientLoginModule login INFO: User authenticated: pasquini Mar 5, 2011 3:07:41 PM littleware.base.PropertiesLoader loadPropsFromFile INFO: Loading C:\Users\pasquini\.littleware\edu\auburn\library\voyager\Voyager.properties Mar 5, 2011 3:07:41 PM littleware.db.DbGuice bindDataSource Command use: lgo [+user name] [+mode client|app] [+url http://server:port] [+profile cli|swing] command options +mode [local|client] -- client establishes session with littleware server, default is client +profile [cli|swing] -- specify AppProfile to pass to AppModuleFactory modules at bootup time +user [username] -- user to authenticate as in client mode, defaults to current OS user +url [server-info] -- url specifies host/port information for the littleware server in client mode command.not.found: No help found for command: , available commands: littleware.apps.lgo.GetAssetCommand [get, cat] Get the asset at a given path littleware.apps.lgo.ListChildrenCommand [ls] List the children under a given path littleware.apps.lgo.DeleteAssetCommand [delete, rm] Delete as asset at a given path littleware.apps.lgo.GetByNameCommand [byname, nget] Get the asset at a given path littleware.lgo.XmlEncodeCommand [xencode, xenc] lgo xmlencode littleware.apps.lgo.CreateUserCommand [mkuser, adduser] Create a littleware.USER under /littleware.home/Users/ littleware.apps.lgo.SetImageCommand [setimage] Associate an image with an asset at a given path littleware.lgo.EzHelpCommand [help] lgo help <command> littleware.apps.lgo.GetRootPathCommand [abspath] Convert the given path to a rooted path littleware.apps.lgo.LgoBrowserCommand [browse] launch littleware browser littleware.apps.lgo.CreateFolderCommand [mkdir] Create a littleware.GENERIC asset at a given path littleware.apps.lgo.CreateLockCommand [mklock] Create a littleware.LOCK asset at a given path edu.auburn.library.tool.vygr2vfind.view.V2vLgoCommand [v2v] Copy records from Voyager to a Vufind Solr index
C:\Users\pasquini\Apps\littleware\client\bin > ./lgo.bat help v2v Mar 5, 2011 3:09:45 PM littleware.security.auth.client.ClientLoginModule login INFO: User authenticated: pasquini Mar 5, 2011 3:09:45 PM littleware.base.PropertiesLoader loadPropsFromFile INFO: Loading C:\Users\pasquini\.littleware\edu\auburn\library\voyager\Voyager.properties Mar 5, 2011 3:09:45 PM littleware.db.DbGuice bindDataSource Command use: lgo [+user name] [+mode client|app] [+url http://server:port] [+profile cli|swing] command options +mode [local|client] -- client establishes session with littleware server, default is client +profile [cli|swing] -- specify AppProfile to pass to AppModuleFactory modules at bootup time +user [username] -- user to authenticate as in client mode, defaults to current OS user +url [server-info] -- url specifies host/port information for the littleware server in client mode edu.auburn.library.tool.vygr2vfind.view.V2vLgoCommand: Copy records from Voyager to a Vufind Solr index Copy records from Voyager to a Vufind Solr index. v2v -min [min] -max [max] [-halt [HH:mm] -continue [stubfile]] -solr /path/to/solr/index/biblio v2v -age [age] -solr /path/to/solr/index/biblio v2v -idfile [file full of bib-ids] -solr /path/to/solr/index/biblio Note: loading vufind.properties from DocsFolder/vygr2vfind Note: specify jdbc URL for Voyager database in ~/.littleware/edu/auburn/library/voyager/Voyager.properties - datasource.voyager = jdbc:oracle:thin:user/password@host:port:vger
There's not much useful there really, but it's nice to at least have something to show. The code drop also updates the IVY artifacts and web-start apps hosted by littleware's ivy2maven2 repository as well as the online javadoc and scaladoc API docs.
I was pretty happy with how smoothly the release process went thanks to the ivy build setup. The root build.xml file includes buildAll and buildAndTest rules that a local jenkins continuous integration server executes whenever I push a change to my personal repositories. Everything would have been great if not for the problems that with java 6 update 24 web-start security that plagued me. Ugh!
Anyway, I now need to decide what littleware tasks to tackle next. On the one hand there are several API and infrastructure design flaws that I need to eventually address, but on the other hand it would be good to build out some useful littleware-based applications to demonstrate the systems utility. On a 3rd hand the more application level code I write the more annoying an API-level refactoring will be to propagate, and a 4th hand realizes that application level development is the best way to get ideas for improving an API, and a 5th hand points out that the experience and learning I gain is the main benefit of working on littleware in the first place. I'll probably just continue with the tasks outlined in the current SCRUM sprint, and continue to develop the scala tools in littleware's catalog repository.
The academic library is a terrible market to work for as a library is amazingly cheap, and even if the library had money - it wouldn't want to change anything. A true librarian would turn the clock back to card catalog days in a heart beat. If a librarian ever gets the bomb, then we're all in trouble; he'll blast us back to the stone age smiling ear to ear. These negatives are positives for a loan frickjack that can bundle a suite of open source tools in a cloud-hosted library-in-a-box, and make money charging $200- a month. We'll see what I think next month.
Saturday, March 05, 2011
Chinese breakfast!
It's a rainy day in Auburn. The dogs and I were drenched on our morning walk, and it felt like a good day to cook some breakfast when we got home. Cong you bing (葱油饼 - green onion pancake) is one of the few Chinese dishes I make on a regular basis. Just mix a cup of water with some flour and a little oil and salt to make a dough, split it into 4 parts, roll out, jelly roll with salted diced green onions, stretch out to a pancake, and fry it up. I'm always surprised when something so simple (flour, water, green onions, salt, oil) is so good.
One trick when rolling out the pancake is - don't roll it out much. Pressing too much with a rolling pin on the dough with green onions mixed in squeezes water out of the onions, and the dough turns to mush. Just roll the dough out a little bit with a rolling pin, then pick the bing (pancake) up, and stretch it with your hands - like pizza dough.
The bing is great with a fried egg.
fight the tyranny of basil pesto!
I love pesto, but, frickjack that I am, I always assumed pesto was made with basil, and it's hard to get my hands on a big pile of basil without spending a fortune, so I didn't eat pesto much ... until now! I can't remember how I finally got a clue, but I think I was wistfully looking over the ingredients of some pesto jar at the grocery, and I saw spinach instead of basil. A freakin' light bulb lit up above my head (very low watt is all my head can manage), and I realized I no longer had to be a slave to basil - that tyrant!
Anyway, spinach is plentiful this time of year at the grocery, and it makes great pesto. Just mince up the spinach, then blend with olive oil, parmesan, salt, pepper, - pine nuts if you got 'em; toss with pasta ... oh so good!
Friday, March 04, 2011
Silly user, tricks are for programmers!
At the one and (thankfully) only systems department meeting I attended at the library over a month ago there was a short conversation about how systems installed an obscure version of perl (not ActiveState or Cygwin) on a cataloging department Windows XP box, so a cataloger could run a magic perl script handed down from the ages. The magic perl script processed a file of MARC records from our "books on order" vendor to update each record with the correct Auburn location code for where the record's book would be shelved.
I volunteered at the time that Jack or I could whip out a java or C# program to replace the perl script. I was warned that this was complex code that tied together purchase orders, bib, holdings, and item records. I had to see this amazing piece of work!
When I finally got around to looking at the perl script and a sample input I found about 50 lines of perl and a simple file full of BIB records. I knew it!
Anyway, I wrote a little webstart app (MarcConvert - more info here) that could probably replace the perl script. MarcConvert reads an input file of records in MARC or MARCXML format, and writes the records back out to an output file in MARC, MARCXML, or SIMPLE (readable) format while optionally applying a "location filter". I'll e-mail a few people at the library to see if they want to give it a try. MarcConvert should be useful in a few ways.
- First, MarcConvert can transform a file of MARC records to a readable format, so a cataloger can take a quick look at what is actually in the file.
- Next, if a cataloger wants to make a simple change to a file of MARC records, then he/she can just convert the file to XML, make the changes to the XML in a standard editor, then convert the XML file back to MARC.
- Finally, a cataloger can apply the "location filter" to a MARC file without installing perl.
Thursday, March 03, 2011
jre6 update 24 sucks
It's always annoying when something outside my control changes, and breaks my code. I received an e-mail the other day from my former coworker at the library reporting that one of the little tools I wrote stopped working on some machines. I suggested a few things to try, but I assumed that something ridiculous happened at the library, and they would fix it up. By the end of the day they let me know that web start with the new java 6 update 24 threw a SecurityException when launching my tool.
I at first could not reproduce the problem running a copy of the library tools, but that was just because I was running a pre-update version of java. My Windows 7 laptop has 3 java installs - a 64 bit jre, a 64 bit jdk, and a 32 bit jre - only the 32 bit jre has update 24. My netbeans developer environment and powershell command line both point at the pre-update jdk, but Chrome's java plugin runs the 32 bit jre with update 24. I was already annoyed at this point. Ugh.
Google helped me narrow the problem down to web-start's interaction with the Apache felix OSGi implementation that I use. I wrote up a little test case (below), and submited a ticket to Oracle's java team.
package littleware.demo; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URL; import java.net.URLClassLoader; import java.sql.Connection; import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import org.apache.felix.framework.Felix; public class JavaToy { private static final Logger log = Logger.getLogger( JavaToy.class.getName() ); public static class AppRunner implements Runnable { public void run() { final StringWriter swriter = new StringWriter(); final PrintWriter pwriter = new PrintWriter( swriter ); pwriter.append( "Class path: " ).append( System.getProperty( "java.class.path" ) ).append( "\n\n-------------------------\n" ); final ClassLoader classLoader = this.getClass().getClassLoader(); //Thread.currentThread().getContextClassLoader(); if ( classLoader instanceof URLClassLoader ) { pwriter.append( "URLClassLoader:\n" ); for ( URL url : ((URLClassLoader) classLoader).getURLs() ) { pwriter.append( url.toString() ).append( "\n" ); } pwriter.append( "\n--------------------------------\n" ); } try { Class.forName( "bogus.DoesNotExist" ); pwriter.append( "No exception thrown on bogus class load\n" ); } catch ( Exception ex ) { pwriter.append( "Caught exception loading bogus class: " ).append( ex.toString() ).append( "\n" ); ex.printStackTrace(pwriter); } pwriter.flush(); final JFrame jframe = new JFrame( "Webstart test" ); final JTextArea jtext = new JTextArea( swriter.toString(), 20, 40 ); jframe.add( new JScrollPane( jtext ) ); jframe.pack(); jframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); jframe.setVisible(true); } } public static void main( String[] args ) { try { log.log( Level.INFO, "Launching felix!" ); (new Felix(new HashMap<String, Object>())).start(); Thread.sleep( 2000 ); } catch (Exception ex) { log.log(Level.SEVERE, "Caught exception", ex); System.exit(0); } SwingUtilities.invokeLater( new AppRunner() ); } }
Web-start with a pre-update-24 jre throws the expected ClassNotFoundException and yields this result:
Class path: C:\Program Files\Java\jre6\lib\deploy.jar ------------------------- URLClassLoader: file:/C:/Users/pasquini/Documents/Code/JavaToy/dist/JavaToy.jar file:/C:/Users/pasquini/Documents/Code/JavaToy/dist/lib/felix-2.0.4.jar http://felix.extensions:9/ -------------------------------- Caught exception loading bogus class: java.lang.ClassNotFoundException: bogus.DoesNotExist java.lang.ClassNotFoundException: bogus.DoesNotExist ...
An update-24 jre throws a troublesome SecurityException with this result:
Class path: C:\\Program Files (x86)\\Java\\jre6\\lib\\deploy.jar ------------------------- URLClassLoader: file:/C:/Users/pasquini/Documents/Code/JavaToy/dist/JavaToy.jar file:/C:/Users/pasquini/Documents/Code/JavaToy/dist/lib/felix-2.0.4.jar http://felix.extensions:9/ -------------------------------- Caught exception loading bogus class: java.lang.SecurityException: Permission denied: http://felix.extensions:9/bogus/DoesNotExist.class java.lang.SecurityException: Permission denied: http://felix.extensions:9/bogus/DoesNotExist.class ...
The bug robot sent me a nice response for my trouble.
Dear Java Developer,
Thank you for your interest in improving the quality of Java Technology.
Your report has been assigned an internal review ID of 1990127, which is NOT visible on the Sun Developer Network (SDN).
Please be aware that the large volume of reports we receive sometimes prevents us from responding individually to each message.
If the information is determined to be a new Bug or RFE, or a duplicate of a known Bug or RFE, you will receive a followup email containing a seven digit bug number. You may search for, view, or vote for this bug in the Bug Database at http://bugs.sun.com/.
If you just reported an issue that could have a major impact on your project and require a timely response, please consider purchasing one of the support offerings described at http://developers.sun.com/services/.
Bla bla bla ...
Fortunately, the felix user mailing list had a thread on the issue, and some cool Karl Pauls guy pointed me in the right direction to throw together a little patch (see below) that got me back in business.
Hurray for open source! Of course now its 3 days of head banging, trying random hacks, and considering dropping felix or web-start later. I'm too relieved to be bitter! Oracle actually closed a related ticket as "Not a bug", because the http://... URL in the ClassLoader path violates the web-start single-origin policy - now more strictly enforced in update 24. That looks like some lazy Oracle developer dodging work to me, because a signed web-start app granted all-permissions can do almost anything (open network ports, erase the disk, write and launch a program, whatever), so what's the deal with the SecurityException scanning the class path ?
Re: Java 6 Update 24 breaks Felix Reuben Pasquini Thu, 03 Mar 2011 10:00:46 -0800 Here's an ExtensionManager patch that got me back in business with webstart (don't know what's up with the sun.org.moz... import in Felix.java): --------------------- C:\Users\pasquini\Documents\Code\felix-framework > svn diff -x -w Index: src/main/java/org/apache/felix/framework/Felix.java =================================================================== --- src/main/java/org/apache/felix/framework/Felix.java (revision 1076687) +++ src/main/java/org/apache/felix/framework/Felix.java (working copy) @@ -75,8 +75,8 @@ import org.osgi.framework.hooks.service.ListenerHook; import org.osgi.service.packageadmin.ExportedPackage; import org.osgi.service.startlevel.StartLevel; -import sun.org.mozilla.javascript.internal.UintMap; + public class Felix extends BundleImpl implements Framework { // The secure action used to do privileged calls Index: src/main/java/org/apache/felix/framework/ExtensionManager.java =================================================================== --- src/main/java/org/apache/felix/framework/ExtensionManager.java (revision 1076687) +++ src/main/java/org/apache/felix/framework/ExtensionManager.java (working copy) @@ -87,6 +87,10 @@ static { + // Allow system-property based disable of ExtensionManager. + // Adding http://felix.extension:9 to the class path causes problems + // in webstart which enforces a "single origin" policy as of jre 6 update 24. + if( System.getProperty( "felix.extensions.enabled", "true" ).equalsIgnoreCase( "true" ) ) { // pre-init the url sub-system as otherwise we don't work on gnu/classpath ExtensionManager extensionManager = new ExtensionManager(); try @@ -113,7 +117,10 @@ extensionManager = null; } m_extensionManager = extensionManager; + } else { + m_extensionManager = null; } + } private final Logger m_logger; private final Map m_headerMap = new StringMap(false); --------------------------- Then add <property name="felix.extensions.enabled" value="false" /> in the .jnlp <resources> block, and I'm back in business. Thanks for pointing me in the right direction. Hope something like this makes it into the next release ... ? Cheers, Reuben On Thu, Mar 3, 2011 at 10:52 AM, Reuben Pasquini <reu...@frickjack.com>wrote: > I agree it sounds like an Oracle bug, but a workaround would be great. > > A config parameter that disables extension bundles works for me too. > > I embed felix in a very limitted way to manage the startup/shutdown > lifecycle > > via BundleActivators, so I don't think my apps will miss the extension > bundles. > > Let me know when you have a patch checked in, and I'll give it a try ... > > or if you think it's a small change, then point me at the right part of the > felix > > repo, and I'll try to throw together a patch for you. > > Thanks for the help! > > > > Cheers, > > Reuben > > On Thu, Mar 3, 2011 at 3:16 AM, Karl Pauls <karlpa...@gmail.com> wrote: > >> On Thu, Mar 3, 2011 at 10:08 AM, Bauersachs Ingo >> <ingo.bauersa...@fhnw.ch> wrote: >> >> Problem is this doesn't make sense to me as the app has allpermission >> >> (or sets the security manager to null even). Why enforce this then? It >> >> sounds like a bug (and there are several at oracle by now). Lets see >> >> what they do >> > >> > Indeed, this makes no sense. >> > >> >> I'll try to find a workaround on the weekend and if >> >> not, I'll probably add a property to disable extension bundles (which >> >> would make the url go away - only extension bundles will not work). >> > >> > 6u24 is out and I needed a workaround fast. Changing the extension url >> from http to file seems to satisfy the same origin policy. If my change >> doesn't cause other side-effects it might even be a permanent solution. (I >> have far to less experience with OSGi/Felix to really comment on this) >> >> If it works for you it is ok for now - it is not the permanent >> solution as there will be other issues (there is a reason we do what >> we do there - related to extension bundles). But if i can't find >> something better the solution will be close (i.e., provide a way to >> disable extension bundles -> don't register this url at all). >> >> regards, >> >> Karl >> >> >> > Regards, >> > Ingo