decorateable._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2005 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: decorateable.pike,v 1.1 2008/03/31 13:39:57 exodusd Exp $
18  */
19 #include <macros.h>
20 #include <exception.h>
21 #include <classes.h>
22 #include <access.h>
23 #include <database.h>
24 #include <roles.h>
25 #include <attributes.h>
26 //! The decoration features of a sTeam object are implemented in this file.
27 //! Object uses it so any object inside a sTeam server features a list
28 //! of decorations. The functions to add and remove decorations are located
29 //! in Object and call the low level functions in this class.
30 class decorateable {
31 public:
32 
33 
34 
35 
36 
37  array aDecorations; // list of decorations
38 
39 string get_identifier();
40 void update_path();
41  void require_save(void|string ident, void|string index);
42 
43 /**
44  * Initialization of decorations on this object.
45  *
46  * @see add_decoration
47  * @see remove_decoration
48  */
49 private:
50  void init_decorations()
51 {
52  aDecorations = ({ });
53 }
54 
55 public:
56 
57 /**
58  * Add a decoration to this object. The decoration is identified by a path of
59  * the form: "server:/path-in-server-sandbox" or "object:/object-path" or
60  * "object:#object-id". An instance of the decoration will be provided and
61  * attached to the proxy of this object.
62  *
63  * @param string path the path to the decoration source code
64  * @return true if the decoration could be successfully added, false if not
65  * @see remove_decoration
66  */
67 protected:
68  bool add_decoration ( string path )
69 {
70  if ( !stringp(path) || path == "" )
71  THROW( "Trying to add decoration with empty path !", E_ERROR );
72  LOG( "Adding decoration: " + path + " to "+ get_identifier() );
73  return do_add_decoration( path );
74 }
75 
76 public:
77 
78 protected:
79  bool do_add_decoration ( string path )
80 {
81  if ( search( aDecorations, path ) >= 0 )
82  steam_error( "add_decoration: Decoration already on %O\n", get_identifier() );
83 
84  aDecorations += ({ path });
85 
86  require_save( STORE_DECORATIONS );
87  return true;
88 }
89 
90 public:
91 
92 protected:
93  object load_decoration ( string path )
94 {
95  string type, decoration_path, decorator_content;
96 
97  if ( ! stringp(path) )
98  steam_error( "No decoration given!\n" );
99 
100  if (sscanf(path, "%s:%s", type, decoration_path) != 2) {
101  decoration_path = path;
102  type = "object";
103  }
104 
105  if ( !stringp(decoration_path) || decoration_path == "" )
106  steam_error( "No decoration given!\n" );
107 
108  switch ( lower_case( type ) ) {
109 
110  case "server":
111  string sandbox_path = _Server->get_sandbox_path();
112  decorator_content = Stdio.read_file( sandbox_path + decoration_path );
113  if ( !stringp(decorator_content) )
114  steam_error( "Failed to find decoration object in server dir (%s):" +
115  " %s\n", sandbox_path, decoration_path );
116  break;
117 
118  case "file":
119  case "object":
120  default:
121  if ( decoration_path[0] == '#' ) {
122  int id = (int)(decoration_path[1..]);
123  object co = find_object( id );
124  if ( !objectp(co) )
125  steam_error( "Failed to find decoration object with id %d\n", id );
126  decorator_content = co->get_content();
127  }
128  else {
129  object co = OBJ( decoration_path );
130  if ( !objectp(co) )
131  steam_error( "Failed to find decoration object in %s\n",
132  decoration_path );
133  decorator_content = co->get_content();
134  }
135  break;
136  }
137 
138  if ( !stringp(decorator_content) || sizeof(decorator_content) == 0 )
139  steam_error( "Decoration has no content: %s\n", path );
140 
141  program p;
142  mixed err = catch( p = compile_string( decorator_content ) );
143  if ( err ) {
144  werror( "Failed to compile decoration: %s\n", path );
145  throw( err );
146  }
147  /*
148  if ( ! Program.implements( p, pApi ) )
149  steam_error( "Decoration program does not implement decoration api, " +
150  "should implement get_decoration_class() !\n" );
151  */
152 
153  if ( objectp(decoration_obj) )
154  return decoration_obj;
155  return 0;
156 }
157 
158 public:
159 
160 /**
161  * Removes a decoration from the object. This function just removes
162  * the decoration path from the list of decorations.
163  *
164  * @param string path the decoration path to remove
165  * @return true if the decoration was successfully removed, false otherwise
166  * @see add_decoration
167  */
168 protected:
169  bool remove_decoration ( string path )
170 {
171  if ( search( aDecorations, path ) == -1 )
172  THROW( "Decoration " + path + " not present on object !", E_ERROR );
173 
174  aDecorations -= ({ path });
175 
176  require_save( STORE_DECORATIONS );
177  return true;
178 }
179 
180 public:
181 
182 /**
183  * This function returns a copied list of all decorations of this
184  * object.
185  *
186  * @return the array of decorations
187  */
188 array get_decorations ()
189 {
190  return copy_value( aDecorations );
191 }
192 
193 /**
194  * Checks whether this object has a certain decoration.
195  *
196  * @param path the decoration path
197  * @return true if the object has this decoration, false if not
198  */
199 bool has_decoration ( string path )
200 {
201  return search( aDecorations, path ) >= 0;
202 }
203 
204 /**
205  * Retrieve decorations for storing them in the database.
206  * Only the global _Database object is able to call this function.
207  *
208  * @return mapping of object data.
209 private:
210  * @see restore_decorations
211  */
212 private:
213 final mapping retrieve_decorations ()
214 {
215  if ( CALLER != _Database )
216  THROW( "Caller is not the database object !", E_ACCESS );
217 
218  return ([ "Decorations" : aDecorations ]);
219 }
220 
221 public:
222 
223 /**
224  * Called by database to restore the object data again upon loading.
225  *
226  * @param mixed the object data
227 private:
228  * @see retrieve_decorations
229  */
230 private:
231 final void restore_decorations ( mixed data )
232 {
233  if ( CALLER != _Database )
234  THROW( "Caller is not the database object !", E_ACCESS );
235 
236  aDecorations = data[ "Decorations" ];
237  if ( !arrayp(aDecorations) ) {
238  aDecorations = ({ });
239  require_save( STORE_DECORATIONS );
240  }
241 }
242 
243 public:
244 
245 
246 };