public function schema($dn = null)
    {
        // Schema caching by Knut-Olav Hoven
        // If a schema caching object is registered, we use that to fetch
        // a schema object.
        // See registerSchemaCache() for more info on this.
        if ($this->_schema === null) {
            if ($this->_schema_cache) {
               $cached_schema = $this->_schema_cache->loadSchema();
               if ($cached_schema instanceof Net_LDAP2_Error) {
                   return $cached_schema; // route error to client
               } else {
                   if ($cached_schema instanceof Net_LDAP2_Schema) {
                       $this->_schema = $cached_schema;
                   }
               }
            }
        }

        // Fetch schema, if not tried before and no cached version available.
        // If we are already fetching the schema, we will skip fetching.
        if ($this->_schema === null) {
            // store a temporary error message so subsequent calls to schema() can
            // detect, that we are fetching the schema already.
            // Otherwise we will get an infinite loop at Net_LDAP2_Schema::fetch()
            $this->_schema = new Net_LDAP2_Error('Schema not initialized');
            $this->_schema = Net_LDAP2_Schema::fetch($this, $dn);

            // If schema caching is active, advise the cache to store the schema
            if ($this->_schema_cache) {
                $caching_result = $this->_schema_cache->storeSchema($this->_schema);
                if ($caching_result instanceof Net_LDAP2_Error) {
                    return $caching_result; // route error to client
                }
            }
        }
        return $this->_schema;
    }