Is Representation in acceptRepresentation == Request.getEntity() ?

2009-08-04 Thread Paul J. Lucas
If I am implementing:

public void acceptRepresentation( Representation rep ) {
// ...
}

Is using that rep exactly the same as if I had instead done:

Representation rep1 = getRequest().getEntity();

?  Is the rep being passed to acceptRepresentation() just a  
convenience?

- Paul

--
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2380079


Form parsing doesn't work

2009-02-18 Thread Paul J. Lucas
I have a bit of code that processes a multipart/form-data form.  I'm  
sending a test request using curl, e.g.:

curl -v -F from=paul%40lucasmail.org http://localhost:8182/foo;

I have code that parses the form that starts off with:

final MediaType mediaType = request.getEntity().getMediaType();
final Form form =
MediaType.APPLICATION_WWW_FORM.equals( mediaType, true ) ||
MediaType.MULTIPART_FORM_DATA.equals( mediaType, true ) ?
request.getEntityAsForm() :
request.getResourceRef().getQueryAsForm();

The form data isn't parsed correctly: the one and only name is the  
boundary string.  The FormReader class doesn't seem to handle  
multipart/form-data.

I'm using an older Restlet version (1.0.9), but I tried upgrading to  
1.1.2 and it makes no difference.

How to I parse multipart/form-data forms correctly?  (Preferably using  
1.0.9.)

- Paul

--
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=1188665


ERROR: 'Broken pipe'

2008-11-17 Thread Paul J. Lucas

I've been seeing a lot of:

ERROR:  'Broken pipe'
Exception intercepted @ HttpServerConverter.commit

lately.  What exactly does it mean?  How can I print out the  
exception?  And possible how to debug this?


I'm using Restlet 1.0.9.

- Paul


Re: Knowing if a client disconnected?

2008-08-13 Thread Paul J. Lucas

On Aug 13, 2008, at 9:53 AM, Jerome Louvel wrote:

If the socket is broken or was closed by the client while the  
response is
written, you won't be able to restore it. However, you can log the  
fact
the you got this request from this client and wait for the client to  
retry

its request.


OK, but my question was: how do I *know* it actually happened?

- Paul


Re: Knowing if a client disconnected?

2008-08-13 Thread Paul J. Lucas

On Aug 13, 2008, at 10:26 AM, Jerome Louvel wrote:


The closest you'll find in the Restlet API is the
org.restlet.service.ConnectorService class that has two callback  
methods:

- beforeSend(Representation entity)
- afterSend(Representation entity)

Maybe we could introduce a new call-back method onSendError(...)  
that

would inform you about the failed response and the reason for failure.


So you're saying there's no way to know *now* with the API as it  
currently is?  It would be nice to know *now*.


- Paul


Knowing if a client disconnected?

2008-08-12 Thread Paul J. Lucas
Suppose I have  a service that takes some time to compute the response  
to.  Further suppose that a client connects but then disconnects  
prematurely for whatever reason either before I start or while I am  
returning a response.  Is there any way to know if the client is  
really still there and connected?


- Paul


Any interest in a DTO class?

2008-08-07 Thread Paul J. Lucas
I wanted a simple way to get the values of request parameters into an  
Object.  I've implemented a DTO (Data Transfer Object) class that can  
be used for this.


Suppose you want to implement a query request.  You could do something  
like:


public class QueryDTO extends DTO {
@Required public String q;
public SortOrder order; // SortOrder is enum { NAME, DATE, SIZE }
public Boolean desc;

QueryDTO( Request request ) throws DTOException {
super( request );
if ( order == null ) order == SortOrder.NAME;
if ( desc == null ) desc = Boolean.FALSE;
}
}

What this says is that a request has 3 query parameters.  Of those,  
q is a required String.  The DTO constructor takes care of all the  
parsing of form data (for both APPLICATION_WWW_FORM and  
MULTIPART_FORM_DATA cases), enforces @Require constraints, and handles  
enum values.  You can then use it like:


public void handleGet() {
try {
QueryDTO dto = new QueryDTO( getRequest() );
// ... use dto.{members} as you please ...
}
catch ( DTOException e ) {
e.setStatusOf( getResponse() );
}
}

DTO also correctly handles array values.  For example, specifying:

public String[] field;

allows field to be specified more than once:

http://server/foo?field=val1field=val2;...

There are also @Permitted and @Forbidden annotations.  For example:

@Permitted( onlyIf={y} )
public Integer x;

@Permitted( onlyIf={x} )
public Integer y;

This will cause DTO to throw an exception if either x or y is  
given without the other.  (@Forbidden works similarly, but in reverse.)


If there's interest, I'd be willing to donate this code to Restlet.

- Paul



Re: Hanging on ServerSocket.accept()

2008-07-07 Thread Paul J. Lucas

On Jul 4, 2008, at 3:57 AM, Jerome Louvel wrote:


What do you mean by launching 1/10 times?


I mean that the problem only manifests immediately after launch (if it  
manifests at all).  The problem never manifests if the software has  
been running OK for a while (meaning it has been servicing requests).



Do you stop and restart the application?


Yes.


Do you do this using Component#start() and stop() methods ...


Yes.


and differently?


I don't know what you mean by that.

