Only a few people reacted, plus there where some comments on IRC. Based on
those I made some changes. I'll make some comments on my original post. The
VOTING will probably start tomorrow.
Michiel Meeuwissen wrote:
> The idea is to delegate all this stuff to one new class. This class I called
> 'ResourceLoader' and
> extends from ClassLoader. You load a resource from it approximately like this:
>
> InputStream loggingConfiguration =
> ResourceLoader.getRoot().getResourceAsStream("/log/log.xml");
I renamed 'getRoot' to 'getConfigurationRoot()', and I also added a
'getWebRoot()'. The 'webroot' resource-loader is very similar to the
configuration resource-loader, but you can load resources with it which are
not actual MMBase configuration. I used it e.g. in my adaptation of
URIResolver to make Editwizards work in a war too.
>
> This code will first look for a file WEB-INF/config/log/log.xml and if not exists
> then for the file
> WEB-INF/classes/mmbase/config/log/log.xml and if that too does not exist, then for
> the resource
> mmbase/config/log/log.xml.
>
> The location of this resource-base is open for discussion. I tried to go for a short
> path, so e.g. I
> let away the 'org' (these are not java classes any way).
>
> Also something must be thought of for loading modules and builders as a resource.
>
> I came up with this:
>
>
> Set builders = builderLoader.getSubResources(ResourceLoader.XML_PATTERN, true/*
> recursive*/, ResourceLoader.INDEX);
> log.info("Loading " + builders);
> Iterator i = builders.iterator();
> while (i.hasNext()) {
>
> So, besides all files of WEB-INF/config/builders it also loads all builders
> mentioned in the
> resource ResourceLoader.INDEX (which I now set to "INDEX", also open to discussion).
This stuff with 'INDEX' is actually a lot less needed then I originally
thought because ServletContext allows for iterating through its resources
too. It is still supported though, for when you want to put things in a jar
in WEB-INF/lib or so. It is implicit now, though, since I don't think you
want to be bothered by it.
The method is called now getResourcePaths (as in ServletContext).
There is also a version to search for 'directories' only.
> Impact
>
> - Most configuration code will need a simple rewrite. MMBase.getConfigPath() will
> no longer give an
> absolute path. If this last thing is seen as a problem, it could merely be
> deprecated. and a
> similar functions could be added for use with ResourceLoader. Then at least old
> code using
> getConfigPath will remain to work (but of course you cannot run a war with that
> code).
>
> Some configuration code will be quite simplified.
I decided to not change the behaviour of getConfigPath. It will still return
a file name if that is possible. I will deprecate it though and remove all
uses of it in MMBase code. Also the 'String' based constructors of
XMLBasicReaders will be deprecated. I figured you can as well do something
like new
XMLBasicReader(ResourceLoader.getConfigurationRoot().getInputSource("myfile.xml"));
or so. That means that behaviour of the constructors of XMLBasicReaders will
not change and possible third party extensions will remain working as they
did.
>
> Remaining problems:
>
> - Reading of web.xml of MMBaseServlet will not be possible any-more. It currently
> gives an
> stack-trace in my log, (but mmbase starts oterwise correctly). It is only used
> for that silly
> function to servlet mapping. I'm sure we can come up with some solution (if
> needed, by a copy of
> web.xml under WEB-INF/classes...)
Fixed by ServletContext.getResource.
>
> - File-watching. I plan to implement ResourceWatcher based on FileWatcher. This
> will make sure that
> the onChange are only called when really necessary. (e.g. if
> WEB-INF/classes/mmbase/config/log/log.xml changes and WEB-INF/config/log/log.xml
> exists, this
> event must be ignored). I don't foresee difficulties with this.
I have implemented this too, it works fine.
Furthermore I added a few important improvements:
1. Besides a resource loader, the class will also be a resource _writer_ (as
requested by Daniel)
It works quite easily. You can simply request an OutputStream rather then
an InputStream from the URLConnection object, and there are some helper
mthods for that like: createResourceAsStream (vs getResourceAsStream) and
getWriter (vs getReader).
Whether a resource is read-only can be checked by
URLConnection.getDoOutput(). (It is AFAIK e.g. not possible to write new
files loadable by ServletContext, while in a war you depend on that. But
at least you can check it beforehand by this.)
2. I implemented a 'resources' builder. If this builder is installed, you
can always store a resource, because it simply stores it in this
dedicated builder. This can come in handy if you run in a packed war or
on a read-only filesystem.
So the loading mechanism also considers this builder now. The builder is
optionial, so we can opt to not defaultly install it.
The ResourceWatcher is a MMBaseObserver too, so it works as well if you
change a node.
ResourceWatcher issues warnings if you cange a resource which is
'shadowed' by another one. E.g. if a file changes, while such a node
exists already.
3. I implemented a 'resourcedit' jsp, which is a generic MMBase resource
search and edit tool. I would suggest to add it to the admin-pages, but
for the moment it is mainly a test and demonstration for ResourceLoader
itself.
I will post a new war.
This is a already link to an installed resourceedit.jsp:
http://mihxil.komputilo.org/mm18/mmbase/admin/?category=admin&subcategory=resourceedit
(with the usual name/password).
This server runs on an 'unpacked' war (in server.xml unpackWARs="false"
and: <Context path="/mm18" docBase="/home/mmbase/mmbase.war" />
The source-code of some files of interest (like resourceedit.jsp) can be
found in speeltuin/mihxil/resourceloader).
Michiel
--
Michiel Meeuwissen mihxil'
Mediacentrum 140 H'sum [] ()
+31 (0)35 6772979 nl_NL eo_XX en_US