]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WOScriptedComponent.m
fixed OGo bug #888
[sope] / sope-appserver / NGObjWeb / WOScriptedComponent.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
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: WOScriptedComponent.m 1 2004-08-20 10:08:27Z znek $
22
23 #include "WOScriptedComponent.h"
24 #include <NGObjWeb/WOTemplateBuilder.h>
25 #include <NGScripting/NGScriptLanguage.h>
26 #include "common.h"
27
28 @interface NSObject(misc)
29 - (void)applyStandardClasses;
30 - (BOOL)isScriptFunction;
31
32 - (id)callScriptFunction:(NSString *)_name withObject:(id)_arg0;
33 - (id)evaluateScript:(NSString *)_script source:(NSString *)_s line:(int)_line;
34
35 @end
36
37 @interface WOComponent(UsedPrivates)
38 - (id)initWithName:(NSString *)_cname
39   template:(WOTemplate *)_template
40   inContext:(WOContext *)_ctx;
41 @end
42
43 @interface WOComponentScript(UsedPrivates)
44 - (id)initScriptWithComponent:(id)_comp;
45 @end
46
47 @implementation WOScriptedComponent
48
49 static BOOL logScriptKVC     = NO;
50 static BOOL logScriptInit    = NO;
51 static BOOL logScriptDealloc = NO;
52
53 + (void)initialize {
54   static BOOL didInit = NO;
55   if (!didInit) {
56     NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
57     didInit = YES;
58     logScriptKVC     = [ud boolForKey:@"WOLogScriptKVC"];
59     logScriptInit    = [ud boolForKey:@"WOLogScriptInit"];
60     logScriptDealloc = [ud boolForKey:@"WOLogScriptDealloc"];
61   }
62 }
63
64 - (id)initWithName:(NSString *)_cname
65   template:(WOTemplate *)_template
66   inContext:(WOContext *)_ctx
67 {
68   if ((self = [super initWithName:_cname template:_template inContext:_ctx])) {
69     self->script = [[_template componentScript] retain];
70
71     self->language = 
72       [[NGScriptLanguage languageWithName:[self->script language]] retain];
73     if (self->language == nil) {
74       [self logWithFormat:
75               @"did not find engine for script language %@", 
76               [self->script language]];
77       RELEASE(self);
78       return nil;
79     }
80     
81     if ((self->shadow = [self->language createShadowForMaster:self]) == nil) {
82       [self logWithFormat:
83               @"could not create shadow for component in language %@", 
84               self->language];
85       RELEASE(self);
86       return nil;
87     }
88     
89     if ([self->shadow respondsToSelector:@selector(applyStandardClasses)])
90       [(id)self->shadow applyStandardClasses];
91     
92     [self->script initScriptWithComponent:self];
93     
94     if (logScriptInit)
95       [self logWithFormat:@"created scripted component: %@", self];
96   }
97   return self;
98 }
99
100 - (void)dealloc {
101   if (logScriptDealloc)
102     [self logWithFormat:@"will dealloc scripted component: %@", self];
103   
104   [self->shadow invalidateShadow]; /* ensure shadow is dead ;-) */
105   RELEASE(self->shadow);
106   RELEASE(self->language);
107   RELEASE(self->script);
108   RELEASE(self->template);
109   [super dealloc];
110 }
111
112 /* accessors */
113
114 - (void)setTemplate:(id)_template {
115   ASSIGN(self->template, _template);
116 }
117 - (WOElement *)_woComponentTemplate {
118   return self->template;
119 }
120
121 - (BOOL)isScriptedComponent {
122   return YES;
123 }
124
125 /* scripting */
126
127 - (id)evaluateScript:(NSString *)_script language:(NSString *)_lang 
128   source:(NSString *)_src line:(unsigned)_line
129 {
130   return [self->shadow evaluateScript:_script source:_src line:_line];
131 }
132
133 /* notification mapping */
134
135 - (void)awake {
136   [super awake];
137   
138   if ([self->shadow hasFunctionNamed:@"awake"])
139     [self->shadow callScriptFunction:@"awake"];
140 }
141 - (void)sleep {
142   if ([self->shadow hasFunctionNamed:@"sleep"])
143     [self->shadow callScriptFunction:@"sleep"];
144   
145   //[self debugWithFormat:@"vars: %@", [self variableDictionary]];
146   [super sleep];
147 }
148
149 /* script properties */
150
151 - (BOOL)takeValue:(id)_value forJSPropertyNamed:(NSString *)_key {
152   NSAssert1(self->shadow, @"missing shadow for component %@", self);
153   [self->shadow setObject:_value forKey:_key];
154   return YES;
155 }
156 - (id)valueForJSPropertyNamed:(NSString *)_key {
157   [self debugWithFormat:@"value for prop %@", _key];
158   NSAssert1(self->shadow, @"missing shadow for component %@", self);
159   return [self->shadow objectForKey:_key];
160 }
161
162 /* extra variables */
163
164 - (void)setObject:(id)_obj forKey:(NSString *)_key {
165   //[self debugWithFormat:@"setObject:%@ forKey:%@", _obj, _key];
166   NSAssert1(self->shadow, @"missing shadow for component %@", self);
167   [self->shadow setObject:_obj forKey:_key];
168 }
169 - (id)objectForKey:(NSString *)_key {
170   NSAssert1(self->shadow, @"missing shadow for component %@", self);
171   return [self->shadow objectForKey:_key];
172 }
173
174 /* key-value coding */
175
176 - (void)takeValue:(id)_value forKey:(NSString *)_key {
177   NSString *funcName;
178   id       func;
179   unsigned len;
180   unsigned char *buf;
181   
182   len = [_key cStringLength];
183   buf = malloc(len + 4);
184   [_key getCString:&(buf[3])];
185   buf[0] = 's'; buf[1] = 'e'; buf[2] = 't';
186   buf[len + 3] = '\0';
187   if (len > 0) buf[3] = toupper(buf[3]);
188   funcName = [NSString stringWithCString:buf length:(len + 3)];
189   free(buf);
190   
191   if ((func = [self->shadow objectForKey:funcName])) {
192     if ([func isScriptFunction]) {
193       id result;
194       
195       if (logScriptKVC) {
196         [self logWithFormat:@"KVC: for key %@ call %@(%@)", 
197                 _key, funcName, _value];
198       }
199       
200       result = [self->shadow callScriptFunction:funcName withObject:_value];
201     }
202     else {
203       [self logWithFormat:
204               @"KVC: object stored at '%@' is not a function, "
205               @"could not set value for key %@ !",
206               funcName, _key];
207     }
208   }
209   else {
210     if (logScriptKVC) {
211       [self logWithFormat:@"KVC: assign %@=%@ (no func '%@')", 
212               _key, _value, funcName];
213     }
214     
215     [self->shadow setObject:_value forKey:_key];
216   }
217 }
218
219 - (id)valueForKey:(NSString *)_key {
220   id obj;
221   
222   //[self logWithFormat:@"script: valueForKey:%@", _key];
223   
224   if ((obj = [self->shadow objectForKey:_key])) {
225     if ([obj isScriptFunction]) {
226       if (logScriptKVC) {
227         [self logWithFormat:@"KVC: for key %@ call %@", 
228                 _key, _key];
229       }
230       obj = [self->shadow callScriptFunction:_key];
231     }
232     else {
233       if (logScriptKVC) {
234         [self logWithFormat:@"KVC: valueForKey(%@): %@", 
235                 _key, obj];
236       }
237     }
238     return obj;
239   }
240   else {
241     if (logScriptKVC) {
242       [self logWithFormat:@"KVC: get value for key %@ from WOComponent", 
243               _key];
244     }
245     return [super valueForKey:_key];
246   }
247 }
248
249 /* logging */
250
251 - (NSString *)loggingPrefix {
252   return [NSString stringWithFormat:@"script<%@>[0x%08X]", [self name], self];
253 }
254
255 @end /* WOScriptedComponent */
256
257 @implementation WOScriptedComponent(JSSupport)
258
259 - (id)_jsfunc_FileManager:(NSArray *)_args {
260   return [NSFileManager defaultManager];
261 }
262
263 @end /* WOScriptedComponent(JSSupport) */
264
265 @implementation NSObject(ScriptFunc)
266
267 - (BOOL)isScriptFunction {
268   return NO;
269 }
270
271 @end /* NSObject(ScriptFunc) */