It is important to cleanly shutdown your server connector in order  
to quickly release the open sockets.


It's not that the server can not *bind* to the socket -- it does.   
(The problem I assume you are referring to is the SO_LINGER option on  
the socket.)


It binds, listens, and does an accept -- and it hangs on the accept.

Did you looked at the list of open TCP/IP sockets under Windows? You  
can try

'netstat -n' for example.


I know the socket is open and accepting because I can telnet to the  
port.  Both the telnet client and server hang.


- Paul


Re: Series.getValues()

2008-03-24 Thread Paul J. Lucas

On Mar 23, 2008, at 10:50 AM, Jerome Louvel wrote:

Paul, the Series class address the lack of a structure maintaining a  
list of
named entries. There is no reusable Parameter class (name, value  
pair) in
the JDK. Only the Map.EntryK,V interface comes close to it. Having  
just a
ListParameter (via ArrayList or similar) is good but doesn't  
provide any

facility to lookup the structure by parameter name (like the
getValuesArray(name) method you were looking for). This is what the  
Series
class adds in addition of being a ListParameter. I hope that makes  
sense.



You can use ListParameter if you write more generic utility classes:

public interface CollectionFilterT {
boolean accept( T obj );
}

public final class CollectionUtil {

public static T CollectionT filter( CollectionT in,
CollectionT out,
 
CollectionFilterT filter ) {

for ( T x : in )
if ( filter.accept( x ) )
out.add( x );
return out;
}
}

Then you just implement CollectionFilter:

public ParameterNameFilter implements CollectionFilterParameter {
public ParameterNameFilter( String name ) {
m_name = name;
}
public boolean accept( Parameter p ) {
return p.getName().equals( m_name );
}
private final String m_name;
}

Finally:

ListParameter fooParams = CollectionUtil.filter(
in, new LinkedListParameter, new ParameterNameFilter( foo )
);

The bonuses are:

1. The Series class doesn't leak into places that shouldn't have a  
dependency on it since you're using an ordinary List.


2. The solution above is completely generic and can be used for lots  
of other stuff.


If you want, you can add other Util methods that are convenience  
methods to lessen typing.


- Paul


Re: Series.getValues()

2008-03-22 Thread Paul J. Lucas

On Mar 22, 2008, at 4:21 AM, Stephan Koops wrote:


is it necessary to use the legacy datatype array?


Since when is an array a legacy datatype?  (If this were C++ instead  
of Java, that question would have more merit.)


I think never the Series deals with arrays. What about returning  
SeriesString?


I prefer simpler APIs.  Your suggestion means I have to understand  
what a Series is, why it's supposedly better than either an array or a  
Collection, and how I have to use it.


In Restlet, I don't even really understand what problem all the  
Wrapper classes solve, never mind Series.  To me, it's a lot of code  
one either has to maintain or learn about for very little (if any)  
benefit.  IMHO, Restlet should be a reference implementation of REST,  
not an exercise in how to tweak the Java collections API.


- Paul


Re: Series.getValues()

2008-03-22 Thread Paul J. Lucas

On Mar 22, 2008, at 11:16 AM, Stephan Koops wrote:

Since we have java.util.List. Ok, sometime it is useful to ue  
arrays, but IMO in the most cases the list is the better solution.  
Typically you collect the result in a List, because you don't know  
the result size. Than you perhaps convert it to an array. So it is  
not faster to return arrays. The only argument for arrays are for  
me, that they are faster.



I don't have that strong opinions on List vs. arrays.  My only point  
was saying that Java arrays are not legacy.



Series is also a List. you can handle it as List.


Yes, I know.  I simply don't see that Series solves any particular  
problem and hence why it's necessary.  IMHO, it would have been  
simpler and cleaner just to use List directly which every Java  
programmers knows how to use already.


- Paul


Series.getValues()

2008-03-20 Thread Paul J. Lucas
Sorry if this is a duplicate, but I never say my original message echo  
to the list.


Begin forwarded message:
Date: March 19, 2008 4:19:32 PM PDT
To: discuss@restlet.tigris.org
Subject: Series.getValues()

This method, as written in Restlet 1.0.8, specifically this variant:

getValues(String name, String separator, boolean ignoreCase)

has room for improvement.  Aside from the fact that the ignoreCase  
parameter is not used, globbing the values together with a separator  
is not that useful.  I really want:


String[] getValues(String name)

with an implementation like:

   public String[] getFormValues( String paramName ) {
   final ListString temp = new LinkedListString();
   for ( Parameter param : this )
   if ( param.getName().equalsIgnoreCase( paramName ) )
   temp.add( param.getValue() );
   return temp.toArray( new String[ temp.size() ] );
   }

- Paul



Re: Root URIs under Windows

2008-03-10 Thread Paul J. Lucas

On Mar 10, 2008, at 1:45 AM, Thierry Boileau wrote:


I've tested this code below with both Restlet 1.1 (snapshot) and
Restlet 1.0.8 and it works.
Could you tell us more about your code?


I have my own classes derived from Directory and DirectoryResource.  I  
override DirectoryResource.handleGet().  In handleGet(), I need to  
know what the Directory's root directory is so I call  
Directory.getRootRef().getPath().  The path it returns is URL-encoded,  
e.g., spaces are encoded as %20.  This is why my code fails (because  
it needs to be decoded first).


