package._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: package.pike,v 1.1 2008/03/31 13:39:57 exodusd Exp $
18  */
19 inherit "module";
20 #include <macros.h>
21 #include <database.h>
22 #include <classes.h>
23 #include <attributes.h>
24 #include <types.h>
25 #include <events.h>
26 class package : public module{
27 public:
28 
29 
30 
31 
32 import Attributes;
33 
34 
35 
36 /**
37  * Constructor for a module initializes the package attributes.
38  *
39  */
40 protected:
41  void create_module()
42 {
43  ::create_module();
44 
45 }
46 
47 public:
48 
49 
50 /**
51  * Callback function for package initialization code.
52  *
53  */
54 private:
55  void init_package()
56 {
57  set_attribute("package:components", ([ ]) );
58  set_attribute("package:log", ({ }) );
59  set_attribute("package:factories", ([ ]) );
60  set_attribute("package:classes", ([ ]) );
61  set_attribute("package:class_ids", 1);
62 }
63 
64 public:
65 
66 
67 /**
68 private:
69  * Initialize the module and call the init_package function.
70  *
71 private:
72  * @see init_package
73  */
74 private:
75  void init_module()
76 {
77  ::init_module();
78  init_package();
79 }
80 
81 public:
82 
83 
84 /**
85  * The package was loaded. Callback function.
86  *
87  */
88 protected:
89  void load_package()
90 {
91 }
92 
93 public:
94 
95 
96 /**
97  * Load the module. Calls load_package.
98  *
99  */
100 protected:
101  void load_module()
102 {
103  if ( !mappingp(query_attribute("package:factories")) )
104  set_attribute("package:factories", ([ ]) );
105  if ( !mappingp(query_attribute("package:classes")) )
106  set_attribute("package:classes", ([ ]) );
107  if ( query_attribute("package:class_ids") == 0 )
108  set_attribute("package:class_ids", 1);
109 
110  load_package();
111 }
112 
113 public:
114 
115 
116 /**
117  * This function will be called when the package is being installed.
118  *
119  */
120 protected:
121  void install_package(string source, string|void version)
122 {
123 }
124 
125 public:
126 
127 
128 /**
129  * This function will be called when the package is being uninstalled.
130  */
131 protected:
132  void uninstall_package ()
133 {
134 }
135 
136 public:
137 
138 
139 /**
140  * Function called when the package is uninstalled.
141  *
142  */
143 protected:
144  void uninstall()
145 {
146  uninstall_package();
147  mixed val;
148  mixed comps = do_query_attribute("package:components") || ([ ]);
149 
150  foreach ( indices(comps), string comp )
151  {
152  if ( objectp(val=comps[comp]) )
153  {
154  if ( val->get_object_class() & CLASS_OBJECT )
155  val->delete();
156  }
157  else if ( intp(val) && val == 1 )
158  {
159  // this wont happen I guess...
160  LOG("Removing file " + comp);
161  rm(comp);
162  }
163  }
164 }
165 
166 public:
167 
168 
169 /**
170  * Package uninstallation function calls uninstall().
171  *
172  * @return 0 or 1.
173  * @see uninstall
174  */
175 int pck_uninstall()
176 {
177  LOG("pck_uninstall()");
178  uninstall();
179  return 1;
180  }
181  return 0;
182 }
183 
184 
185 /*
186 protected:
187  void delete_object ()
188 {
189  try_event( EVENT_DELETE, CALLER );
190  mixed err = catch( uninstall() );
191  if ( err ) werror( "%s\n%O\n", err[0], err[1] );
192  ::delete_object();
193 }
194 
195 public:
196 */
197 
198 
199 /**
200  * Can be called in order to update the packet. This is used by the web-package
201  * for example.
202  *
203  */
204 string pck_update()
205 {
206 }
207 
208 
209 /**
210  * Called when the package is installed and calls install_package().
211  * This function is called by the database.
212  *
213  * @param string source - the source directory to copy files from.
214  * @return 0 or 1.
215  * @see pck_install
216  */
217 int install(string source, string|void version)
218 {
219  LOG("Installing package !");
220  if ( CALLER != _Database )
221  THROW("Caller must be the sTeam Server !", E_ACCESS);
222 
223 
224  mixed err = catch {
225  install_package(source, version);
226  };
227  if ( err != 0 ) {
228  MESSAGE("Error while installing package: \n"+
229  err[0]+"\n"+
230  PRINT_BT(err));
231  uninstall();
232  throw(err);
233  }
234  return 1;
235 }
236 
237 
238 /**
239  * Add something to the package log attribute.
240  *
241  * @param string str - the string to log
242  */
243 protected:
244  void pck_log(string str)
245 {
246 }
247 
248 public:
249 
250 
251 /**
252  * Get the logged string array for this package.
253  *
254  * @return Array of logged string messages.
255  */
256 array
257 pck_get_log()
258 {
259 }
260 
261 
262 /**
263  * Add a component to this package. This function is usually
264  * used when the package is installed.
265  *
266  * @param string desc - description of the component.
267  * @param object obj - the component to add.
268  * @param string|void fname - the file name of the component inside steam.
269  */
270 protected:
271  void add_component(string desc, object obj,string|void fname)
272 {
273  mixed err;
274 
275  do_append_attribute("package:components",([desc : obj ]));
276  if ( obj->get_object_class() & CLASS_DOCLPC ) {
277  object script = get_component("/scripts/"+fname);
278  array instances = obj->get_instances();
279 
280  if ( stringp(fname) && objectp(script) &&
281  script->get_identifier() == fname &&
282  search(instances, script) >= 0 )
283  {
284  pck_log("Upgrading script: " + fname);
285  if ( objectp(obj->get_object()) )
286  master()->upgrade(object_program(obj->get_object()));
287  add_component("/scripts/"+fname, script, fname);
288  }
289  else {
290  if ( objectp(script) ) {
291  // something is horrible wrong !
292  // script exists, but not in instances
293  pck_log("Replacing script " + fname);
294  err = catch {
295  script->delete();
296  };
297  if ( err != 0 )
298  pck_log("Error while deleting old script");
299  }
300  LOG("Creating new script:" + fname);
301  err = catch {
302  script = obj->execute( ([ "name": fname, ]) );
303  object scripts = _FILEPATH->path_to_object("/scripts");
304  script->move(scripts);
305  pck_log("Created new script:" + fname + " from " +
306  master()->describe_object(obj) + " (Instances:"+
307  sizeof(obj->get_instances())+")");
308  };
309  if ( err != 0 )
310  pck_log("Failed to create script: " + fname);
311  }
312  if ( objectp(script) )
313  add_component("/scripts/"+fname, script);
314  }
315 }
316 
317 public:
318 
319 
320 /**
321  * Get a component by its description.
322  *
323  * @param string desc - description of the component to find.
324  * @return the found component.
325  */
326 object
327 get_component(string desc)
328 {
329  return do_query_attribute("package:components")[desc];
330 }
331 
332 
333 /**
334  * Get all registered component of this package.
335  *
336  * @return mapping of components.
337  */
338 mapping get_components()
339 {
340  return copy_value(do_query_attribute("package:components"));
341 }
342 
343 
344 /**
345  * Register an attribute inside object obj and set its default value
346  * and acquireing.
347  *
348  * @param object obj - the object to register the attribute.
349  * @param int|string key - the key of the attribute.
350  * @param mixed def - the attributes default value.
351  */
352 protected:
353  void
354 pck_reg_attribute(object obj, int|string key, mixed def, mixed acq)
355 {
356  if ( stringp(acq) && acq == REG_ACQ_ENVIRONMENT )
357  obj->set_acquire_attribute(key, obj->get_environment);
358  else if ( objectp(acq) ) {
359  if ( obj->get_object_id() != acq->get_object_id() )
360  obj->set_acquire_attribute(key, acq);
361  else
362  obj->set_acquire_attribute(key, 0);
363  }
364  LOG("Setting value for "+ obj->get_identifier() + ",key="+key+",value="+
365  (objectp(def) ? def->get_identifier():"?"));
366  obj->set_attribute(key, def);
367 }
368 
369 public:
370 
371 
372 /**
373  * Provide an attribute for a class or one object, CLASS_ANY also includes
374  * all modules
375  *
376  * @param object_class - an object or a class of objects, CLASS any for all
377  * @param key - the attribute key
378  * @param desc - the description of this attribute
379  * @param cntrl - the control registration info,CONTROL_ATTR_USER|SERVER|CLIENT
380  * @param perm - permission for the attribute: ATTR_FREE_READ|WRITE|RESTRICTED
381  * @param def - the default value of an attribute,
382  * only set if attribute is not acquired
383  * @param acq - acquiring information, nothing, an object or and integer for
384  * setting acquiring to the objects environment
385  * @param obj_def - the default object from that is acquired - this object
386  * will contain the default value for the attribute (see def)
387  * @see kernel/factory.register_attributes
388  */
389 protected:
390  void
391 provide_attribute(int|object object_class, int|string key,int type,string desc,
392  int read_event, int write_event, string|object|void acq,
393  int cntrl, mixed def, void|object obj_def)
394 {
395  object factory;
396 
397  if ( intp(object_class) )
398  {
399  factory = _Server->get_factory(object_class);
400  Attribute pattr = factory->describe_attribute(key);
401  Attribute attr = Attribute(key, desc, type, def, acq, cntrl,
402  read_event, write_event);
403 
404  if ( !objectp(pattr) || pattr != attr )
405  {
406  factory->register_attribute(attr);
407  }
408  }
409  else
410  pck_reg_attribute(object_class, key, def, acq);
411 
412  if ( objectp(obj_def) )
413  pck_reg_attribute(obj_def, key, def, acq);
414 }
415 
416 public:
417 
418 
419 /**
420  * Add a new class handled by this package.
421  *
422  * @param int id - the class id
423  * @param object factory - the factory handling the class
424  * @param void|bool force - overwrite existing classes
425  */
426 void add_class(int id, object factory, void|bool force)
427 {
428  mapping mFactories = query_attribute("package:factories");
429 
430  if ( !force && objectp(mFactories[id]) )
431  THROW("Class is already defined !", E_ERROR);
432 
433  mFactories[id] = factory;
434  set_attribute("package:factories", mFactories);
435 }
436 
437 
438 /**
439  * Register a new class and get the id for it.
440  *
441  * @param string name - the name of the class
442  * @return the class id for the class
443  */
444 int register_class(string name)
445 {
446  mapping mClasses = query_attribute("package:classes");
447  int id = query_attribute("package:class_ids");
448  mClasses[name] = id;
449  set_attribute("package:classes", mClasses);
450  set_attribute("package:class_ids", (id<<1));
451 }
452 
453 
454 /**
455  * Get the class id for a given class.
456  *
457  * @param string name - the name of the class.
458  * @return the class id or 0 if not registered.
459  */
460 int get_class_id(string name)
461 {
462  mapping mClasses = query_attribute("package:classes");
463  return mClasses[name];
464 }
465 
466 
467 /**
468  * Get the mapping of classes handled by this package.
469  *
470  * @return mapping of classes, index is class id and value is the factory.
471  */
472 mapping get_classes()
473 {
474  return query_attribute("package:factories");
475 }
476 
477 
478 mixed get_config ( string key )
479 {
480  object config = get_config_object();
481  if ( !objectp(config) ) return UNDEFINED;
482  return config->get_config( key );
483 }
484 
485 
486 mapping get_configs ( array|void configs )
487 {
488  object config = get_config_object();
489  if ( !objectp(config) ) return UNDEFINED;
490  return config->get_configs( configs );
491 }
492 
493 
494 mixed set_config ( string key, mixed value )
495 {
496  object config = get_config_object( 1 );
497  if ( !objectp(config) ) return UNDEFINED;
498  return config->set_config( key, value );
499 }
500 
501 
502 mapping set_configs ( mapping configs )
503 {
504  object config = get_config_object( 1 );
505  if ( !objectp(config) ) return UNDEFINED;
506  return config->set_configs( configs );
507 }
508 
509 
510 object get_config_object ( int|void create_if_missing )
511 {
512  object config = OBJ( "/config/packages/" + get_identifier() );
513  if ( objectp(config) || !create_if_missing ) return config;
514  object package_configs = OBJ( "/config/packages" );
515  if ( !objectp(package_configs) ) return UNDEFINED;
516  config = get_factory( CLASS_DOCUMENT )->execute( ([
517  "name" : get_identifier(),
518  "mimetype" : "application/x-steam-config",
519  ]) );
520  if ( !objectp(config) ) return UNDEFINED;
521  if ( !config->move( package_configs ) ) {
522  config->delete();
523  return UNDEFINED;
524  }
525  get_module( "decorator" )->add_decoration( config, "server:/decorations/Config.pike" );
526  config->set_attribute( OBJ_TYPE, "object_config_package" );
527  return config;
528 }
529 
530 
531 int get_object_class() { return ::get_object_class() | CLASS_PACKAGE | CLASS_SCRIPT; }
532 string get_version() { return do_query_attribute(PACKAGE_VERSION); }
533 
534 
535 };