]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOComponentReference.m
minor improvement to WOHttpAdaptor, bumped framework revisions
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOComponentReference.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #include "WOComponentReference.h"
23 #include "WOElement+private.h"
24 #include "WOContext+private.h"
25 #include "WOComponent+private.h"
26 #include "decommon.h"
27
28 @interface WOContext(ComponentStackCount)
29 - (unsigned)componentStackCount;
30 @end
31
32 @implementation WOComponentReference
33
34 static int   profileComponents = -1;
35 static BOOL  coreOnRecursion   = NO;
36 static BOOL  debugOn           = NO;
37 static Class NSDateClass = Nil;
38
39 + (void)initialize {
40   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
41   
42   profileComponents = [[ud objectForKey:@"WOProfileComponents"]
43                            boolValue] ? 1 : 0;
44   coreOnRecursion = [ud boolForKey:@"WOCoreOnRecursiveSubcomponents"];
45   NSDateClass = [NSDate class];
46 }
47
48 - (id)initWithName:(NSString *)_name
49   associations:(NSDictionary *)_config
50   template:(WOElement *)_c
51 {
52   if ((self = [super initWithName:_name associations:_config template:_c])) {
53     self->containsForm    = YES;
54     self->activeComponent = OWGetProperty(_config, @"component");
55     self->bindings        = [_config copyWithZone:[self zone]];
56     [(NSMutableDictionary *)_config removeAllObjects];
57     
58     self->template = [_c retain];
59   }
60   return self;
61 }
62
63 - (void)dealloc {
64   [self->template        release];
65   [self->bindings        release];
66   [self->activeComponent release];
67   [self->child           release];
68   [super dealloc];
69 }
70
71 /* accessors */
72
73 - (WOComponent *)childComponent {
74   return self->child; // THREAD
75 }
76
77 static inline void
78 _updateComponent(WOComponentReference *self, WOContext *_ctx)
79 {
80   /*
81     Note: this is rather dangerous. We keep a processing state - the 'child'
82           ivar containing the component - inside the dynamic element. Yet
83           elements are supposed to be stateless.
84           
85           As long as we are single-threaded this should not be a problem, but
86           keep in mind that this element is NOT reentrant.
87   */
88   // THREAD
89   WOComponent *newChild;
90   
91   if (self->activeComponent == nil)
92     return;
93
94   newChild = [self->activeComponent valueInComponent:[_ctx component]];
95 #if 0
96   if (newChild == nil) {
97     [[_ctx component] logWithFormat:
98                         @"missing child (got nil) "
99                         @"(element=%@, association=%@, component=%@).",
100                         self, self->activeComponent,
101                         [[_ctx component] name]];
102   }
103 #endif
104     
105   if (newChild != self->child) { // THREAD
106 #if 0
107     NSLog(@"switched component %@ => %@ ...",
108           [self->child name], [newChild name]);
109 #endif
110     ASSIGN(self->child, newChild);
111     [newChild setParent:[_ctx component]];
112     [newChild setBindings:self->bindings];
113   }
114 }
115
116 /* handling requests */
117
118 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
119   WOComponent *parent;
120
121   parent = [_ctx component];
122   
123   _updateComponent(self, _ctx);
124
125   if (self->child != nil) {
126     [_ctx enterComponent:self->child content:self->template];
127     [self->child takeValuesFromRequest:_req inContext:_ctx];
128     [_ctx leaveComponent:self->child];
129   }
130 }
131
132 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
133   WOComponent *parent;
134   id result    = nil;
135
136   parent = [_ctx component];
137
138   _updateComponent(self, _ctx);
139
140   if (self->child != nil) {
141     [_ctx enterComponent:self->child content:self->template];
142     result = [self->child invokeActionForRequest:_req inContext:_ctx];
143     [_ctx leaveComponent:self->child];
144   }
145   
146   return result;
147 }
148
149 /* generate response */
150
151 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
152   WOComponent *parent;
153   
154   parent = [_ctx component];
155   
156   _updateComponent(self, _ctx);
157   
158   if (self->child == parent) {
159     [self warnWithFormat:@"recursive call of component: %@", parent];
160     if (coreOnRecursion)
161       abort();
162   }
163   
164   if (self->child != nil) {
165     NSTimeInterval st = 0.0;
166
167     if (profileComponents)
168       st = [[NSDateClass date] timeIntervalSince1970];
169     
170     [_ctx enterComponent:self->child content:self->template];
171     [self->child appendToResponse:_response inContext:_ctx];
172     [_ctx leaveComponent:self->child];
173
174     if (profileComponents) {
175       NSTimeInterval diff;
176       int i;
177       diff = [[NSDateClass date] timeIntervalSince1970] - st;
178       for (i = [_ctx componentStackCount]; i >= 0; i--)
179         printf("  ");
180       printf("[%s %s]: %0.3fs\n",
181              [[child name] cString], 
182 #if APPLE_RUNTIME || NeXT_RUNTIME
183              sel_getName(_cmd), 
184 #else
185              sel_get_name(_cmd), 
186 #endif
187              diff);
188     }
189   }
190   else if (debugOn) {
191     [self debugWithFormat:@"missing component for reference: %@",
192             self->activeComponent];
193     [_response appendContentHTMLString:@"[missing component for reference: "];
194     [_response appendContentHTMLString:[self->activeComponent description]];
195     [_response appendContentHTMLString:@"]"];
196   }
197 }
198
199 /* description */
200
201 - (NSString *)description {
202   NSMutableString *desc;
203   
204   desc = [NSMutableString stringWithCapacity:64];
205   [desc appendFormat:@"<%@[0x%08X]:", NSStringFromClass([self class]), self];
206   
207   if (self->child != nil) {
208     [desc appendFormat:@" child=%@[0x%08X] childName=%@",
209             NSStringFromClass([self->child class]),
210             self->child, [self->child name]];
211   }
212   
213   [desc appendString:@">"];
214   return desc;
215 }
216
217 @end /* WOComponentReference */