So the question is: should Reference.getPath() (and other get*()  
methods) return their component strings already decoded?  This would  
parallel URI.getPath().  If you really want the original form, there's  
URI.getRawPath() and there could correspondingly be  
Reference.getRaw*() methods.


- Paul


Root URIs under Windows

2008-03-07 Thread Paul J. Lucas
Does anybody use Restlet under Windows?  I want my server's root URI  
to be a directory like:


C:\Documents and Settings\pjl\My Documents\My Pictures\

That's held in a File variable.  I convert that to a URI then to a  
String like:


String rootURI = rootDir.toURI().toString();

That gives me a URI like:

file:/C:/Documents%20and%20Settings/pjl/My%20Documents/My%20Pictures/

but that doesn't work.  I get FileNotFound for all files.

What's the right way to use Windows' directories with Restlet?

- Paul


Re: Root URIs under Windows

2008-03-07 Thread Paul J. Lucas

On Mar 7, 2008, at 5:12 PM, cleverpig wrote:


   public Restlet createRoot(){
   final String
DIR_ROOT_URI=file:///E:/eclipse3.1RC3/workspace/RestletPractice/static_files/ 
;


Yes, I already know how to do the code.  That's not my question.  The  
differences between your example and mine are:


+ Yours has file:/// whereas mine has file:/
+ Yours has no spaces encoded as %20.

I hacked my code and made it use file:/// and it made no  
difference.  After some more experimentation, it seems the problem is  
the %20 characters.  To make a simpler test-case, I used a path like:


C:\tmp\sub_directory

When converted via File.toURI().toString(), I get:

file:/C:/tmp/sub_directory

and that works.  When I rename sub_directory so it has a space instead:

C:\tmp\sub directory

I get:

file:/C:/tmp/sub%20directory

And this causes Restlet not to work.  It seems like a bug to me.

- Paul


Restlet vs. Resource

2008-02-08 Thread Paul J. Lucas
Is there a guideline when one should extend Restlet vs. extens  
Resource?  My rationalization is that: if X represents some kind of  
physical resource, the one should extend Resource; if X represents  
some kind of service, e.g., a search service, then one should  
extend Restlet.


Opinions?

- Paul


Status class should have a Throwable field

2008-01-26 Thread Paul J. Lucas

I would like to be able to have code like:

try {
// ...
}
catch ( SomeException e ) {
response.setStatus( CLIENT_ERROR_BAD_REQUEST, e );
}

That is that you can pass a Throwable to setStatus() and that the  
Status class have the additional methods of:


void setThrown( Throwable t );
Throwable getThrown();

The default implementation of the response that gets returned to the  
client will simply do an:


t.getMessage()

and include that as the textual error message.  However, if I  
implement my own StatusService, I have full access to the exception.   
In my case, I'd like to return an XML entity containing an XML-ized  
version of the exception's stack trace.


- Paul


Re: Status class should have a Throwable field

2008-01-26 Thread Paul J. Lucas
OK, fine: then simply add a constructor that takes a Throwable as  
well as a getThrown() method.  Status can stay immutable.


- Paul


On Jan 26, 2008, at 1:06 PM, Stephan Koops wrote:


Hello Paul,

if I understood you right, than you want to add method to the class  
Status to save the exception in the status object. But the Status  
objects are immutable as all metadata. So this won't work.


best regards
  Stephan


Re: Directory redirection issues

2008-01-21 Thread Paul J. Lucas

On Jan 21, 2008, at 1:32 PM, Jerome Louvel wrote:

1. How do I turn directory redirection off?  Specifically, if the  
request refers to a directory and the URI doesn't end in '/', it's  
OK for the server to add the '/' internally for processing, but I  
don't want it to issue a 303 response.


The problem that arise if you don't force a redirect is that all  
relative URIs served become harder to construct and read.


For example with the /foo/bar base URI, the joe.html relative  
URI resolves to /foo/joe.html instead of the expected /foo/bar/ 
joe.html because the browser has no way to know that /foo/bar is  
corresponding to a directory.


I understand the problem.  I'm not saying don't add the '/' at the  
end; I'm saying have a flag that silently adds it internally without  
doing an explicit redirect.  In the cases where you set  
directoryRedirection to true, mutate the Request instead to append  
the '/' as if you did the redirection and the client sent you back a  
new request with the trailing '/'.


- Paul


Changing the root URI

2008-01-17 Thread Paul J. Lucas
So I create a Router, create some Directory instances with a given  
rootURI, and attach them to the router.


At some later time, I want to change what the rootURI is globally  
while the server is running.  In Directory, rootRef is private and  
there's no setRootRef() method.  Why not? Similarly, Application  
doesn't have a setRoot() method.  Why not?


How can I do what I want?  Right now it seems the only way would be  
to do something like call Router.getRoutes() and replace the list  
with new Directory instances.


- Paul


Re: Bad implementation of Status error checking

2008-01-16 Thread Paul J. Lucas
Also, it seems that isSuccess() is wrong.  In reading RFC 2616, 1xx  
and 3xx codes are not errors, so they should be considered success  
codes, no?


- Paul


On Jan 16, 2008, at 10:09 AM, Paul J. Lucas wrote:

What if I want to make up my own Status codes?  The isSuccess() and  
is*Error() methods do explicit code checks.  Why?  Why isn't the  
implementation for, say, isSuccess() this:


return code = 200  code  300;

?


Re: Aborting request in Filter

2008-01-13 Thread Paul J. Lucas

Sorry for not commenting earlier, but

Anyway, in thinking about this more, I don't think a filter should  
have any knowledge of its next filter.  When a request is received,  
the engine should have a list of filters, i.e., the list itself  
should be external to all the filters.


So, currently, you have:

Request - F1 - F2 - ... - Fn

I would prefer:

Request - L1F1 - L2F2 - ... - LnFn

where Li is a node in a linked list and the element type of the list  
is Filter.  However, once you do that, there is no longer a need for  
Filter as a separate class: it's just an ordinary Restlet.   
Furthermore, whether a filter is before or after depends only on  
where it is in the list and is also not a property of a filter.  (If  
I wanted a single instance of some filter to be both before and  
after, I would simply insert the same instance twice in the list at  
different places.)


As for whether to continue upon error, each Restlet, upon insertion  
into the list, Restlet could have a method like:


boolean acceptStatus( Status s ) {
return s.isSuccess();
}

Hence, the default would be to abort continuation down the list of  
Restlets; however, if a Restlet wants to filter error responses, it  
would simply override acceptStatus().


- Paul


On Jan 13, 2008, at 6:51 AM, Jerome Louvel wrote:


Here are the details of the change:

Filter.beforeHandle() and doHandle() methods can now indicates if the
processing should continue normal, go to the afterHandle() method  
directly

or stop immediately.

IMPORTANT NOTE: as it isn't possible to add a return parameter to an
existing method, the change can break existing filters. In this  
case, you
just need to return the CONTINUE constant from your method and  
use int

as return parameter.



Re: Shutting down a server

2008-01-10 Thread Paul J. Lucas
Well, I just tried calling System.exit(0) and nothing happens: the  
process doesn't exit.  FYI: I'm using the Simple HTTP server.  There  
are a bunch of threads stuck in wait().


How can I shutdown the server and cause the process to exit?

- Paul


On Jan 9, 2008, at 11:43 PM, Paul J. Lucas wrote:


When I start my server, I have:

component = new Component();
// ...
component.start();

To shutdown a server, I assume I do:

component.stop();

However, the process doesn't stop.  Should I then simply do:

System.exit( 0 );

?


Re: Aborting request in Filter

2008-01-10 Thread Paul J. Lucas
Well, if you want to post-process a request in error, you need to  
distinguish that case from the case where you don't want to post- 
process in error.


Another problem is that the current doHandle() calls next.handle()  
and that doesn't return a boolean to indicate whether to do post- 
processing in error.  So, even if you make doHandle() return a  
boolean, it's not clear what you return since it has no way to know  
whether it should continue (unless it checks the Status code).


There's also the case where, even if you return false from  
beforeHandle(), you might still want to call afterHandle(), no?


So if you really wanted to cover all cases, you'd have to do  
something like:


boolean beforeSucceeded = beforeHandle( request, response );
if ( beforeSucceeded )
doHandle( request, response );
afterHandle( beforeSucceeded, request, response );

If you don't want to post-process, then the implementation of  
afterHandle() can check the Status code itself and do nothing on error.


The added parameter of beforeSucceeded to afterHandle() would be  
needed to distinguish the case where beforeHandle() failed (and thus  
doHandle() was never called) vs. doHandle() failing.


- Paul


On Jan 10, 2008, at 12:08 AM, Jerome Louvel wrote:

You expose a good use case. The solution below has some drawbacks  
because you might want to post-process a request in error, for  
example to add a status representation like the StatusFilter do in  
NRE. Even the proposed test on doHandle() could be limiting (even  
if it does solve your issue).


Here is what I propose : let's add boolean return parameters to  
beforeHandle() and doHandle() that will determine whether the  
processing should continue with doHandle() or afterHandle()  
respectively. We can make this backward compatible easily and add  
it to 1.1 M2.


How does it sounds?


Re: Shutting down a server

2008-01-10 Thread Paul J. Lucas
I switched to using Jetty and I had the same problem -- the process  
didn't terminate. So I figured out that it was my fault by creating a  
deadlock.  I removed that and now the process terminates when calling  
System.exit(0).  So then I went and tried Simple again and it too now  
terminates.


I then tried removing the call to System.exit(0) to see if the  
process would exit naturally.  It doesn't with Simple and does with  
Jetty.  Hence, the bug with Simple seems confirmed.


Hypothetically, if I wanted to continue to use Simple, it is OK to  
call System.exit(0) and still terminate gracefully?


- Paul


On Jan 10, 2008, at 5:31 AM, Kevin Conaway wrote:

Bug the Simple developers.  I am absolutely astonished that they  
don't provide a clean way to shut down their server.


On Jan 10, 2008 2:59 AM, Paul J. Lucas  [EMAIL PROTECTED] wrote:
Well, I just tried calling System.exit(0) and nothing happens: the
process doesn't exit.  FYI: I'm using the Simple HTTP server.  There
are a bunch of threads stuck in wait().

How can I shutdown the server and cause the process to exit?

- Paul


On Jan 9, 2008, at 11:43 PM, Paul J. Lucas wrote:

 When I start my server, I have:

   component = new Component();
   // ...
   component.start();

 To shutdown a server, I assume I do:

   component.stop();

 However, the process doesn't stop.  Should I then simply do:

   System.exit( 0 );

 ?



Re: Aborting request in Filter

2008-01-10 Thread Paul J. Lucas
By the way, in the doHandle() method, if there isn't a next Restlet,  
the method sets the response to CLIENT_ERROR_NOT_FOUND.  Shouldn't  
that be SERVER_ERROR_INTERNAL because the programmer goofed by not  
setting a next Restlet?


- Paul


Aborting request in Filter

2008-01-09 Thread Paul J. Lucas
If I write my own filter and use its beforeHandler(), I would like,  
upon some catastrophe, to abort the entire request and return some  
client error code.


Unfortunately, it doesn't appear that the API for Filter allows  
aborting a request.  True?


This is another good case for using exceptions.

- Paul


Shutting down a server

2008-01-09 Thread Paul J. Lucas

When I start my server, I have:

component = new Component();
// ...
component.start();

To shutdown a server, I assume I do:

component.stop();

However, the process doesn't stop.  Should I then simply do:

System.exit( 0 );

?

- Paul


Re: The alphanum algorithm

2007-12-19 Thread Paul J. Lucas

On Dec 19, 2007, at 8:57 AM, Jerome Louvel wrote:

However, there appear to be three authors/contributors, so we would  
need to get the agreement and JCA of all of them which complicates  
things a bit.


Given the algorithm description in English, just write the code  
yourself from scratch and the copyright issue becomes moot.  This  
algorithm isn't exactly rocket science.


- Paul


Re: The alphanum algorithm

2007-12-19 Thread Paul J. Lucas

On Dec 19, 2007, at 11:13 AM, Rob Heittman wrote:

I have concerns about doing an independent implementation because  
it would likely bear substantial resemblance to yours.


As long as you do a clean room implementation, i.e., you'd swear  
under oath that you didn't look at the original code, it doesn't  
matter how much it resembles the original.


- Paul


Limiting threads

2007-12-17 Thread Paul J. Lucas
Is it possible to limit the number of threads that Restlet uses/spawns  
in servicing requests?


- Paul


Restlet and Flickr

2007-12-05 Thread Paul J. Lucas
Has anybody done a Flickr client using Restlet?  If so, details  
appreciated.  Or, failing that, being pointed in the right direction  
on how to do it (what classes to derive from) would be good.


I've been looking at the Restlet code and the thing that strikes me  
as wrong is that the core classes have a small, finite number of  
authentication schemes hard-coded into them, e.g., NMTL and AWS.   
IMHO, there should be no authentication schemes hard-coded.  There  
should be an interface and instead a set of bundled ones, but there's  
no reason, for example, why SecurityUtils should know anything about  
the X-Amz-Date HTTP header.


- Paul


Re: Exceptions in general

2007-12-05 Thread Paul J. Lucas

On Dec 4, 2007, at 3:03 AM, Stian Soiland wrote:


On 12/3/07, Paul J. Lucas [EMAIL PROTECTED] wrote:


Funny, because java.io.FileNotFoundException is derived from
IOException.  So clearly there's precedent.


Did you notice the io package name? :-) The exceptions here are
about resources, not IO.


