You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Jorg Heymans <jh...@domek.be> on 2004/11/08 09:17:25 UTC
[rfc] commons fileupload replacement
Hi,
I have provided a patch [1] that removes cocoon's multipart upload
parser with one based on commons-fileupload.
My approach breaks existing client code however, so Antonio suggested to
get a few more opinions before continueing.
1) Part, PartOnDisk, PartInMemory are not necessary anymore. They are
replaced by the FileItem interface of commons fileupload. It should be
doable to wrap the FileItems in a Part class as suggested by Reinhard
(with a slight change to the contract, see [1] ) .
2) web.xml parameter "overwrite-uploads" is gone. Instead, we need a
parameter like "where-to-store-uploads" with values "disk" or "memory".
In addition to this (not included in the patch) commons-fileupload
offers a "threshold" for memory based storage, files larger than the
threshold will get written to disk anyway - we don't *have* to use this
however.
3) There is no replacement for getHeaders() in Part.java.
The nice thing to do would be to deprecate the Part classes, and wrap
the FileItem interface inside Part for 2.1.6. , remove Part in 2.1.7?
Or is 2.1.6 too soon for this?
Thoughts?
Jorg
[1] http://nagoya.apache.org/bugzilla/show_bug.cgi?id=32102
Re: [rfc] commons fileupload replacement
Posted by Sylvain Wallez <sy...@apache.org>.
Jorg Heymans wrote:
> Hi,
>
> I have provided a patch [1] that removes cocoon's multipart upload
> parser with one based on commons-fileupload.
>
> My approach breaks existing client code however, so Antonio suggested to
> get a few more opinions before continueing.
>
> 1) Part, PartOnDisk, PartInMemory are not necessary anymore. They are
> replaced by the FileItem interface of commons fileupload. It should be
> doable to wrap the FileItems in a Part class as suggested by Reinhard
> (with a slight change to the contract, see [1] ) .
PartOnDisk and PartInMemory are particular implementations of the
general Part contract. An application can rely on obtaining a Part, but
cannot expect to have a particular implementation of it if it aims to be
truly independent of the deployment environment.
However, testing for "instanceof PartOnDisk" may allow for performance
improvements by allowing the application to move around a file rather
than reading it and writing it in another location. Commons upload takes
a different approach for this with the "write(File)" method that
abstracts this. We could add this convenience method to Part to avoid
the above-mentioned "instanceof" test.
So my opinion is that we should have a "CommonsUploadPart" that
implements the original Part contract. Especially important is the
"disposeWithRequest" stuff that is used by CForms: the default is to
automatically trash uploaded content when a request ends, but the CForms
upload widget can "detach" a Part from the requests so that uploaded
content survives across continuation calls.
> 2) web.xml parameter "overwrite-uploads" is gone. Instead, we need a
> parameter like "where-to-store-uploads" with values "disk" or "memory".
> In addition to this (not included in the patch) commons-fileupload
> offers a "threshold" for memory based storage, files larger than the
> threshold will get written to disk anyway - we don't *have* to use this
> however.
>
> 3) There is no replacement for getHeaders() in Part.java.
Mmmh... let's keep it and map it the headers provided as methods in
FileItem (content-type, length, etc).
> The nice thing to do would be to deprecate the Part classes, and wrap
> the FileItem interface inside Part for 2.1.6. , remove Part in 2.1.7?
Rather than deprecating Part, we should maybe move it to
o.a.c.environment, as multipart requests can exist in environments other
than servlets (i.e. SMTP).
Sylvain
--
Sylvain Wallez Anyware Technologies
http://www.apache.org/~sylvain http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Re: [rfc] commons fileupload replacement
Posted by Geoff Howard <ge...@gmail.com>.
On Mon, 8 Nov 2004 14:16:45 -0600 (CST), Luigi Bai
<lp...@focalpoint.com> wrote:
>
> On Mon, 8 Nov 2004, Geoff Howard wrote:
>
> > On Mon, 8 Nov 2004 08:20:56 -0600 (CST), Luigi Bai
> > <lp...@focalpoint.com> wrote:
...
> I read your reference and Stefano's proposal.
Excellent.
> I agree with the concept of
> having request interceptors, but I am not sure I agree with his syntactic
> proposal. In particular, it requires the creation of yet another type of
> sitemap component, meaning that it is heavily integrated into the Cocoon
> core. Why is that necessary?
Well, not really. While sitemap statements are often also components
I don't think they always are or need to be IIUC. At the end of the
day, they are nodes recognized by the tree processor. We have no
construct (including actions) which allow the raw request object
(besides attributes) to be modified, or re-interpreted in any way. To
grant this power to existing sitemap elements would be dangerous (in
the sense of ripe for abuse or confusion).
> Despite your characterization of Actions (below), I think they are a valid
> method for providing "cross cutting" functionality in a lightweight
> fashion. They don't require a user to implement PipelineNodes and all that
> jazz. And if the functionality proves to be stable and useful, then you
> can "harden" it into more formal syntax.
To clarify, once the proposed "adapt request" support exists, we would
almost certainly bundle and configure by default the very few
capabilities which would require it - multipart file handling would
almost certainly be part of this. So, users wouldn't have to
implement PipelineNodes unless they had some unique new requirement or
wanted to write an alternative. Further, this would likely be a
fairly simple contract anyway.
> The problem with Actions is that while they're flexible and lightweight,
> they cannot have access to all the parts of a pipeline that a Node can. I
> lean toward allowing an Action to tell the Environment to replace its
> Request object, allowing it to do the SOAP/DAV/upload processing in the
> Action. Yes, this can allow people to shoot themselves in the foot. But I
> think the benefits outweigh the risk.
:) Most would say that the problem is that Actions have access to too much!
I think though that we're just on some semantics based on the way you
have mentally categorized actions.
Again, the problem as I understand it with actions is that they:
1) Can perform back-end "actions".
2) Can decide between alternate paths/steps in the sitemap.
3) Can also completely redirect the request
4) Can also return values back to the sitemap which can trigger later
decision points using any other sitemap directive.
None of these are bad in them selves - it's the mixing of all of them.
Adding the ability to modify the way in which the request is made
available to later steps in processing would only muddy things
further.
> Otherwise, a valid "hack" would be to have an Action that processed the
> multipart stream (like StreamGenerator) but which put its Parts under the
> RequestAttributes (the only part of the Request it's allowed to
> manipulate). Downstream components would then have to get the parts from
> the Attributes, not Params, but that'd be a contract to observe, nothing
> special.
I think this is why this needs to be handled deeper in the core (the
request adapting, not necessarily the multipart parsing). And to
reiterate, would then not need to be re-done by people (just as it is
not now re-done by everyone needing to use multipart uploads) but
rather just utilized.
Anyone care to chip in with a path forward? Can we do "adapt-request" now?
Geoff
> >> By the way, I'm not clear on why Multipart support can't be implemented as
> >> an Action? If it's an Action, then it's clearly pluggable, and all this
> >> goes away. Why is it so early in the process, hard coded in CocoonServlet?
> >
> > - Actions were a muddy concept that have been or can be at least
> > partially if not fully replaced by other items.
>
Re: [rfc] commons fileupload replacement
Posted by Luigi Bai <lp...@focalpoint.com>.
On Mon, 8 Nov 2004, Geoff Howard wrote:
> On Mon, 8 Nov 2004 08:20:56 -0600 (CST), Luigi Bai
> <lp...@focalpoint.com> wrote:
>> I'd like to point out that the Multipart support in Cocoon is one of the
>> few things that isn't pluggable or replaceable. I'd like it to be possible
>> to configure web.xml/CocoonServlet to take a class name that implements
>> some MultipartParser interface, and keep Part as an interface (perhaps
>> letting it evolve as different implementations are available).
>
> Some historical/background points (with the caveat that some changes
> have happened due to CForms that I have not paid full attention to):
> - We also have tried to avoid anti-patterns like "over
> componentization" i.e., making things pluggable that really don't need
> to be, which was probably judged to be the case here (though see
> below).
> - There were other grander plans for request handling. In particular,
> see the "Pluggable Request Factories" of Stefano's RT here:
> http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=106131747919501&w=2
> - You'll notice a third point in the RT above: our "pluggable" problem
> extends beyond multipart uploads. It includes things like WebDAV and
> SOAP.
>
I read your reference and Stefano's proposal. I agree with the concept of
having request interceptors, but I am not sure I agree with his syntactic
proposal. In particular, it requires the creation of yet another type of
sitemap component, meaning that it is heavily integrated into the Cocoon
core. Why is that necessary?
Despite your characterization of Actions (below), I think they are a valid
method for providing "cross cutting" functionality in a lightweight
fashion. They don't require a user to implement PipelineNodes and all that
jazz. And if the functionality proves to be stable and useful, then you
can "harden" it into more formal syntax.
The problem with Actions is that while they're flexible and lightweight,
they cannot have access to all the parts of a pipeline that a Node can. I
lean toward allowing an Action to tell the Environment to replace its
Request object, allowing it to do the SOAP/DAV/upload processing in the
Action. Yes, this can allow people to shoot themselves in the foot. But I
think the benefits outweigh the risk.
Otherwise, a valid "hack" would be to have an Action that processed the
multipart stream (like StreamGenerator) but which put its Parts under the
RequestAttributes (the only part of the Request it's allowed to
manipulate). Downstream components would then have to get the parts from
the Attributes, not Params, but that'd be a contract to observe, nothing
special.
>
>> By the way, I'm not clear on why Multipart support can't be implemented as
>> an Action? If it's an Action, then it's clearly pluggable, and all this
>> goes away. Why is it so early in the process, hard coded in CocoonServlet?
>
> - Actions were a muddy concept that have been or can be at least
> partially if not fully replaced by other items.
Re: [rfc] commons fileupload replacement
Posted by Luigi Bai <lp...@focalpoint.com>.
On Mon, 8 Nov 2004, Geoff Howard wrote:
> On Mon, 8 Nov 2004 08:20:56 -0600 (CST), Luigi Bai
> <lp...@focalpoint.com> wrote:
>> I'd like to point out that the Multipart support in Cocoon is one of the
>> few things that isn't pluggable or replaceable. I'd like it to be possible
>> to configure web.xml/CocoonServlet to take a class name that implements
>> some MultipartParser interface, and keep Part as an interface (perhaps
>> letting it evolve as different implementations are available).
>
> Some historical/background points (with the caveat that some changes
> have happened due to CForms that I have not paid full attention to):
> - We also have tried to avoid anti-patterns like "over
> componentization" i.e., making things pluggable that really don't need
> to be, which was probably judged to be the case here (though see
> below).
> - There were other grander plans for request handling. In particular,
> see the "Pluggable Request Factories" of Stefano's RT here:
> http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=106131747919501&w=2
> - You'll notice a third point in the RT above: our "pluggable" problem
> extends beyond multipart uploads. It includes things like WebDAV and
> SOAP.
>
Good points.
>> Keeping the integration at the level of Interface means we don't run into
>> the same kind of rigamarole that is going on with ECM etc.
>
> True, although another major lesson learned from ECM was that external
> communities can also let you down. The last time I monitored the
> commons list, I didn't get warm fuzzies about the politics and health
> there, for what that's worth.
>
That's precisely what I mean...
>> By the way, I'm not clear on why Multipart support can't be implemented as
>> an Action? If it's an Action, then it's clearly pluggable, and all this
>> goes away. Why is it so early in the process, hard coded in CocoonServlet?
>
> - Actions were a muddy concept that have been or can be at least
> partially if not fully replaced by other items.
> - Why so early in the process is another good question. Two reasons I
> remember are:
> 1) Cocoon is not only a CocoonServlet but also runs in different
> environments (Command Line for example) where multipart requests do
> not have exact parallel if they exist at all. We have tried to avoid
> dependencies on Servlet specific APIs in part due to this issue.
> Combined with the fact that Cocoon's uri abstraction (all uris are
> mapped to the CocoonServlet, making total control in sitemap possible)
> makes it possible that relying on Commons upload may turn out to be a
> bad idea in the end: they do not have the same complexity of concerns.
> In fact, they've had some recent refactoring there to accomodate
> portlet environments. If someone can give an analysis of whether this
> helps us or hurts us with respect to our complex needs, that would be
> a big plus.
> 2) The cocoon framework as many frameworks pre-parses the request to
> make all parameters available to the pipeline semantics. The plan of
> adaptRequest was to allow this to take place for most parameters up
> front, but the multipart bits later. The work to do this was never
> done.
>
Ah, a generic request adaptation framework.
> Any patch that addresses all these concerns would probably get some
> good attention.
>
> Short of that, a patch that provides backwards compatibility by
> wrapping the commons library is next best in my opinion. Short of
> full pluggable request adaptors, encapsulation is as good as
> configurability in this case IMO. In this case, I think people will
> be fine with one solution for the project, as long as it's easy to rip
> out and replace if necessary.
>
That's why I'm suggesting having an Interface and an init-param that
allows you to load a class implementing that Interface. Right now if
multipart is not fixed/patched (see below) in 2.1.6 then we need to
"carry" this patch forward to the new source tree if/when we use 2.1.6.
This is in contrast to almost anything else (Generators, Serializers,
Transformers) that we just fork off into our own namespace, patch or
extend, and pull out of our own jar at run time.
I suppose we could fork the whole CocoonServlet.
> Earlier someone noted the comment in the code about multipart/mixed.
> I am not an expert here, but when I looked into this some time ago, it
> was not supported by browsers. We do support multiple files per form
> using multiple input elements, so full conformance with the spec would
> be academic. Am I wrong here?
>
> Geoff
>
Not academic; see http://issues.apache.org/bugzilla/show_bug.cgi?id=31067
We are using a script with "curl" to upload multiple files on one input
element (this is for a list of images to a slide show style viewer).
Re: [rfc] commons fileupload replacement
Posted by Geoff Howard <ge...@gmail.com>.
On Mon, 8 Nov 2004 08:20:56 -0600 (CST), Luigi Bai
<lp...@focalpoint.com> wrote:
> I'd like to point out that the Multipart support in Cocoon is one of the
> few things that isn't pluggable or replaceable. I'd like it to be possible
> to configure web.xml/CocoonServlet to take a class name that implements
> some MultipartParser interface, and keep Part as an interface (perhaps
> letting it evolve as different implementations are available).
Some historical/background points (with the caveat that some changes
have happened due to CForms that I have not paid full attention to):
- We also have tried to avoid anti-patterns like "over
componentization" i.e., making things pluggable that really don't need
to be, which was probably judged to be the case here (though see
below).
- There were other grander plans for request handling. In particular,
see the "Pluggable Request Factories" of Stefano's RT here:
http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=106131747919501&w=2
- You'll notice a third point in the RT above: our "pluggable" problem
extends beyond multipart uploads. It includes things like WebDAV and
SOAP.
> Keeping the integration at the level of Interface means we don't run into
> the same kind of rigamarole that is going on with ECM etc.
True, although another major lesson learned from ECM was that external
communities can also let you down. The last time I monitored the
commons list, I didn't get warm fuzzies about the politics and health
there, for what that's worth.
> By the way, I'm not clear on why Multipart support can't be implemented as
> an Action? If it's an Action, then it's clearly pluggable, and all this
> goes away. Why is it so early in the process, hard coded in CocoonServlet?
- Actions were a muddy concept that have been or can be at least
partially if not fully replaced by other items.
- Why so early in the process is another good question. Two reasons I
remember are:
1) Cocoon is not only a CocoonServlet but also runs in different
environments (Command Line for example) where multipart requests do
not have exact parallel if they exist at all. We have tried to avoid
dependencies on Servlet specific APIs in part due to this issue.
Combined with the fact that Cocoon's uri abstraction (all uris are
mapped to the CocoonServlet, making total control in sitemap possible)
makes it possible that relying on Commons upload may turn out to be a
bad idea in the end: they do not have the same complexity of concerns.
In fact, they've had some recent refactoring there to accomodate
portlet environments. If someone can give an analysis of whether this
helps us or hurts us with respect to our complex needs, that would be
a big plus.
2) The cocoon framework as many frameworks pre-parses the request to
make all parameters available to the pipeline semantics. The plan of
adaptRequest was to allow this to take place for most parameters up
front, but the multipart bits later. The work to do this was never
done.
Any patch that addresses all these concerns would probably get some
good attention.
Short of that, a patch that provides backwards compatibility by
wrapping the commons library is next best in my opinion. Short of
full pluggable request adaptors, encapsulation is as good as
configurability in this case IMO. In this case, I think people will
be fine with one solution for the project, as long as it's easy to rip
out and replace if necessary.
A third option: The entire project at Commons as far as I can see is
about 15 classes and hasn't had a release in almost a year and a half.
(I'm guessing this is because the RFC for file uploads has not
changed and probably isn't expected to?). In this case, I think it's
entirely reasonable to just fix our existing implementation rather
than depend on another project.
Earlier someone noted the comment in the code about multipart/mixed.
I am not an expert here, but when I looked into this some time ago, it
was not supported by browsers. We do support multiple files per form
using multiple input elements, so full conformance with the spec would
be academic. Am I wrong here?
Geoff
> On Mon, 8 Nov 2004, Jorg Heymans wrote:
>
> >>
> >> Is posible to add support for both at the same time? If this is possible,
> >> then we can add it in 2.1.6 and deprecate the old approach.
> >
> > so you mean actually wrap a FileItem inside PartOnDisk and PartInMemory,
> > instead of creating our own FileItemPart subclassed from Part? Yes that would
> > work as well give or take a few bodges.
> >
> > Regards
> > Jorg
Re: [rfc] commons fileupload replacement
Posted by Luigi Bai <lp...@focalpoint.com>.
On Mon, 8 Nov 2004, Jorg Heymans wrote:
>
>
> Luigi Bai wrote:
>> Hi,
>>
>> I'd like to point out that the Multipart support in Cocoon is one of the
>> few things that isn't pluggable or replaceable. I'd like it to be possible
>> to configure web.xml/CocoonServlet to take a class name that implements
>> some MultipartParser interface, and keep Part as an interface (perhaps
>> letting it evolve as different implementations are available).
> Point taken, but how many different implementations does a multipartparser
> really need ? Commons-fileupload is RFC 1867 compliant, has disk and memory
> based storage and is a "known and trusted" commons library.
>
Not many different ones are "needed". However, the current one is buggy,
and it would have been much easier to replace for an end-user if it
werent' so heavily embedded into the Servlet. If some problem turns up in
commons-upload, or in your code, as a non-commit level end user I'm back
in the same boat; I have to rewrite CocoonServlet to just fix it or hack
it out. I *could* then make a PATCH to fix it, which would be forever
ignored in Bugzilla. :-)
I find it hard to believe that we just saw Avalon/Excalibur/etc. implode,
Carsten is rewriting core to get around it - I don't think it's reasonable
to hard code another dependency at the class level. Since you're rewriting
it anyway, how hard is it to abstract one level out?
>>
>> Keeping the integration at the level of Interface means we don't run into
>> the same kind of rigamarole that is going on with ECM etc.
> True, but we're talking about 5 isolated classes that deal with file uploads,
> nothing more.
>
> IMHO : YAGNI
>
Well, it's your code.
Re: [rfc] commons fileupload replacement
Posted by Jorg Heymans <jh...@domek.be>.
Luigi Bai wrote:
> Hi,
>
> I'd like to point out that the Multipart support in Cocoon is one of the
> few things that isn't pluggable or replaceable. I'd like it to be
> possible to configure web.xml/CocoonServlet to take a class name that
> implements some MultipartParser interface, and keep Part as an interface
> (perhaps letting it evolve as different implementations are available).
Point taken, but how many different implementations does a
multipartparser really need ? Commons-fileupload is RFC 1867 compliant,
has disk and memory based storage and is a "known and trusted" commons
library.
>
> Keeping the integration at the level of Interface means we don't run
> into the same kind of rigamarole that is going on with ECM etc.
True, but we're talking about 5 isolated classes that deal with file
uploads, nothing more.
IMHO : YAGNI
Regards
Jorg
Re: [rfc] commons fileupload replacement
Posted by Luigi Bai <lp...@focalpoint.com>.
Hi,
I'd like to point out that the Multipart support in Cocoon is one of the
few things that isn't pluggable or replaceable. I'd like it to be possible
to configure web.xml/CocoonServlet to take a class name that implements
some MultipartParser interface, and keep Part as an interface (perhaps
letting it evolve as different implementations are available).
Keeping the integration at the level of Interface means we don't run into
the same kind of rigamarole that is going on with ECM etc.
By the way, I'm not clear on why Multipart support can't be implemented as
an Action? If it's an Action, then it's clearly pluggable, and all this
goes away. Why is it so early in the process, hard coded in CocoonServlet?
On Mon, 8 Nov 2004, Jorg Heymans wrote:
>>
>> Is posible to add support for both at the same time? If this is possible,
>> then we can add it in 2.1.6 and deprecate the old approach.
>
> so you mean actually wrap a FileItem inside PartOnDisk and PartInMemory,
> instead of creating our own FileItemPart subclassed from Part? Yes that would
> work as well give or take a few bodges.
>
> Regards
> Jorg
>
>
Re: [rfc] commons fileupload replacement
Posted by Jorg Heymans <jh...@domek.be>.
>
> Is posible to add support for both at the same time? If this is possible,
> then we can add it in 2.1.6 and deprecate the old approach.
so you mean actually wrap a FileItem inside PartOnDisk and PartInMemory,
instead of creating our own FileItemPart subclassed from Part? Yes that
would work as well give or take a few bodges.
Regards
Jorg
Re: [rfc] commons fileupload replacement
Posted by Antonio Gallardo <ag...@agssa.net>.
Jorg Heymans dijo:
> Hi,
>
> I have provided a patch [1] that removes cocoon's multipart upload
> parser with one based on commons-fileupload.
>
> My approach breaks existing client code however, so Antonio suggested to
> get a few more opinions before continueing.
>
> 1) Part, PartOnDisk, PartInMemory are not necessary anymore. They are
> replaced by the FileItem interface of commons fileupload. It should be
> doable to wrap the FileItems in a Part class as suggested by Reinhard
> (with a slight change to the contract, see [1] ) .
>
> 2) web.xml parameter "overwrite-uploads" is gone. Instead, we need a
> parameter like "where-to-store-uploads" with values "disk" or "memory".
> In addition to this (not included in the patch) commons-fileupload
> offers a "threshold" for memory based storage, files larger than the
> threshold will get written to disk anyway - we don't *have* to use this
> however.
>
> 3) There is no replacement for getHeaders() in Part.java.
>
> The nice thing to do would be to deprecate the Part classes, and wrap
> the FileItem interface inside Part for 2.1.6. , remove Part in 2.1.7?
>
> Or is 2.1.6 too soon for this?
>
> Thoughts?
> Jorg
>
> [1] http://nagoya.apache.org/bugzilla/show_bug.cgi?id=32102
Hi Jorg:
Thanks for posting about that! :-D
Is posible to add support for both at the same time? If this is possible,
then we can add it in 2.1.6 and deprecate the old approach.
WDYT?
Best Regards,
Antonio Gallardo