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.message;
018
019 import java.io.Serializable;
020
021 import org.apache.logging.log4j.util.Strings;
022
023 /**
024 * The StructuredData identifier.
025 */
026 public class StructuredDataId implements Serializable {
027
028 private static final String AT = "@";
029
030 /**
031 * RFC 5424 Time Quality.
032 */
033 public static final StructuredDataId TIME_QUALITY = new StructuredDataId("timeQuality", null,
034 new String[]{"tzKnown", "isSynced", "syncAccuracy"});
035
036 /**
037 * RFC 5424 Origin.
038 */
039 public static final StructuredDataId ORIGIN = new StructuredDataId("origin", null,
040 new String[]{"ip", "enterpriseId", "software", "swVersion"});
041
042 /**
043 * RFC 5424 Meta.
044 */
045 public static final StructuredDataId META = new StructuredDataId("meta", null,
046 new String[]{"sequenceId", "sysUpTime", "language"});
047
048 /**
049 * Reserved enterprise number.
050 */
051 public static final int RESERVED = -1;
052
053 private static final long serialVersionUID = 9031746276396249990L;
054 private static final int MAX_LENGTH = 32;
055
056 private final String name;
057 private final int enterpriseNumber;
058 private final String[] required;
059 private final String[] optional;
060
061
062 protected StructuredDataId(final String name, final String[] required, final String[] optional) {
063 int index = -1;
064 if (name != null) {
065 if (name.length() > MAX_LENGTH) {
066 throw new IllegalArgumentException(String.format("Length of id %s exceeds maximum of %d characters",
067 name, MAX_LENGTH));
068 }
069 index = name.indexOf(AT);
070 }
071
072 if (index > 0) {
073 this.name = name.substring(0, index);
074 this.enterpriseNumber = Integer.parseInt(name.substring(index + 1));
075 } else {
076 this.name = name;
077 this.enterpriseNumber = RESERVED;
078 }
079 this.required = required;
080 this.optional = optional;
081 }
082
083 /**
084 * A Constructor that helps conformance to RFC 5424.
085 *
086 * @param name The name portion of the id.
087 * @param enterpriseNumber The enterprise number.
088 * @param required The list of keys that are required for this id.
089 * @param optional The list of keys that are optional for this id.
090 */
091 public StructuredDataId(final String name, final int enterpriseNumber, final String[] required,
092 final String[] optional) {
093 if (name == null) {
094 throw new IllegalArgumentException("No structured id name was supplied");
095 }
096 if (name.contains(AT)) {
097 throw new IllegalArgumentException("Structured id name cannot contain an " + Strings.quote(AT));
098 }
099 if (enterpriseNumber <= 0) {
100 throw new IllegalArgumentException("No enterprise number was supplied");
101 }
102 this.name = name;
103 this.enterpriseNumber = enterpriseNumber;
104 final String id = enterpriseNumber < 0 ? name : name + AT + enterpriseNumber;
105 if (id.length() > MAX_LENGTH) {
106 throw new IllegalArgumentException("Length of id exceeds maximum of 32 characters: " + id);
107 }
108 this.required = required;
109 this.optional = optional;
110 }
111
112 /**
113 * Creates an id using another id to supply default values.
114 * @param id The original StructuredDataId.
115 * @return the new StructuredDataId.
116 */
117 public StructuredDataId makeId(final StructuredDataId id) {
118 if (id == null) {
119 return this;
120 }
121 return makeId(id.getName(), id.getEnterpriseNumber());
122 }
123
124 /**
125 * Creates an id based on the current id.
126 * @param defaultId The default id to use if this StructuredDataId doesn't have a name.
127 * @param enterpriseNumber The enterprise number.
128 * @return a StructuredDataId.
129 */
130 public StructuredDataId makeId(final String defaultId, final int enterpriseNumber) {
131 String id;
132 String[] req;
133 String[] opt;
134 if (enterpriseNumber <= 0) {
135 return this;
136 }
137 if (this.name != null) {
138 id = this.name;
139 req = this.required;
140 opt = this.optional;
141 } else {
142 id = defaultId;
143 req = null;
144 opt = null;
145 }
146
147 return new StructuredDataId(id, enterpriseNumber, req, opt);
148 }
149
150 /**
151 * Returns a list of required keys.
152 * @return a List of required keys or null if none have been provided.
153 */
154 public String[] getRequired() {
155 return required;
156 }
157
158 /**
159 * Returns a list of optional keys.
160 * @return a List of optional keys or null if none have been provided.
161 */
162 public String[] getOptional() {
163 return optional;
164 }
165
166 /**
167 * Returns the StructuredDataId name.
168 * @return the StructuredDataId name.
169 */
170 public String getName() {
171 return name;
172 }
173
174 /**
175 * Returns the enterprise number.
176 * @return the enterprise number.
177 */
178 public int getEnterpriseNumber() {
179 return enterpriseNumber;
180 }
181
182 /**
183 * Indicates if the id is reserved.
184 * @return true if the id uses the reserved enterprise number, false otherwise.
185 */
186 public boolean isReserved() {
187 return enterpriseNumber <= 0;
188 }
189
190 @Override
191 public String toString() {
192 return isReserved() ? name : name + AT + enterpriseNumber;
193 }
194 }