So what?  java.io.IOException means *any* exception with *any* I/O,  
be it file, socket, keyboard, courier pigeon, whatever.


If RestletException were to exist, then *any* exception with *any*  
resource, be it a file on a local disk, or some other abstract  
resource, would be appropriate.  Would calling it ResourceException  
make it make more sense to you?


- Paul


Re: RESTClient

2007-11-30 Thread Paul J. Lucas

On Nov 30, 2007, at 6:05 AM, Lars Heuer wrote:


RESTClient is a Java platform client application to test RESTful
webservices. http://code.google.com/p/rest-client/


IMHO, command-line test tools are better because they're far more  
easily automated.  I just write Perl script wrappers around curl.


- Paul


Re: Exceptions in general

2007-11-29 Thread Paul J. Lucas

On Nov 29, 2007, at 6:30 AM, Tim Peierls wrote:

However, I don't have a concrete proposal, and I don't see an easy  
way to do this without breaking code for 1.1m1 users.


Personally, I'd prefer to break an API rather than have to live with  
a hacked API forever.  Since Restlet is currently a 1.x API, it's  
presumably in its infancy.  Now is the time to rework it to make it  
better even if it means breaking some people's code.  If they don't  
want to upgrade, well, they have the option of not doing so.


- Paul


Re: Lightweight alternative to Reference

