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 : * @package log4php
19 : */
20 :
21 : /**
22 : * Abstract class that defines output logs strategies.
23 : *
24 : * @version $Revision: 1240469 $
25 : * @package log4php
26 : */
27 : abstract class LoggerAppender extends LoggerConfigurable {
28 :
29 : /**
30 : * Set to true when the appender is closed. A closed appender will not
31 : * accept any logging requests.
32 : * @var boolean
33 : */
34 : protected $closed = false;
35 :
36 : /**
37 : * The first filter in the filter chain.
38 : * @var LoggerFilter
39 : */
40 : protected $filter;
41 :
42 : /**
43 : * The appender's layout. Can be null if the appender does not use
44 : * a layout.
45 : * @var LoggerLayout
46 : */
47 : protected $layout;
48 :
49 : /**
50 : * Appender name. Used by other components to identify this appender.
51 : * @var string
52 : */
53 : protected $name;
54 :
55 : /**
56 : * Appender threshold level. Events whose level is below the threshold
57 : * will not be logged.
58 : * @var LoggerLevel
59 : */
60 : protected $threshold;
61 :
62 : /**
63 : * Set to true if the appender requires a layout.
64 : *
65 : * True by default, appenders which do not use a layout should override
66 : * this property to false.
67 : *
68 : * @var boolean
69 : */
70 : protected $requiresLayout = true;
71 :
72 : /**
73 : * Default constructor.
74 : * @param string $name Appender name
75 : */
76 : public function __construct($name = '') {
77 100 : $this->name = $name;
78 :
79 : // Closes the appender on shutdown. Better than a destructor because
80 : // it will be called even if a fatal error occurs (destructor won't).
81 100 : register_shutdown_function(array($this, 'close'));
82 :
83 100 : if ($this->requiresLayout) {
84 88 : $this->layout = $this->getDefaultLayout();
85 88 : }
86 100 : }
87 :
88 : /**
89 : * Returns the default layout for this appender. Can be overriden by
90 : * derived appenders.
91 : *
92 : * @return LoggerLayout
93 : */
94 : public function getDefaultLayout()
95 : {
96 86 : return new LoggerLayoutSimple();
97 : }
98 :
99 : /**
100 : * Adds a filter to the end of the filter chain.
101 : * @param LoggerFilter $filter add a new LoggerFilter
102 : */
103 : public function addFilter($filter) {
104 5 : if($this->filter === null) {
105 5 : $this->filter = $filter;
106 5 : } else {
107 2 : $this->filter->addNext($filter);
108 : }
109 5 : }
110 :
111 : /**
112 : * Clears the filter chain by removing all the filters in it.
113 : */
114 : public function clearFilters() {
115 1 : $this->filter = null;
116 1 : }
117 :
118 : /**
119 : * Returns the first filter in the filter chain.
120 : * The return value may be <i>null</i> if no is filter is set.
121 : * @return LoggerFilter
122 : */
123 : public function getFilter() {
124 1 : return $this->filter;
125 : }
126 :
127 : /**
128 : * Returns the first filter in the filter chain.
129 : * The return value may be <i>null</i> if no is filter is set.
130 : * @return LoggerFilter
131 : */
132 : public function getFirstFilter() {
133 23 : return $this->filter;
134 : }
135 :
136 : /**
137 : * Performs threshold checks and invokes filters before delegating logging
138 : * to the subclass' specific <i>append()</i> method.
139 : * @see LoggerAppender::append()
140 : * @param LoggerLoggingEvent $event
141 : */
142 : public function doAppend(LoggerLoggingEvent $event) {
143 23 : if($this->closed) {
144 0 : return;
145 : }
146 :
147 23 : if(!$this->isAsSevereAsThreshold($event->getLevel())) {
148 2 : return;
149 : }
150 :
151 23 : $f = $this->getFirstFilter();
152 23 : while($f !== null) {
153 4 : switch ($f->decide($event)) {
154 4 : case LoggerFilter::DENY: return;
155 3 : case LoggerFilter::ACCEPT: return $this->append($event);
156 3 : case LoggerFilter::NEUTRAL: $f = $f->getNext();
157 3 : }
158 3 : }
159 21 : $this->append($event);
160 21 : }
161 :
162 : /**
163 : * Sets the appender layout.
164 : * @param LoggerLayout $layout
165 : */
166 : public function setLayout($layout) {
167 54 : if($this->requiresLayout()) {
168 54 : $this->layout = $layout;
169 54 : }
170 54 : }
171 :
172 : /**
173 : * Returns the appender layout.
174 : * @return LoggerLayout
175 : */
176 : public function getLayout() {
177 5 : return $this->layout;
178 : }
179 :
180 : /**
181 : * Configurators call this method to determine if the appender
182 : * requires a layout.
183 : *
184 : * <p>If this method returns <i>true</i>, meaning that layout is required,
185 : * then the configurator will configure a layout using the configuration
186 : * information at its disposal. If this method returns <i>false</i>,
187 : * meaning that a layout is not required, then layout configuration will be
188 : * skipped even if there is available layout configuration
189 : * information at the disposal of the configurator.</p>
190 : *
191 : * <p>In the rather exceptional case, where the appender
192 : * implementation admits a layout but can also work without it, then
193 : * the appender should return <i>true</i>.</p>
194 : *
195 : * @return boolean
196 : */
197 : public function requiresLayout() {
198 77 : return $this->requiresLayout;
199 : }
200 :
201 : /**
202 : * Retruns the appender name.
203 : * @return string
204 : */
205 : public function getName() {
206 49 : return $this->name;
207 : }
208 :
209 : /**
210 : * Sets the appender name.
211 : * @param string $name
212 : */
213 : public function setName($name) {
214 0 : $this->name = $name;
215 0 : }
216 :
217 : /**
218 : * Returns the appender's threshold level.
219 : * @return LoggerLevel
220 : */
221 : public function getThreshold() {
222 5 : return $this->threshold;
223 : }
224 :
225 : /**
226 : * Sets the appender threshold.
227 : *
228 : * @param LoggerLevel|string $threshold Either a {@link LoggerLevel}
229 : * object or a string equivalent.
230 : * @see LoggerOptionConverter::toLevel()
231 : */
232 : public function setThreshold($threshold) {
233 9 : $this->setLevel('threshold', $threshold);
234 9 : }
235 :
236 : /**
237 : * Checks whether the message level is below the appender's threshold.
238 : *
239 : * If there is no threshold set, then the return value is always <i>true</i>.
240 : *
241 : * @param LoggerLevel $level
242 : * @return boolean Returns true if level is greater or equal than
243 : * threshold, or if the threshold is not set. Otherwise returns false.
244 : */
245 : public function isAsSevereAsThreshold($level) {
246 23 : if($this->threshold === null) {
247 21 : return true;
248 : }
249 2 : return $level->isGreaterOrEqual($this->getThreshold());
250 : }
251 :
252 : /**
253 : * Prepares the appender for logging.
254 : *
255 : * Derived appenders should override this method if option structure
256 : * requires it.
257 : */
258 : public function activateOptions() {
259 33 : $this->closed = false;
260 33 : }
261 :
262 : /**
263 : * Forwards the logging event to the destination.
264 : *
265 : * Derived appenders should implement this method to perform actual logging.
266 : *
267 : * @param LoggerLoggingEvent $event
268 : */
269 : abstract protected function append(LoggerLoggingEvent $event);
270 :
271 : /**
272 : * Releases any resources allocated by the appender.
273 : *
274 : * Derived appenders should override this method to perform proper closing
275 : * procedures.
276 : */
277 : public function close() {
278 7 : $this->closed = true;
279 7 : }
280 :
281 : /** Triggers a warning for this logger with the given message. */
282 : protected function warn($message) {
283 2 : $id = get_class($this) . (empty($this->name) ? '' : ":{$this->name}");
284 2 : trigger_error("log4php: [$id]: $message", E_USER_WARNING);
285 0 : }
286 :
287 : }
|