1<?php 2/* 3The NuSOAP project home is: 4http://sourceforge.net/projects/nusoap/ 5 6The primary support for NuSOAP is the mailing list: 7nusoap-general@lists.sourceforge.net 8*/ 9 10/** 11* caches instances of the wsdl class 12* 13* @author Scott Nichol <snichol@users.sourceforge.net> 14* @author Ingo Fischer <ingo@apollon.de> 15* @version $Id: class.wsdlcache.php,v 1.7 2007/04/17 16:34:03 snichol Exp $ 16* @access public 17*/ 18class nusoap_wsdlcache { 19 /** 20 * @var resource 21 * @access private 22 */ 23 var $fplock; 24 /** 25 * @var integer 26 * @access private 27 */ 28 var $cache_lifetime; 29 /** 30 * @var string 31 * @access private 32 */ 33 var $cache_dir; 34 /** 35 * @var string 36 * @access public 37 */ 38 var $debug_str = ''; 39 40 /** 41 * constructor 42 * 43 * @param string $cache_dir directory for cache-files 44 * @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited 45 * @access public 46 */ 47 function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) { 48 $this->fplock = array(); 49 $this->cache_dir = $cache_dir != '' ? $cache_dir : '.'; 50 $this->cache_lifetime = $cache_lifetime; 51 } 52 53 /** 54 * creates the filename used to cache a wsdl instance 55 * 56 * @param string $wsdl The URL of the wsdl instance 57 * @return string The filename used to cache the instance 58 * @access private 59 */ 60 function createFilename($wsdl) { 61 return $this->cache_dir.'/wsdlcache-' . md5($wsdl); 62 } 63 64 /** 65 * adds debug data to the class level debug string 66 * 67 * @param string $string debug data 68 * @access private 69 */ 70 function debug($string){ 71 $this->debug_str .= get_class($this).": $string\n"; 72 } 73 74 /** 75 * gets a wsdl instance from the cache 76 * 77 * @param string $wsdl The URL of the wsdl instance 78 * @return object wsdl The cached wsdl instance, null if the instance is not in the cache 79 * @access public 80 */ 81 function get($wsdl) { 82 $filename = $this->createFilename($wsdl); 83 if ($this->obtainMutex($filename, "r")) { 84 // check for expired WSDL that must be removed from the cache 85 if ($this->cache_lifetime > 0) { 86 if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) { 87 unlink($filename); 88 $this->debug("Expired $wsdl ($filename) from cache"); 89 $this->releaseMutex($filename); 90 return null; 91 } 92 } 93 // see what there is to return 94 if (!file_exists($filename)) { 95 $this->debug("$wsdl ($filename) not in cache (1)"); 96 $this->releaseMutex($filename); 97 return null; 98 } 99 $fp = @fopen($filename, "r"); 100 if ($fp) { 101 $s = implode("", @file($filename)); 102 fclose($fp); 103 $this->debug("Got $wsdl ($filename) from cache"); 104 } else { 105 $s = null; 106 $this->debug("$wsdl ($filename) not in cache (2)"); 107 } 108 $this->releaseMutex($filename); 109 return (!is_null($s)) ? unserialize($s) : null; 110 } else { 111 $this->debug("Unable to obtain mutex for $filename in get"); 112 } 113 return null; 114 } 115 116 /** 117 * obtains the local mutex 118 * 119 * @param string $filename The Filename of the Cache to lock 120 * @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode 121 * @return boolean Lock successfully obtained ?! 122 * @access private 123 */ 124 function obtainMutex($filename, $mode) { 125 if (isset($this->fplock[md5($filename)])) { 126 $this->debug("Lock for $filename already exists"); 127 return false; 128 } 129 $this->fplock[md5($filename)] = fopen($filename.".lock", "w"); 130 if ($mode == "r") { 131 return flock($this->fplock[md5($filename)], LOCK_SH); 132 } else { 133 return flock($this->fplock[md5($filename)], LOCK_EX); 134 } 135 } 136 137 /** 138 * adds a wsdl instance to the cache 139 * 140 * @param object wsdl $wsdl_instance The wsdl instance to add 141 * @return boolean WSDL successfully cached 142 * @access public 143 */ 144 function put($wsdl_instance) { 145 $filename = $this->createFilename($wsdl_instance->wsdl); 146 $s = serialize($wsdl_instance); 147 if ($this->obtainMutex($filename, "w")) { 148 $fp = fopen($filename, "w"); 149 if (! $fp) { 150 $this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache"); 151 $this->releaseMutex($filename); 152 return false; 153 } 154 fputs($fp, $s); 155 fclose($fp); 156 $this->debug("Put $wsdl_instance->wsdl ($filename) in cache"); 157 $this->releaseMutex($filename); 158 return true; 159 } else { 160 $this->debug("Unable to obtain mutex for $filename in put"); 161 } 162 return false; 163 } 164 165 /** 166 * releases the local mutex 167 * 168 * @param string $filename The Filename of the Cache to lock 169 * @return boolean Lock successfully released 170 * @access private 171 */ 172 function releaseMutex($filename) { 173 $ret = flock($this->fplock[md5($filename)], LOCK_UN); 174 fclose($this->fplock[md5($filename)]); 175 unset($this->fplock[md5($filename)]); 176 if (! $ret) { 177 $this->debug("Not able to release lock for $filename"); 178 } 179 return $ret; 180 } 181 182 /** 183 * removes a wsdl instance from the cache 184 * 185 * @param string $wsdl The URL of the wsdl instance 186 * @return boolean Whether there was an instance to remove 187 * @access public 188 */ 189 function remove($wsdl) { 190 $filename = $this->createFilename($wsdl); 191 if (!file_exists($filename)) { 192 $this->debug("$wsdl ($filename) not in cache to be removed"); 193 return false; 194 } 195 // ignore errors obtaining mutex 196 $this->obtainMutex($filename, "w"); 197 $ret = unlink($filename); 198 $this->debug("Removed ($ret) $wsdl ($filename) from cache"); 199 $this->releaseMutex($filename); 200 return $ret; 201 } 202} 203 204/** 205 * For backward compatibility 206 */ 207class wsdlcache extends nusoap_wsdlcache { 208} 209?> 210