2007-11-29 Thread Paul J. Lucas

On Nov 29, 2007, at 3:18 PM, Jerome Louvel wrote:

It could have methods starting with append like the StringBuilder  
class,

and follow the Reference naming convention. For example it could have:

 - appendScheme(String scheme)
 - appendSchemeSpecificPart(String ssp)
 - appendFragment(String fragment)
 - appendHierarchicalPart(String ssp)
 - appendAuthority(String authority)
 - appendPath(String path)
 - appendSegment(String segment)
 - appendMatrixParam(String name, String value)
 - appendQuery(String query)
 - appendQueryParam(String name, String value)


Except it's not append: it's insert into the right place or set.


It should force the reference to be built in the correct order so an
efficient StringBuilder could be used internally and should guide the
developer with clear warning messages when parts are not appended  
in the

right order.


Why should it enforce the order?  The burden should be on the  
implementor, not the user.  Don't use a StringBuilder: use simple  
fields:


class URI {
private String scheme;
private String host;
// ...
}

- Paul


Re: Lightweight alternative to Reference

2007-11-29 Thread Paul J. Lucas

On Nov 29, 2007, at 4:32 PM, Rob Heittman wrote:

The warnings to the user (cough Checked Exceptions /cough) should  
come in when you try to confess the builder into a URI, Reference,  
or String and it doesn't contain enough pieces and parts to have  
meaning.


