1: <?php
2: /**
3: * Licensed to the Apache Software Foundation (ASF) under one or more
4: * contributor license agreements. See the NOTICE file distributed with
5: * this work for additional information regarding copyright ownership.
6: * The ASF licenses this file to You under the Apache License, Version 2.0
7: * (the "License"); you may not use this file except in compliance with
8: * the License. You may obtain a copy of the License at
9: *
10: * http://www.apache.org/licenses/LICENSE-2.0
11: *
12: * Unless required by applicable law or agreed to in writing, software
13: * distributed under the License is distributed on an "AS IS" BASIS,
14: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15: * See the License for the specific language governing permissions and
16: * limitations under the License.
17: */
18:
19: /**
20: * LoggerAppenderFile appends log events to a file.
21: *
22: * This appender uses a layout.
23: *
24: * ## Configurable parameters: ##
25: *
26: * - **file** - Path to the target file. Relative paths are resolved based on
27: * the working directory.
28: * - **append** - If set to true, the appender will append to the file,
29: * otherwise the file contents will be overwritten.
30: *
31: * @version $Revision: 1382274 $
32: * @package log4php
33: * @subpackage appenders
34: * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
35: * @link http://logging.apache.org/log4php/docs/appenders/file.html Appender documentation
36: */
37: class LoggerAppenderFile extends LoggerAppender {
38:
39: /**
40: * If set to true, the file is locked before appending. This allows
41: * concurrent access. However, appending without locking is faster so
42: * it should be used where appropriate.
43: *
44: * TODO: make this a configurable parameter
45: *
46: * @var boolean
47: */
48: protected $locking = true;
49:
50: /**
51: * If set to true, appends to file. Otherwise overwrites it.
52: * @var boolean
53: */
54: protected $append = true;
55:
56: /**
57: * Path to the target file.
58: * @var string
59: */
60: protected $file;
61:
62: /**
63: * The file resource.
64: * @var resource
65: */
66: protected $fp;
67:
68: /**
69: * Helper function which can be easily overriden by daily file appender.
70: */
71: protected function getTargetFile() {
72: return $this->file;
73: }
74:
75: /**
76: * Acquires the target file resource, creates the destination folder if
77: * necessary. Writes layout header to file.
78: *
79: * @return boolean FALSE if opening failed
80: */
81: protected function openFile() {
82: $file = $this->getTargetFile();
83:
84: // Create the target folder if needed
85: if(!is_file($file)) {
86: $dir = dirname($file);
87:
88: if(!is_dir($dir)) {
89: $success = mkdir($dir, 0777, true);
90: if ($success === false) {
91: $this->warn("Failed creating target directory [$dir]. Closing appender.");
92: $this->closed = true;
93: return false;
94: }
95: }
96: }
97:
98: $mode = $this->append ? 'a' : 'w';
99: $this->fp = fopen($file, $mode);
100: if ($this->fp === false) {
101: $this->warn("Failed opening target file. Closing appender.");
102: $this->fp = null;
103: $this->closed = true;
104: return false;
105: }
106:
107: // Required when appending with concurrent access
108: if($this->append) {
109: fseek($this->fp, 0, SEEK_END);
110: }
111:
112: // Write the header
113: $this->write($this->layout->getHeader());
114: }
115:
116: /**
117: * Writes a string to the target file. Opens file if not already open.
118: * @param string $string Data to write.
119: */
120: protected function write($string) {
121: // Lazy file open
122: if(!isset($this->fp)) {
123: if ($this->openFile() === false) {
124: return; // Do not write if file open failed.
125: }
126: }
127:
128: if ($this->locking) {
129: $this->writeWithLocking($string);
130: } else {
131: $this->writeWithoutLocking($string);
132: }
133: }
134:
135: protected function writeWithLocking($string) {
136: if(flock($this->fp, LOCK_EX)) {
137: if(fwrite($this->fp, $string) === false) {
138: $this->warn("Failed writing to file. Closing appender.");
139: $this->closed = true;
140: }
141: flock($this->fp, LOCK_UN);
142: } else {
143: $this->warn("Failed locking file for writing. Closing appender.");
144: $this->closed = true;
145: }
146: }
147:
148: protected function writeWithoutLocking($string) {
149: if(fwrite($this->fp, $string) === false) {
150: $this->warn("Failed writing to file. Closing appender.");
151: $this->closed = true;
152: }
153: }
154:
155: public function activateOptions() {
156: if (empty($this->file)) {
157: $this->warn("Required parameter 'file' not set. Closing appender.");
158: $this->closed = true;
159: return;
160: }
161: }
162:
163: public function close() {
164: if (is_resource($this->fp)) {
165: $this->write($this->layout->getFooter());
166: fclose($this->fp);
167: }
168: $this->fp = null;
169: $this->closed = true;
170: }
171:
172: public function append(LoggerLoggingEvent $event) {
173: $this->write($this->layout->format($event));
174: }
175:
176: /**
177: * Sets the 'file' parameter.
178: * @param string $file
179: */
180: public function setFile($file) {
181: $this->setString('file', $file);
182: }
183:
184: /**
185: * Returns the 'file' parameter.
186: * @return string
187: */
188: public function getFile() {
189: return $this->file;
190: }
191:
192: /**
193: * Returns the 'append' parameter.
194: * @return boolean
195: */
196: public function getAppend() {
197: return $this->append;
198: }
199:
200: /**
201: * Sets the 'append' parameter.
202: * @param boolean $append
203: */
204: public function setAppend($append) {
205: $this->setBoolean('append', $append);
206: }
207:
208: /**
209: * Sets the 'file' parmeter. Left for legacy reasons.
210: * @param string $fileName
211: * @deprecated Use setFile() instead.
212: */
213: public function setFileName($fileName) {
214: $this->setFile($fileName);
215: }
216:
217: /**
218: * Returns the 'file' parmeter. Left for legacy reasons.
219: * @return string
220: * @deprecated Use getFile() instead.
221: */
222: public function getFileName() {
223: return $this->getFile();
224: }
225: }
226: