/apache-log4j-1.2.17/src/main/java/org/apache/log4j/pattern/NameAbbreviator.java
Java | 350 lines | 158 code | 49 blank | 143 comment | 43 complexity | c58e1b6dc65fd0022f46ab9f76bf1f05 MD5 | raw file
Possible License(s): Apache-2.0
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.log4j.pattern;
19
20import java.util.ArrayList;
21import java.util.List;
22
23
24/**
25 * NameAbbreviator generates abbreviated logger and class names.
26 *
27 */
28public abstract class NameAbbreviator {
29 /**
30 * Default (no abbreviation) abbreviator.
31 */
32 private static final NameAbbreviator DEFAULT = new NOPAbbreviator();
33
34 /**
35 * Gets an abbreviator.
36 *
37 * For example, "%logger{2}" will output only 2 elements of the logger name,
38 * %logger{-2} will drop 2 elements from the logger name,
39 * "%logger{1.}" will output only the first character of the non-final elements in the name,
40 * "%logger{1~.2~} will output the first character of the first element, two characters of
41 * the second and subsequent elements and will use a tilde to indicate abbreviated characters.
42 *
43 * @param pattern abbreviation pattern.
44 * @return abbreviator, will not be null.
45 */
46 public static NameAbbreviator getAbbreviator(final String pattern) {
47 if (pattern.length() > 0) {
48 // if pattern is just spaces and numbers then
49 // use MaxElementAbbreviator
50 String trimmed = pattern.trim();
51
52 if (trimmed.length() == 0) {
53 return DEFAULT;
54 }
55
56 int i = 0;
57 if (trimmed.length() > 0) {
58 if (trimmed.charAt(0) == '-') {
59 i++;
60 }
61 for (;
62 (i < trimmed.length()) &&
63 (trimmed.charAt(i) >= '0') &&
64 (trimmed.charAt(i) <= '9');
65 i++) {
66 }
67 }
68
69
70 //
71 // if all blanks and digits
72 //
73 if (i == trimmed.length()) {
74 int elements = Integer.parseInt(trimmed);
75 if (elements >= 0) {
76 return new MaxElementAbbreviator(elements);
77 } else {
78 return new DropElementAbbreviator(-elements);
79 }
80 }
81
82 ArrayList fragments = new ArrayList(5);
83 char ellipsis;
84 int charCount;
85 int pos = 0;
86
87 while ((pos < trimmed.length()) && (pos >= 0)) {
88 int ellipsisPos = pos;
89
90 if (trimmed.charAt(pos) == '*') {
91 charCount = Integer.MAX_VALUE;
92 ellipsisPos++;
93 } else {
94 if ((trimmed.charAt(pos) >= '0') && (trimmed.charAt(pos) <= '9')) {
95 charCount = trimmed.charAt(pos) - '0';
96 ellipsisPos++;
97 } else {
98 charCount = 0;
99 }
100 }
101
102 ellipsis = '\0';
103
104 if (ellipsisPos < trimmed.length()) {
105 ellipsis = trimmed.charAt(ellipsisPos);
106
107 if (ellipsis == '.') {
108 ellipsis = '\0';
109 }
110 }
111
112 fragments.add(new PatternAbbreviatorFragment(charCount, ellipsis));
113 pos = trimmed.indexOf(".", pos);
114
115 if (pos == -1) {
116 break;
117 }
118
119 pos++;
120 }
121
122 return new PatternAbbreviator(fragments);
123 }
124
125 //
126 // no matching abbreviation, return defaultAbbreviator
127 //
128 return DEFAULT;
129 }
130
131 /**
132 * Gets default abbreviator.
133 *
134 * @return default abbreviator.
135 */
136 public static NameAbbreviator getDefaultAbbreviator() {
137 return DEFAULT;
138 }
139
140 /**
141 * Abbreviates a name in a StringBuffer.
142 *
143 * @param nameStart starting position of name in buf.
144 * @param buf buffer, may not be null.
145 */
146 public abstract void abbreviate(final int nameStart, final StringBuffer buf);
147
148 /**
149 * Abbreviator that simply appends full name to buffer.
150 */
151 private static class NOPAbbreviator extends NameAbbreviator {
152 /**
153 * Constructor.
154 */
155 public NOPAbbreviator() {
156 }
157
158 /**
159 * {@inheritDoc}
160 */
161 public void abbreviate(final int nameStart, final StringBuffer buf) {
162 }
163 }
164
165 /**
166 * Abbreviator that drops starting path elements.
167 */
168 private static class MaxElementAbbreviator extends NameAbbreviator {
169 /**
170 * Maximum number of path elements to output.
171 */
172 private final int count;
173
174 /**
175 * Create new instance.
176 * @param count maximum number of path elements to output.
177 */
178 public MaxElementAbbreviator(final int count) {
179 this.count = count;
180 }
181
182 /**
183 * Abbreviate name.
184 * @param buf buffer to append abbreviation.
185 * @param nameStart start of name to abbreviate.
186 */
187 public void abbreviate(final int nameStart, final StringBuffer buf) {
188 // We substract 1 from 'len' when assigning to 'end' to avoid out of
189 // bounds exception in return r.substring(end+1, len). This can happen if
190 // precision is 1 and the category name ends with a dot.
191 int end = buf.length() - 1;
192
193 String bufString = buf.toString();
194 for (int i = count; i > 0; i--) {
195 end = bufString.lastIndexOf(".", end - 1);
196
197 if ((end == -1) || (end < nameStart)) {
198 return;
199 }
200 }
201
202 buf.delete(nameStart, end + 1);
203 }
204 }
205
206 /**
207 * Abbreviator that drops starting path elements.
208 */
209 private static class DropElementAbbreviator extends NameAbbreviator {
210 /**
211 * Maximum number of path elements to output.
212 */
213 private final int count;
214
215 /**
216 * Create new instance.
217 * @param count maximum number of path elements to output.
218 */
219 public DropElementAbbreviator(final int count) {
220 this.count = count;
221 }
222
223 /**
224 * Abbreviate name.
225 * @param buf buffer to append abbreviation.
226 * @param nameStart start of name to abbreviate.
227 */
228 public void abbreviate(final int nameStart, final StringBuffer buf) {
229 int i = count;
230 for(int pos = buf.indexOf(".", nameStart);
231 pos != -1;
232 pos = buf.indexOf(".", pos + 1)) {
233 if(--i == 0) {
234 buf.delete(nameStart, pos + 1);
235 break;
236 }
237 }
238 }
239 }
240
241
242 /**
243 * Fragment of an pattern abbreviator.
244 *
245 */
246 private static class PatternAbbreviatorFragment {
247 /**
248 * Count of initial characters of element to output.
249 */
250 private final int charCount;
251
252 /**
253 * Character used to represent dropped characters.
254 * '\0' indicates no representation of dropped characters.
255 */
256 private final char ellipsis;
257
258 /**
259 * Creates a PatternAbbreviatorFragment.
260 * @param charCount number of initial characters to preserve.
261 * @param ellipsis character to represent elimination of characters,
262 * '\0' if no ellipsis is desired.
263 */
264 public PatternAbbreviatorFragment(
265 final int charCount, final char ellipsis) {
266 this.charCount = charCount;
267 this.ellipsis = ellipsis;
268 }
269
270 /**
271 * Abbreviate element of name.
272 * @param buf buffer to receive element.
273 * @param startPos starting index of name element.
274 * @return starting index of next element.
275 */
276 public int abbreviate(final StringBuffer buf, final int startPos) {
277 int nextDot = buf.toString().indexOf(".", startPos);
278
279 if (nextDot != -1) {
280 if ((nextDot - startPos) > charCount) {
281 buf.delete(startPos + charCount, nextDot);
282 nextDot = startPos + charCount;
283
284 if (ellipsis != '\0') {
285 buf.insert(nextDot, ellipsis);
286 nextDot++;
287 }
288 }
289
290 nextDot++;
291 }
292
293 return nextDot;
294 }
295 }
296
297 /**
298 * Pattern abbreviator.
299 *
300 *
301 */
302 private static class PatternAbbreviator extends NameAbbreviator {
303 /**
304 * Element abbreviation patterns.
305 */
306 private final PatternAbbreviatorFragment[] fragments;
307
308 /**
309 * Create PatternAbbreviator.
310 *
311 * @param fragments element abbreviation patterns.
312 */
313 public PatternAbbreviator(List fragments) {
314 if (fragments.size() == 0) {
315 throw new IllegalArgumentException(
316 "fragments must have at least one element");
317 }
318
319 this.fragments = new PatternAbbreviatorFragment[fragments.size()];
320 fragments.toArray(this.fragments);
321 }
322
323 /**
324 * Abbreviate name.
325 * @param buf buffer that abbreviated name is appended.
326 * @param nameStart start of name.
327 */
328 public void abbreviate(final int nameStart, final StringBuffer buf) {
329 //
330 // all non-terminal patterns are executed once
331 //
332 int pos = nameStart;
333
334 for (int i = 0; (i < (fragments.length - 1)) && (pos < buf.length());
335 i++) {
336 pos = fragments[i].abbreviate(buf, pos);
337 }
338
339 //
340 // last pattern in executed repeatedly
341 //
342 PatternAbbreviatorFragment terminalFragment =
343 fragments[fragments.length - 1];
344
345 while ((pos < buf.length()) && (pos >= 0)) {
346 pos = terminalFragment.abbreviate(buf, pos);
347 }
348 }
349 }
350}