PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/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. package org.apache.log4j.pattern;
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. /**
  21. * NameAbbreviator generates abbreviated logger and class names.
  22. *
  23. */
  24. public abstract class NameAbbreviator {
  25. /**
  26. * Default (no abbreviation) abbreviator.
  27. */
  28. private static final NameAbbreviator DEFAULT = new NOPAbbreviator();
  29. /**
  30. * Gets an abbreviator.
  31. *
  32. * For example, "%logger{2}" will output only 2 elements of the logger name,
  33. * %logger{-2} will drop 2 elements from the logger name,
  34. * "%logger{1.}" will output only the first character of the non-final elements in the name,
  35. * "%logger{1~.2~} will output the first character of the first element, two characters of
  36. * the second and subsequent elements and will use a tilde to indicate abbreviated characters.
  37. *
  38. * @param pattern abbreviation pattern.
  39. * @return abbreviator, will not be null.
  40. */
  41. public static NameAbbreviator getAbbreviator(final String pattern) {
  42. if (pattern.length() > 0) {
  43. // if pattern is just spaces and numbers then
  44. // use MaxElementAbbreviator
  45. String trimmed = pattern.trim();
  46. if (trimmed.length() == 0) {
  47. return DEFAULT;
  48. }
  49. int i = 0;
  50. if (trimmed.length() > 0) {
  51. if (trimmed.charAt(0) == '-') {
  52. i++;
  53. }
  54. for (;
  55. (i < trimmed.length()) &&
  56. (trimmed.charAt(i) >= '0') &&
  57. (trimmed.charAt(i) <= '9');
  58. i++) {
  59. }
  60. }
  61. //
  62. // if all blanks and digits
  63. //
  64. if (i == trimmed.length()) {
  65. int elements = Integer.parseInt(trimmed);
  66. if (elements >= 0) {
  67. return new MaxElementAbbreviator(elements);
  68. } else {
  69. return new DropElementAbbreviator(-elements);
  70. }
  71. }
  72. ArrayList fragments = new ArrayList(5);
  73. char ellipsis;
  74. int charCount;
  75. int pos = 0;
  76. while ((pos < trimmed.length()) && (pos >= 0)) {
  77. int ellipsisPos = pos;
  78. if (trimmed.charAt(pos) == '*') {
  79. charCount = Integer.MAX_VALUE;
  80. ellipsisPos++;
  81. } else {
  82. if ((trimmed.charAt(pos) >= '0') && (trimmed.charAt(pos) <= '9')) {
  83. charCount = trimmed.charAt(pos) - '0';
  84. ellipsisPos++;
  85. } else {
  86. charCount = 0;
  87. }
  88. }
  89. ellipsis = '\0';
  90. if (ellipsisPos < trimmed.length()) {
  91. ellipsis = trimmed.charAt(ellipsisPos);
  92. if (ellipsis == '.') {
  93. ellipsis = '\0';
  94. }
  95. }
  96. fragments.add(new PatternAbbreviatorFragment(charCount, ellipsis));
  97. pos = trimmed.indexOf(".", pos);
  98. if (pos == -1) {
  99. break;
  100. }
  101. pos++;
  102. }
  103. return new PatternAbbreviator(fragments);
  104. }
  105. //
  106. // no matching abbreviation, return defaultAbbreviator
  107. //
  108. return DEFAULT;
  109. }
  110. /**
  111. * Gets default abbreviator.
  112. *
  113. * @return default abbreviator.
  114. */
  115. public static NameAbbreviator getDefaultAbbreviator() {
  116. return DEFAULT;
  117. }
  118. /**
  119. * Abbreviates a name in a StringBuffer.
  120. *
  121. * @param nameStart starting position of name in buf.
  122. * @param buf buffer, may not be null.
  123. */
  124. public abstract void abbreviate(final int nameStart, final StringBuffer buf);
  125. /**
  126. * Abbreviator that simply appends full name to buffer.
  127. */
  128. private static class NOPAbbreviator extends NameAbbreviator {
  129. /**
  130. * Constructor.
  131. */
  132. public NOPAbbreviator() {
  133. }
  134. /**
  135. * {@inheritDoc}
  136. */
  137. public void abbreviate(final int nameStart, final StringBuffer buf) {
  138. }
  139. }
  140. /**
  141. * Abbreviator that drops starting path elements.
  142. */
  143. private static class MaxElementAbbreviator extends NameAbbreviator {
  144. /**
  145. * Maximum number of path elements to output.
  146. */
  147. private final int count;
  148. /**
  149. * Create new instance.
  150. * @param count maximum number of path elements to output.
  151. */
  152. public MaxElementAbbreviator(final int count) {
  153. this.count = count;
  154. }
  155. /**
  156. * Abbreviate name.
  157. * @param buf buffer to append abbreviation.
  158. * @param nameStart start of name to abbreviate.
  159. */
  160. public void abbreviate(final int nameStart, final StringBuffer buf) {
  161. // We substract 1 from 'len' when assigning to 'end' to avoid out of
  162. // bounds exception in return r.substring(end+1, len). This can happen if
  163. // precision is 1 and the category name ends with a dot.
  164. int end = buf.length() - 1;
  165. String bufString = buf.toString();
  166. for (int i = count; i > 0; i--) {
  167. end = bufString.lastIndexOf(".", end - 1);
  168. if ((end == -1) || (end < nameStart)) {
  169. return;
  170. }
  171. }
  172. buf.delete(nameStart, end + 1);
  173. }
  174. }
  175. /**
  176. * Abbreviator that drops starting path elements.
  177. */
  178. private static class DropElementAbbreviator extends NameAbbreviator {
  179. /**
  180. * Maximum number of path elements to output.
  181. */
  182. private final int count;
  183. /**
  184. * Create new instance.
  185. * @param count maximum number of path elements to output.
  186. */
  187. public DropElementAbbreviator(final int count) {
  188. this.count = count;
  189. }
  190. /**
  191. * Abbreviate name.
  192. * @param buf buffer to append abbreviation.
  193. * @param nameStart start of name to abbreviate.
  194. */
  195. public void abbreviate(final int nameStart, final StringBuffer buf) {
  196. int i = count;
  197. for(int pos = buf.indexOf(".", nameStart);
  198. pos != -1;
  199. pos = buf.indexOf(".", pos + 1)) {
  200. if(--i == 0) {
  201. buf.delete(nameStart, pos + 1);
  202. break;
  203. }
  204. }
  205. }
  206. }
  207. /**
  208. * Fragment of an pattern abbreviator.
  209. *
  210. */
  211. private static class PatternAbbreviatorFragment {
  212. /**
  213. * Count of initial characters of element to output.
  214. */
  215. private final int charCount;
  216. /**
  217. * Character used to represent dropped characters.
  218. * '\0' indicates no representation of dropped characters.
  219. */
  220. private final char ellipsis;
  221. /**
  222. * Creates a PatternAbbreviatorFragment.
  223. * @param charCount number of initial characters to preserve.
  224. * @param ellipsis character to represent elimination of characters,
  225. * '\0' if no ellipsis is desired.
  226. */
  227. public PatternAbbreviatorFragment(
  228. final int charCount, final char ellipsis) {
  229. this.charCount = charCount;
  230. this.ellipsis = ellipsis;
  231. }
  232. /**
  233. * Abbreviate element of name.
  234. * @param buf buffer to receive element.
  235. * @param startPos starting index of name element.
  236. * @return starting index of next element.
  237. */
  238. public int abbreviate(final StringBuffer buf, final int startPos) {
  239. int nextDot = buf.toString().indexOf(".", startPos);
  240. if (nextDot != -1) {
  241. if ((nextDot - startPos) > charCount) {
  242. buf.delete(startPos + charCount, nextDot);
  243. nextDot = startPos + charCount;
  244. if (ellipsis != '\0') {
  245. buf.insert(nextDot, ellipsis);
  246. nextDot++;
  247. }
  248. }
  249. nextDot++;
  250. }
  251. return nextDot;
  252. }
  253. }
  254. /**
  255. * Pattern abbreviator.
  256. *
  257. *
  258. */
  259. private static class PatternAbbreviator extends NameAbbreviator {
  260. /**
  261. * Element abbreviation patterns.
  262. */
  263. private final PatternAbbreviatorFragment[] fragments;
  264. /**
  265. * Create PatternAbbreviator.
  266. *
  267. * @param fragments element abbreviation patterns.
  268. */
  269. public PatternAbbreviator(List fragments) {
  270. if (fragments.size() == 0) {
  271. throw new IllegalArgumentException(
  272. "fragments must have at least one element");
  273. }
  274. this.fragments = new PatternAbbreviatorFragment[fragments.size()];
  275. fragments.toArray(this.fragments);
  276. }
  277. /**
  278. * Abbreviate name.
  279. * @param buf buffer that abbreviated name is appended.
  280. * @param nameStart start of name.
  281. */
  282. public void abbreviate(final int nameStart, final StringBuffer buf) {
  283. //
  284. // all non-terminal patterns are executed once
  285. //
  286. int pos = nameStart;
  287. for (int i = 0; (i < (fragments.length - 1)) && (pos < buf.length());
  288. i++) {
  289. pos = fragments[i].abbreviate(buf, pos);
  290. }
  291. //
  292. // last pattern in executed repeatedly
  293. //
  294. PatternAbbreviatorFragment terminalFragment =
  295. fragments[fragments.length - 1];
  296. while ((pos < buf.length()) && (pos >= 0)) {
  297. pos = terminalFragment.abbreviate(buf, pos);
  298. }
  299. }
  300. }
  301. }