]> err.no Git - sope/blob - sope-appserver/NGObjWeb/SoObjects/SoObjectMethodDispatcher.m
renamed packages as discussed in the developer list
[sope] / sope-appserver / NGObjWeb / SoObjects / SoObjectMethodDispatcher.m
1 /*
2   Copyright (C) 2002-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "SoObjectMethodDispatcher.h"
24 #include "SoObject.h"
25 #include "SoClass.h"
26 #include "SoObjectRequestHandler.h"
27 #include "WOContext+SoObjects.h"
28 #include <NGObjWeb/WORequest.h>
29 #include <NGObjWeb/WOResponse.h>
30 #include <NGObjWeb/WOContext.h>
31 #include <NGObjWeb/WOElement.h>
32 #include "common.h"
33
34 @implementation SoObjectMethodDispatcher
35
36 static BOOL debugOn = NO;
37
38 + (void)initialize {
39   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
40   static BOOL didInit = NO;
41   if (didInit) return;
42   didInit = YES;
43
44   debugOn = [ud boolForKey:@"SoObjectMethodDispatcherDebugEnabled"];
45 }
46
47 - (id)initWithObject:(id)_object {
48   if ((self = [super init])) {
49     self->object = [_object retain];
50   }
51   return self;
52 }
53 - (void)dealloc {
54   [self->object release];
55   [super dealloc];
56 }
57
58 /* perform dispatch */
59
60 - (id)dispatchInContext:(WOContext *)_ctx {
61   NSAutoreleasePool *pool;
62   WORequest *rq;
63   id clientObject;
64   id methodObject;
65   id resultObject;
66   
67   pool = [[NSAutoreleasePool alloc] init];
68   rq   = [_ctx request];
69   
70   /* find client object */
71   
72   if ((clientObject = [_ctx clientObject])) {
73     if (debugOn)
74       [self debugWithFormat:@"client object set in ctx: %@", clientObject];
75   }
76   else if ((clientObject = [self->object clientObject])) {
77     if (debugOn)
78       [self debugWithFormat:@"setting client object: %@", clientObject];
79     [_ctx setClientObject:clientObject];
80   }
81   
82   // TODO: should check XML-RPC !!! 
83   //       (hm, why ? XML-RPC is handled by other dispatcher ?)
84   
85   /* find callable (method) object */
86   
87   if ([self->object isCallable]) {
88     if (debugOn)
89       [self debugWithFormat:@"traversed object is callable: %@", self->object];
90     methodObject = self->object;
91   }
92   else if ([[self->object soClass] hasKey:[rq method] inContext:_ctx]) {
93     // TODO: I'm not sure whether this step is correct
94     /* the class has a GET method */
95     methodObject = [self->object lookupName:[rq method] 
96                                  inContext:_ctx
97                                  acquire:NO];
98   }
99   else {
100     // TODO: should we replace the methodObject with a redirect to the
101     //       default method name? This would ensure proper URLs
102     methodObject = [self->object lookupDefaultMethod];
103     if (debugOn)
104       [self debugWithFormat:@"using default method: %@", methodObject];
105   }
106   
107   /* apply arguments */
108     
109   if ([methodObject respondsToSelector:
110                       @selector(takeValuesFromRequest:inContext:)]) {
111     if (debugOn)
112       [self debugWithFormat:@"applying values from request ..."];
113     [methodObject takeValuesFromRequest:rq inContext:_ctx];
114   }
115
116   /* perform call */
117     
118   if (methodObject == nil || ![methodObject isCallable]) {
119     /*
120       The object is neither callable nor does it have a default method,
121       so we just pass it through.
122     */
123     resultObject = self->object;
124     if (debugOn) {
125       [self debugWithFormat:@"got no method, using object as result: %@", 
126               resultObject];
127     }
128   }
129   else {
130     resultObject = [methodObject callOnObject:[_ctx clientObject]
131                                  inContext:_ctx];
132     if (debugOn) {
133       if ([resultObject isKindOfClass:[WOResponse class]]) {
134         [self debugWithFormat:@"call produced response: 0x%08X (code=%i)", 
135                 resultObject, [(WOResponse *)resultObject status]];
136       }
137       else
138         [self debugWithFormat:@"call produced result: %@", resultObject];
139     }
140   }
141   
142   resultObject = [resultObject retain];
143   [pool release];
144   
145   /* deliver result */
146   return [resultObject autorelease];
147 }
148
149 /* logging */
150
151 - (NSString *)loggingPrefix {
152   return @"[obj-mth-dispatch]";
153 }
154 - (BOOL)isDebuggingEnabled {
155   return debugOn ? YES : NO;
156 }
157
158 /* description */
159
160 - (NSString *)description {
161   NSMutableString *ms;
162   
163   ms = [NSMutableString stringWithCapacity:64];
164   [ms appendFormat:@"<0x%08X[%@]:", self,
165         NSStringFromClass((Class)*(void**)self)];
166   
167   if (self->object)
168     [ms appendFormat:@" object=%@", self->object];
169   else
170     [ms appendString:@" <no object>"];
171   
172   [ms appendString:@">"];
173   return ms;
174 }
175
176 @end /* SoObjectMethodDispatcher */