If, as the implementor, you want to be lazy, simply use java.net.URI  
to do the work using the:


URI(String scheme, String userInfo, String host, int port, String  
path, String query, String fragment)


constructor and reuse java.net.URISyntaxException as-is.  (There's no  
need to invent another exception when the one included in the JDK will  
work just fine.)


- Paul


Re: Lightweight alternative to Reference

2007-11-29 Thread Paul J. Lucas

On Nov 29, 2007, at 4:52 PM, Tim Peierls wrote:

Abstractly, though, would you rather see ReferenceBuilderException  
checked or unchecked in the following:


  try {
  Reference ref =  
ReferenceBuilder.appendBar(myBar).appendFoo(myFoo);

  // do something with ref
  } catch (ReferenceBuilderException e) {
  // myBad: foo must come before bar
  // clean up
  // ? throw e;
  }

Programmer was wrong -- this should be unchecked, right?


How do you know the programmer was wrong?  How does the implementor of  
ReferenceBuilder know whether the data was supplied by the programmer  
or the user of the program?  If the latter, it's the user who is wrong  
in which case the programmer must deal with that.  Therefore: checked  
exception.


In general, IMHO, you've got to have a really, really good reason to  
make an exception unchecked.  Because it's easier isn't a good reason.


- Paul


Re: ConverterService architecture

2007-11-28 Thread Paul J. Lucas

On Nov 28, 2007, at 1:31 PM, Jason Terhune wrote:

I haven't actually tried this, but couldn't you just overload the  
toObject()
and toRepresentation() methods?  Doesn't Java do the work of  
choosing the

method with the most specific argument?

For example:
public class ConverterService extends ConverterService {
 public Foo toObject(FooRepresentation fr);

 public FooRepresentation toRepresentation(Foo f);
}


But the base class can't specify the infinite number of derived  
classes as arguments to an infinite number of methods.


- Paul


Re: ConverterService architecture

2007-11-26 Thread Paul J. Lucas

On Nov 26, 2007, at 2:33 AM, Jerome Louvel wrote:

Your suggestion regarding the map of ConverterService is  
interesting. However, how would you handle the reverse conversion  
(from Representation to Object) ?


Also using a map.  For both conversion directions, you allow for the  
possibility of subclasses, e.g.:


public class ConverterServiceMap extends ConverterService {
// ...

public Object toObject( Representation rep ) {
for ( Class c = rep.getClass(); c != Object.class;
  c = c.getSuperclass() ) {
final ConverterService cs = m_toObjMap.get( c );
if ( cs != null )
return cs.toObject( rep );
}
return super.toObject( rep );
}
}

Sometimes the list of available variants is closely related to the  
processing resource, so it may be that the Resource subclass is the  
best place to handle such conversions.


Sometimes, yes.  But other times, you could have several resources/ 
services that all share a common format so it would be nice to write  
the conversion in a single place.


My vote for now is to keep ConverterService deprecated in 1.1  
instead of refactoring it.


