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.message; 018 019import java.io.Serializable; 020 021import org.apache.logging.log4j.util.StringBuilderFormattable; 022import org.apache.logging.log4j.util.Strings; 023 024/** 025 * The StructuredData identifier. 026 */ 027public class StructuredDataId implements Serializable, StringBuilderFormattable { 028 029 /** 030 * RFC 5424 Time Quality. 031 */ 032 public static final StructuredDataId TIME_QUALITY = new StructuredDataId("timeQuality", null, new String[] { 033 "tzKnown", "isSynced", "syncAccuracy"}); 034 035 /** 036 * RFC 5424 Origin. 037 */ 038 public static final StructuredDataId ORIGIN = new StructuredDataId("origin", null, new String[] {"ip", 039 "enterpriseId", "software", "swVersion"}); 040 041 /** 042 * RFC 5424 Meta. 043 */ 044 public static final StructuredDataId META = new StructuredDataId("meta", null, new String[] {"sequenceId", 045 "sysUpTime", "language"}); 046 047 /** 048 * Reserved enterprise number. 049 */ 050 public static final int RESERVED = -1; 051 052 private static final long serialVersionUID = 9031746276396249990L; 053 private static final int MAX_LENGTH = 32; 054 private static final String AT_SIGN = "@"; 055 056 private final String name; 057 private final int enterpriseNumber; 058 private final String[] required; 059 private final String[] optional; 060 061 /** 062 * Creates a StructuredDataId based on the name. 063 * @param name The Structured Data Element name (maximum length is 32) 064 * @since 2.9 065 */ 066 public StructuredDataId(final String name) { 067 this(name, null, null, MAX_LENGTH); 068 } 069 070 /** 071 * Creates a StructuredDataId based on the name. 072 * @param name The Structured Data Element name. 073 * @param maxLength The maximum length of the name. 074 * @since 2.9 075 */ 076 public StructuredDataId(final String name, final int maxLength) { 077 this(name, null, null, maxLength); 078 } 079 080 /** 081 * 082 * @param name 083 * @param required 084 * @param optional 085 */ 086 public StructuredDataId(final String name, final String[] required, final String[] optional) { 087 this(name, required, optional, MAX_LENGTH); 088 } 089 090 /** 091 * A Constructor that helps conformance to RFC 5424. 092 * 093 * @param name The name portion of the id. 094 * @param required The list of keys that are required for this id. 095 * @param optional The list of keys that are optional for this id. 096 * @since 2.9 097 */ 098 public StructuredDataId(final String name, final String[] required, final String[] optional, int maxLength) { 099 int index = -1; 100 if (name != null) { 101 if (maxLength <= 0) { 102 maxLength = MAX_LENGTH; 103 } 104 if (name.length() > maxLength) { 105 throw new IllegalArgumentException(String.format("Length of id %s exceeds maximum of %d characters", 106 name, maxLength)); 107 } 108 index = name.indexOf(AT_SIGN); 109 } 110 111 if (index > 0) { 112 this.name = name.substring(0, index); 113 this.enterpriseNumber = Integer.parseInt(name.substring(index + 1)); 114 } else { 115 this.name = name; 116 this.enterpriseNumber = RESERVED; 117 } 118 this.required = required; 119 this.optional = optional; 120 } 121 122 /** 123 * A Constructor that helps conformance to RFC 5424. 124 * 125 * @param name The name portion of the id. 126 * @param enterpriseNumber The enterprise number. 127 * @param required The list of keys that are required for this id. 128 * @param optional The list of keys that are optional for this id. 129 */ 130 public StructuredDataId(final String name, final int enterpriseNumber, final String[] required, 131 final String[] optional) { 132 this(name, enterpriseNumber, required, optional, MAX_LENGTH); 133 } 134 135 /** 136 * A Constructor that helps conformance to RFC 5424. 137 * 138 * @param name The name portion of the id. 139 * @param enterpriseNumber The enterprise number. 140 * @param required The list of keys that are required for this id. 141 * @param optional The list of keys that are optional for this id. 142 * @param maxLength The maximum length of the StructuredData Id key. 143 * @since 2.9 144 */ 145 public StructuredDataId(final String name, final int enterpriseNumber, final String[] required, 146 final String[] optional, final int maxLength) { 147 if (name == null) { 148 throw new IllegalArgumentException("No structured id name was supplied"); 149 } 150 if (name.contains(AT_SIGN)) { 151 throw new IllegalArgumentException("Structured id name cannot contain an " + Strings.quote(AT_SIGN)); 152 } 153 if (enterpriseNumber <= 0) { 154 throw new IllegalArgumentException("No enterprise number was supplied"); 155 } 156 this.name = name; 157 this.enterpriseNumber = enterpriseNumber; 158 final String id = name + AT_SIGN + enterpriseNumber; 159 if (maxLength > 0 && id.length() > maxLength) { 160 throw new IllegalArgumentException("Length of id exceeds maximum of " + maxLength + " characters: " + id); 161 } 162 this.required = required; 163 this.optional = optional; 164 } 165 166 /** 167 * Creates an id using another id to supply default values. 168 * 169 * @param id The original StructuredDataId. 170 * @return the new StructuredDataId. 171 */ 172 public StructuredDataId makeId(final StructuredDataId id) { 173 if (id == null) { 174 return this; 175 } 176 return makeId(id.getName(), id.getEnterpriseNumber()); 177 } 178 179 /** 180 * Creates an id based on the current id. 181 * 182 * @param defaultId The default id to use if this StructuredDataId doesn't have a name. 183 * @param anEnterpriseNumber The enterprise number. 184 * @return a StructuredDataId. 185 */ 186 public StructuredDataId makeId(final String defaultId, final int anEnterpriseNumber) { 187 String id; 188 String[] req; 189 String[] opt; 190 if (anEnterpriseNumber <= 0) { 191 return this; 192 } 193 if (this.name != null) { 194 id = this.name; 195 req = this.required; 196 opt = this.optional; 197 } else { 198 id = defaultId; 199 req = null; 200 opt = null; 201 } 202 203 return new StructuredDataId(id, anEnterpriseNumber, req, opt); 204 } 205 206 /** 207 * Returns a list of required keys. 208 * 209 * @return a List of required keys or null if none have been provided. 210 */ 211 public String[] getRequired() { 212 return required; 213 } 214 215 /** 216 * Returns a list of optional keys. 217 * 218 * @return a List of optional keys or null if none have been provided. 219 */ 220 public String[] getOptional() { 221 return optional; 222 } 223 224 /** 225 * Returns the StructuredDataId name. 226 * 227 * @return the StructuredDataId name. 228 */ 229 public String getName() { 230 return name; 231 } 232 233 /** 234 * Returns the enterprise number. 235 * 236 * @return the enterprise number. 237 */ 238 public int getEnterpriseNumber() { 239 return enterpriseNumber; 240 } 241 242 /** 243 * Indicates if the id is reserved. 244 * 245 * @return true if the id uses the reserved enterprise number, false otherwise. 246 */ 247 public boolean isReserved() { 248 return enterpriseNumber <= 0; 249 } 250 251 @Override 252 public String toString() { 253 final StringBuilder sb = new StringBuilder(name.length() + 10); 254 formatTo(sb); 255 return sb.toString(); 256 } 257 258 @Override 259 public void formatTo(final StringBuilder buffer) { 260 if (isReserved()) { 261 buffer.append(name); 262 } else { 263 buffer.append(name).append(AT_SIGN).append(enterpriseNumber); 264 } 265 } 266}