00001 /* 00002 * Copyright (C) 2003-2009 Olivier Boudeville 00003 * 00004 * This file is part of the Ceylan library. 00005 * 00006 * The Ceylan library is free software: you can redistribute it and/or modify 00007 * it under the terms of either the GNU Lesser General Public License or 00008 * the GNU General Public License, as they are published by the Free Software 00009 * Foundation, either version 3 of these Licenses, or (at your option) 00010 * any later version. 00011 * 00012 * The Ceylan library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License and the GNU General Public License 00016 * for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License and the GNU General Public License along with the Ceylan library. 00020 * If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 * Author: Olivier Boudeville (olivier.boudeville@esperide.com) 00023 * 00024 */ 00025 00026 00027 #include "CeylanObject.h" 00028 00029 #include "CeylanProcess.h" // for getHostingPID 00030 #include "CeylanTextIdentifier.h" 00031 #include "CeylanOperators.h" 00032 #include "CeylanLogLight.h" // for CEYLAN_LOG 00033 #include "CeylanLogPlug.h" // for LogPlug 00034 #include "CeylanObjectIdentifier.h" // for constructor 00035 #include "CeylanIdentifier.h" // for IdentifierException 00036 00037 00038 #ifdef CEYLAN_USES_CONFIG_H 00039 #include "CeylanConfig.h" // for CEYLAN_DEBUG 00040 #endif // CEYLAN_USES_CONFIG_H 00041 00042 00043 #include <typeinfo> // for typeid 00044 #include <cctype> // for isdigit 00045 00046 00047 using std::string ; 00048 00049 using namespace Ceylan ; 00050 using namespace Ceylan::Log ; 00051 00052 00053 00054 Object::Object( bool trackInstance, bool dropIdentifierOnExit ) : 00055 IdentifierOwner(), 00056 Loggable( "Unknown object" ), 00057 _trackInstance( trackInstance ) 00058 { 00059 00060 00061 CEYLAN_LOG( "Ceylan::Object entering constructor" ) ; 00062 00063 if ( _trackInstance ) 00064 { 00065 00066 CEYLAN_LOG( "Object sending its first message " 00067 "just after allocation." ) ; 00068 00069 send( "Being allocated now." ) ; 00070 00071 /* 00072 * Used to force rebuilding of its identifier so that it 00073 * is not mangled: 00074 * 00075 */ 00076 if ( dropIdentifierOnExit ) 00077 dropIdentifier() ; 00078 00079 } 00080 00081 } 00082 00083 00084 00085 Object::~Object() throw() 00086 { 00087 00088 if ( _trackInstance ) 00089 { 00090 00091 CEYLAN_LOG( 00092 "Object sending its last message just before deallocation." ) ; 00093 00094 send( "Being deallocated now." ) ; 00095 00096 } 00097 00098 } 00099 00100 00101 00102 const std::string Object::getClassName() const 00103 { 00104 00105 string className = typeid( * this ).name() ; 00106 00107 /* 00108 * On g++, this name is prefixed with the length in characters of the name 00109 * (Log would be 3Log), so we remove this numerical prefix. 00110 * 00111 */ 00112 00113 Ceylan::Uint16 i = 0 ; 00114 00115 while ( ::isdigit( className[ i ] ) ) 00116 i++ ; 00117 00118 /* 00119 * With Visual C++ 2005 compiler, class names start with 'class ', 00120 * we remove this mostly useless prefix. 00121 * 00122 */ 00123 const string toRemove = "class " ; 00124 string::size_type pos = className.find( toRemove, 00125 /* starting position */ 0) ; 00126 00127 if ( pos != string::npos && pos == 0 ) 00128 className = className.substr( toRemove.size() ) ; 00129 00130 string result = className.substr( i ) ; 00131 00132 CEYLAN_LOG( "Object::getClassName is: " + result ) ; 00133 00134 return result ; 00135 00136 } 00137 00138 00139 00140 bool Object::isOfSameType( const Object & other ) const 00141 { 00142 00143 return ( getClassName() == other.getClassName() ) ; 00144 00145 } 00146 00147 00148 00149 void Object::logState( Ceylan::VerbosityLevels level ) 00150 { 00151 00152 send( toString( level ) ) ; 00153 00154 } 00155 00156 00157 00158 void Object::send( const string & message, LevelOfDetail levelOfDetail ) 00159 { 00160 00161 CEYLAN_LOG( "Object::send: will send message " + message ) ; 00162 00163 if ( ! hasIdentifier() ) 00164 { 00165 00166 try 00167 { 00168 forgeIdentifier() ; 00169 } 00170 catch( const Identifier::IdentifierException & e ) 00171 { 00172 throw LogException( "Object::send failed: " + e.toString() ) ; 00173 00174 } 00175 00176 CEYLAN_LOG( "Object::send: channel name set to " 00177 + getIdentifier().toString() ) ; 00178 00179 setChannelName( getIdentifier().toString() ) ; 00180 00181 } 00182 00183 CEYLAN_LOG( "Object::send: effective sending of message " + message ) ; 00184 00185 Loggable::send( message, levelOfDetail ) ; 00186 00187 } 00188 00189 00190 00191 const string Object::toString( Ceylan::VerbosityLevels level ) const 00192 { 00193 00194 string result ; 00195 00196 if ( _trackInstance ) 00197 result = "This Ceylan object instance's life cycle is monitored. " ; 00198 else 00199 result = "No monitoring for this Ceylan object " 00200 "instance's life cycle. " ; 00201 00202 result += Loggable::toString( level ) + ". " 00203 + IdentifierOwner::toString( level ) ; 00204 00205 return result ; 00206 00207 } 00208 00209 00210 00211 void Object::forgeIdentifier() 00212 { 00213 00214 CEYLAN_LOG( "Object::forgeIdentifier: new identifier required." ) ; 00215 00216 if ( hasIdentifier() ) 00217 dropIdentifier() ; 00218 00219 CEYLAN_LOG( "Object::forgeIdentifier: creating new object identifier." ) ; 00220 00221 ObjectIdentifier * newID ; 00222 00223 /* 00224 * This was the place where using this instead of *this caused 00225 * the object constructor to be mistakenly called 00226 * (this pointer being converted to bool, and Object constructor 00227 * had not the explicit keyword). 00228 * 00229 */ 00230 try 00231 { 00232 00233 newID = new ObjectIdentifier( * this ) ; 00234 00235 } 00236 catch( const Identifier::IdentifierException & e ) 00237 { 00238 throw Log::LogException( "Object::forgeIdentifier: " + e.toString() ) ; 00239 } 00240 00241 00242 try 00243 { 00244 00245 setIdentifier( *newID ) ; 00246 00247 } 00248 catch( const IdentifierNotAvailableException & e ) 00249 { 00250 throw Log::LogException( "Object::forgeIdentifier: " + e.toString() ) ; 00251 } 00252 00253 00254 CEYLAN_LOG( "Object::forgeIdentifier: new ID is " 00255 + getIdentifier().toString() ) ; 00256 00257 } 00258 00259 00260 00261 void Object::dropIdentifier() 00262 { 00263 00264 deleteIdentifier() ; 00265 00266 } 00267