001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017 package org.apache.logging.log4j.core.appender.db.jdbc;
018
019 import org.apache.logging.log4j.Logger;
020 import org.apache.logging.log4j.core.config.Configuration;
021 import org.apache.logging.log4j.core.config.plugins.Plugin;
022 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
023 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
024 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
025 import org.apache.logging.log4j.core.layout.PatternLayout;
026 import org.apache.logging.log4j.core.util.Booleans;
027 import org.apache.logging.log4j.status.StatusLogger;
028 import org.apache.logging.log4j.util.Strings;
029
030 /**
031 * A configuration element used to configure which event properties are logged to which columns in the database table.
032 */
033 @Plugin(name = "Column", category = "Core", printObject = true)
034 public final class ColumnConfig {
035 private static final Logger LOGGER = StatusLogger.getLogger();
036
037 private final String columnName;
038 private final PatternLayout layout;
039 private final String literalValue;
040 private final boolean eventTimestamp;
041 private final boolean unicode;
042 private final boolean clob;
043
044 private ColumnConfig(final String columnName, final PatternLayout layout, final String literalValue,
045 final boolean eventDate, final boolean unicode, final boolean clob) {
046 this.columnName = columnName;
047 this.layout = layout;
048 this.literalValue = literalValue;
049 this.eventTimestamp = eventDate;
050 this.unicode = unicode;
051 this.clob = clob;
052 }
053
054 public String getColumnName() {
055 return this.columnName;
056 }
057
058 public PatternLayout getLayout() {
059 return this.layout;
060 }
061
062 public String getLiteralValue() {
063 return this.literalValue;
064 }
065
066 public boolean isEventTimestamp() {
067 return this.eventTimestamp;
068 }
069
070 public boolean isUnicode() {
071 return this.unicode;
072 }
073
074 public boolean isClob() {
075 return this.clob;
076 }
077
078 @Override
079 public String toString() {
080 return "{ name=" + this.columnName + ", layout=" + this.layout + ", literal=" + this.literalValue
081 + ", timestamp=" + this.eventTimestamp + " }";
082 }
083
084 /**
085 * Factory method for creating a column config within the plugin manager.
086 *
087 * @param config The configuration object
088 * @param name The name of the database column as it exists within the database table.
089 * @param pattern The {@link PatternLayout} pattern to insert in this column. Mutually exclusive with
090 * {@code literalValue!=null} and {@code eventTimestamp=true}
091 * @param literalValue The literal value to insert into the column as-is without any quoting or escaping. Mutually
092 * exclusive with {@code pattern!=null} and {@code eventTimestamp=true}.
093 * @param eventTimestamp If {@code "true"}, indicates that this column is a date-time column in which the event
094 * timestamp should be inserted. Mutually exclusive with {@code pattern!=null} and
095 * {@code literalValue!=null}.
096 * @param unicode If {@code "true"}, indicates that the column is a Unicode String.
097 * @param clob If {@code "true"}, indicates that the column is a character LOB (CLOB).
098 * @return the created column config.
099 */
100 @PluginFactory
101 public static ColumnConfig createColumnConfig(
102 @PluginConfiguration final Configuration config,
103 @PluginAttribute("name") final String name,
104 @PluginAttribute("pattern") final String pattern,
105 @PluginAttribute("literal") final String literalValue,
106 @PluginAttribute("isEventTimestamp") final String eventTimestamp,
107 @PluginAttribute("isUnicode") final String unicode,
108 @PluginAttribute("isClob") final String clob) {
109 if (Strings.isEmpty(name)) {
110 LOGGER.error("The column config is not valid because it does not contain a column name.");
111 return null;
112 }
113
114 final boolean isPattern = Strings.isNotEmpty(pattern);
115 final boolean isLiteralValue = Strings.isNotEmpty(literalValue);
116 final boolean isEventTimestamp = Boolean.parseBoolean(eventTimestamp);
117 final boolean isUnicode = Booleans.parseBoolean(unicode, true);
118 final boolean isClob = Boolean.parseBoolean(clob);
119
120 if ((isPattern && isLiteralValue) || (isPattern && isEventTimestamp) || (isLiteralValue && isEventTimestamp)) {
121 LOGGER.error("The pattern, literal, and isEventTimestamp attributes are mutually exclusive.");
122 return null;
123 }
124
125 if (isEventTimestamp) {
126 return new ColumnConfig(name, null, null, true, false, false);
127 }
128 if (isLiteralValue) {
129 return new ColumnConfig(name, null, literalValue, false, false, false);
130 }
131 if (isPattern) {
132 final PatternLayout layout =
133 PatternLayout.newBuilder()
134 .withPattern(pattern)
135 .withConfiguration(config)
136 .withAlwaysWriteExceptions(false)
137 .build();
138 return new ColumnConfig(name, layout, null, false, isUnicode, isClob);
139 }
140
141 LOGGER.error("To configure a column you must specify a pattern or literal or set isEventDate to true.");
142 return null;
143 }
144 }