:-(

- Paul


ConverterService architecture

2007-11-23 Thread Paul J. Lucas
The current architecture of ConverterService is such that if I want  
to convert to/from an object of a given class, I subclass  
ConverterService.  Well, what if I want to convert to/from several  
classes?  In my subclass, I could do an:


if ( obj instanceof MyClass1 ) {
// ...
} else if ( obj instanceof MyClass2 ) {
// ...
} else ...

which is (a) tedious and (b) means I have to have my subclass know  
about lots of classes (bad design, IMHO).


So instead, why doesn't Application instead have a:

MapClass,ConverterService

so then the code to to conversion would look up the right  
ConverterService based on the class of the object being converted?


- Paul


Why not Reference.getQueryAsObject?

2007-11-23 Thread Paul J. Lucas
If Message.getEntityAsObject() exists, why doesn't  
Reference.getQueryAsObject() exist?  I want to turn a query (via a  
Form) into an Object using a ConverterService.  (I'm converting a  
query into an Object now, but doing it my own way since the framework  
apparently provides no right way of doing this.)


- Paul


Re: Converting http to file scheme

2007-11-19 Thread Paul J. Lucas

On Nov 19, 2007, at 6:51 AM, Rob Heittman wrote:


Or maybe Paul can figure out a way to do it without the mess.


Right now, I'm still trying to get my head around all this.  It's not  
totally clear to me when things should be a Restlet or a Resource;  
whether one should derive from Directory or DirectoryResource; what  
Helpers are exactly and when to use/derive from them.


For example, in my tinkering, I tried deriving from  
DirectoryResource.  I then attached MyResource to a router like:


router.attach( /foo, MyResource.class );

The problem with that is that MyResource has no no-argument  
constructor (because DirecoryResource doesn't), so you get a  
NoSuchMethodException because the framework wants a no-argument  
constructor.  OK, so that's not the way to do anything.


For my application, I need to do 3 classes of things: simple file  
manipulation (create, delete, update, copy, move, i.e., WebDAV-like  
stuff); image manipulation (get, scale, convert, etc.); and image  
metadata (get, put).  In all cases, I need to convert http-style URLs  
to local file-style URLs.  Jerome mentioned that Directory does this,  
but it's unclear how to leverage that fact.


For example, the metadata part is sort-of simple.  Given a URL like:

http://server/metadata/path/to/image.jpg

when using GET, you should get an XML document back containing the  
metadata of the image rather than the image itself.  I'm guessing  
this can be done with a Filter (?).


Anyway, so it's unclear whether I'll be able to figure out how to  
implement COPY and MOVE without the mess.  (I do have to implement  
*something* to do copy/move.  Ideally, I'd like it to work just like  
WebDAV; but if I can't figure it out, I'll have to do something else.)


- Paul


Implementing COPY and MOVE (Was: Converting http to file scheme)

2007-11-19 Thread Paul J. Lucas

On Nov 19, 2007, at 6:51 AM, Rob Heittman wrote:

In my noodling with DAV method support, COPY and MOVE are especially  
challenging to implement. By extending Directory and friends, you  
can model a COPY as a GET and a PUT, and a MOVE as a GET, DELETE,  
and PUT, but this is messy, not atomic in the right ways, and not  
very performant. Really you need to have COPY and MOVE supported  
down through the client as well. This is a lot easier if you just  
check out trunk and hack on it, than by trying to extend everything  
and coerce Restlet to use the extended classes.


I've figured out that to do this right, yes: you do need to extend  
DirectoryResource.  The problem with that is that Engine insists on  
creating an instance of DirectoryResource and not an instance of one's  
derived class.  So that means one has to subclass Engine and then  
figure out how to get engineClassName in Engine.getInstance() be one's  
own derived class.  (Is there an easy way to do that?)  Anyway, it  
seems like a lot of messy work.


Aside: Why does Engine have a lone createDirectoryResource() method at  
all?  It seems like overly-tight coupling.  Why isn't there an easier- 
to-alter Factor pattern for creating directory resources?


But something that would go a long way toward implementing COPY and  
MOVE would be simply to provide stubs for them, specifically:


1. Add COPY and MOVE to Method.
2. Add allowCopy() and allowMove() to Resource.

Of course, I'm a newbie.  Would doing just items 1 and 2 above be good  
enough to allow even a simple implementation of COPY and MOVE?


- Paul


Re: Implementing COPY and MOVE

2007-11-19 Thread Paul J. Lucas

On Nov 19, 2007, at 8:12 PM, Paul J. Lucas wrote:

I've figured out that to do this right, yes: you do need to extend  
DirectoryResource.  The problem with that is that Engine insists on  
creating an instance of DirectoryResource and not an instance of  
one's derived class.  So that means one has to subclass Engine and  
then figure out how to get engineClassName in Engine.getInstance()  
be one's own derived class.  (Is there an easy way to do that?)   
Anyway, it seems like a lot of messy work.


I just discovered that Directory.findTarget() is what's used to create  
an instance of DirectoryResource.  OK, so if I derived from Directory  
and override findTarget(), I can return an instance of  
MyDirectoryResource that implements:


allowCopy()
allowMove()
handleCopy()
handleMove()

I then wrote MyDirectoryResource.copyOrMove():

private void copyOrMove( boolean isMove ) {
final Request request = getRequest();
final Response response = getResponse();

final String destHeader =
RestletUtil.getHeaderValue( request, Destination );
final String overwrite =
RestletUtil.getHeaderValue( request, Overwrite );
if ( destHeader == null || overwrite == null ) {
response.setStatus( CLIENT_ERROR_BAD_REQUEST );
return;
}

try {
new URI( destHeader );
}
catch ( URISyntaxException e ) {
response.setStatus( CLIENT_ERROR_BAD_REQUEST,  
e.getMessage() );

return;
}

final String serverRoot = MyServer.getServerRootDirectory();

final String sourcePath =  
request.getResourceRef().getRemainingPart();

final File sourceFile = new File( serverRoot + sourcePath );
if ( !sourceFile.exists() ) {
response.setStatus( CLIENT_ERROR_NOT_FOUND );
return;
}

Status successStatus = SUCCESS_CREATED;

final String id =  
request.getResourceRef().getBaseRef().getIdentifier();

String destPath = destHeader.substring( id.length() );
final File targetFile = new File( serverRoot + destPath );

if ( targetFile.exists() ) {
if ( !overwrite.equals( T ) ) {
response.setStatus(
CLIENT_ERROR_PRECONDITION_FAILED,
Destination already exists and Overwrite is not  
'T'

);
return;
}
if ( !targetFile.canWrite() ) {
response.setStatus(
CLIENT_ERROR_LOCKED,
Destination can not be overwritten
);
return;
}
successStatus = SUCCESS_NO_CONTENT;
}
try {
FileUtil.copyFile( sourceFile, targetFile );
if ( isMove )
sourceFile.delete();// TODO: check return value
response.setStatus( successStatus );
}
catch ( IOException e ) {
response.setStatus( SERVER_ERROR_INTERNAL,  
e.getMessage() );

}
}

This seems to work just fine.  Comments?

I'd prefer to leverage Directory's ability to transform an http URI  
into a file URI so I could easily transform destHeader into a  
LocalReference then call getFile() on it, but it's not clear how to do  
that.  How does one do that?


- Paul


Restlet 1.2 (Was: Easier way to get an HTTP header?)

2007-11-18 Thread Paul J. Lucas

On Nov 17, 2007, at 2:42 PM, Rob Heittman wrote:


It, and other full WebDAV stuff is targeted to land in Restlet 1.2.


When is 1.2 targeted to be released?

- Paul


One Directory for entire tree?

2007-11-18 Thread Paul J. Lucas
I was playing around with trying to derive from Directory to  
implement the WebDAV COPY and MOVE methods.  (How feasible is that?)   
One of the first things I did was to call setModifiable() based on  
whether the directory is actually writable (File.canWrite()).  This  
worked fine.


I then wondered about subdirectories.  It seems that the single  
instance of Directory is used for all directories and files under the  
root and therefore isModifiable() returns the status of the root  
directory for all subdirectories and files.  That seems wrong.  Why  
isn't a new instance of Directory created for every subdirectory and  
file so each will return whether *it* is modifiable?


Currently, if isModifiable() returns false during the handling of a  
DELETE method, the status is (correctly) METHOD_NOT_ALLOWED.  But for  
all subdirectories and files, the status is (incorrectly, IMHO)  
INTERNAL_SERVER_ERROR.  The status of METHOD_NOT_ALLOWED should be  
returned for *any* directory or file if it's not modifiable.


- Paul


Converting http to file scheme

2007-11-18 Thread Paul J. Lucas

When a client specifies a URL like:

http://server/path/to/file

how do I convert that into a file URI:

file://localhost/path/to/root/path/to/file

?

The context is in trying to implement the Destination header for a  
WebDAV COPY or MOVE method.  The client specifies the destination as  
an absolute URI.  Obviously I need to map it to the local filesystem.


- Paul


Easier way to get an HTTP header?

2007-11-17 Thread Paul J. Lucas

To get the value of an HTTP header, it seems as though I have to do:

Form f = (Form)request.getAttributes().get( ATTRIBUTE_HEADERS );
String value = f.getFirstValue( MyHeader );

That seems rather... cumbersome.  Is there an easier way?

- Paul


Re: Easier way to get an HTTP header?

2007-11-17 Thread Paul J. Lucas

On Nov 17, 2007, at 2:42 PM, Rob Heittman wrote:


The non-standard header mechanism is the way to go for Destination:
and Overwrite: and such for the moment.


By which you mean the way I've already shown in code?  Or something  
else?


- Paul


Re: New user: guidance for server?

2007-11-15 Thread Paul J. Lucas

As I mentioned, I've already read the tutorial.

Perhaps I should elaborate further.  I'm not ONLY managing static  
files.  I also eventually want to have functionality for doing things  
like:


1. Thumbnail creation, i.e., rescale an image such that its largest  
dimension does not exceed N:


http://server/path/to/image.jpgmaxdimension=100

2. Image format conversion, e.g. original image is Canon RAW, client  
wants JPEG:


http://server/path/to/image.cr2format=jpeg

3. Caching of items 1  2.

Regarding the suggestion to look at the Directory class, if I wanted  
to provide directory listings in XML, I assume then that I could  
derive from it and override getIndexRepresentation() and  
getIndexVariants(), yes?


- Paul


On Nov 15, 2007, at 11:02 AM, Rob Heittman wrote:



I think this is what you want:

http://www.restlet.org/documentation/1.0/tutorial#part06


- Original Message -
From: Paul J. Lucas [EMAIL PROTECTED]
To: discuss@restlet.tigris.org
Sent: Thursday, November 15, 2007 1:05:56 PM (GMT-0500) America/ 
New_York

Subject: New user: guidance for server?

Hi -

I'm new to Restlet.  I want to create a simple server that serves the
contents of directories and images in those directories.  URLs would
be as you would expect:

* Get contents of directory:
http://server/path/to/dir/

* Get image in directory:
http://server/path/to/dir/image.jpg

Additionally, clients would be able to create and delete new
directories and images therein.

I've read the tutorial, looked at sample code, and even read the
O'Reilly book, but it's still not clear what the right approach is.

One way is to have an ImageService class derived from Restlet and
attach this to the server's default host.  Another way is to have an
ImageResource class service derived from Resource and attach this to a
Router.  It's not clear to me which is the right way of doing what I
want.

Any guidance would be appreciated.  Thanks.

- Paul