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 */ 017package org.apache.logging.log4j.core.appender.db.jdbc; 018 019import org.apache.logging.log4j.Logger; 020import org.apache.logging.log4j.core.config.Configuration; 021import org.apache.logging.log4j.core.config.plugins.Plugin; 022import org.apache.logging.log4j.core.config.plugins.PluginAttribute; 023import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; 024import org.apache.logging.log4j.core.config.plugins.PluginFactory; 025import org.apache.logging.log4j.core.layout.PatternLayout; 026import org.apache.logging.log4j.core.util.Booleans; 027import org.apache.logging.log4j.status.StatusLogger; 028import 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) 034public 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}