View Javadoc
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.logging.log4j.message;
18  
19  import java.io.Serializable;
20  
21  import org.apache.logging.log4j.util.StringBuilderFormattable;
22  import org.apache.logging.log4j.util.Strings;
23  
24  /**
25   * The StructuredData identifier.
26   */
27  public class StructuredDataId implements Serializable, StringBuilderFormattable {
28  
29      /**
30       * RFC 5424 Time Quality.
31       */
32      public static final StructuredDataId TIME_QUALITY = new StructuredDataId("timeQuality", null, new String[] {
33              "tzKnown", "isSynced", "syncAccuracy"});
34  
35      /**
36       * RFC 5424 Origin.
37       */
38      public static final StructuredDataId ORIGIN = new StructuredDataId("origin", null, new String[] {"ip",
39              "enterpriseId", "software", "swVersion"});
40  
41      /**
42       * RFC 5424 Meta.
43       */
44      public static final StructuredDataId META = new StructuredDataId("meta", null, new String[] {"sequenceId",
45              "sysUpTime", "language"});
46  
47      /**
48       * Reserved enterprise number.
49       */
50      public static final int RESERVED = -1;
51  
52      private static final long serialVersionUID = 9031746276396249990L;
53      private static final int MAX_LENGTH = 32;
54      private static final String AT_SIGN = "@";
55  
56      private final String name;
57      private final int enterpriseNumber;
58      private final String[] required;
59      private final String[] optional;
60  
61      protected StructuredDataId(final String name, final String[] required, final String[] optional) {
62          int index = -1;
63          if (name != null) {
64              if (name.length() > MAX_LENGTH) {
65                  throw new IllegalArgumentException(String.format("Length of id %s exceeds maximum of %d characters",
66                          name, MAX_LENGTH));
67              }
68              index = name.indexOf(AT_SIGN);
69          }
70  
71          if (index > 0) {
72              this.name = name.substring(0, index);
73              this.enterpriseNumber = Integer.parseInt(name.substring(index + 1));
74          } else {
75              this.name = name;
76              this.enterpriseNumber = RESERVED;
77          }
78          this.required = required;
79          this.optional = optional;
80      }
81  
82      /**
83       * A Constructor that helps conformance to RFC 5424.
84       *
85       * @param name The name portion of the id.
86       * @param enterpriseNumber The enterprise number.
87       * @param required The list of keys that are required for this id.
88       * @param optional The list of keys that are optional for this id.
89       */
90      public StructuredDataId(final String name, final int enterpriseNumber, final String[] required,
91              final String[] optional) {
92          if (name == null) {
93              throw new IllegalArgumentException("No structured id name was supplied");
94          }
95          if (name.contains(AT_SIGN)) {
96              throw new IllegalArgumentException("Structured id name cannot contain an " + Strings.quote(AT_SIGN));
97          }
98          if (enterpriseNumber <= 0) {
99              throw new IllegalArgumentException("No enterprise number was supplied");
100         }
101         this.name = name;
102         this.enterpriseNumber = enterpriseNumber;
103         final String id = name + AT_SIGN + enterpriseNumber;
104         if (id.length() > MAX_LENGTH) {
105             throw new IllegalArgumentException("Length of id exceeds maximum of 32 characters: " + id);
106         }
107         this.required = required;
108         this.optional = optional;
109     }
110 
111     /**
112      * Creates an id using another id to supply default values.
113      *
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      *
127      * @param defaultId The default id to use if this StructuredDataId doesn't have a name.
128      * @param anEnterpriseNumber The enterprise number.
129      * @return a StructuredDataId.
130      */
131     public StructuredDataId makeId(final String defaultId, final int anEnterpriseNumber) {
132         String id;
133         String[] req;
134         String[] opt;
135         if (anEnterpriseNumber <= 0) {
136             return this;
137         }
138         if (this.name != null) {
139             id = this.name;
140             req = this.required;
141             opt = this.optional;
142         } else {
143             id = defaultId;
144             req = null;
145             opt = null;
146         }
147 
148         return new StructuredDataId(id, anEnterpriseNumber, req, opt);
149     }
150 
151     /**
152      * Returns a list of required keys.
153      *
154      * @return a List of required keys or null if none have been provided.
155      */
156     public String[] getRequired() {
157         return required;
158     }
159 
160     /**
161      * Returns a list of optional keys.
162      *
163      * @return a List of optional keys or null if none have been provided.
164      */
165     public String[] getOptional() {
166         return optional;
167     }
168 
169     /**
170      * Returns the StructuredDataId name.
171      *
172      * @return the StructuredDataId name.
173      */
174     public String getName() {
175         return name;
176     }
177 
178     /**
179      * Returns the enterprise number.
180      *
181      * @return the enterprise number.
182      */
183     public int getEnterpriseNumber() {
184         return enterpriseNumber;
185     }
186 
187     /**
188      * Indicates if the id is reserved.
189      *
190      * @return true if the id uses the reserved enterprise number, false otherwise.
191      */
192     public boolean isReserved() {
193         return enterpriseNumber <= 0;
194     }
195 
196     @Override
197     public String toString() {
198         final StringBuilder sb = new StringBuilder(name.length() + 10);
199         formatTo(sb);
200         return sb.toString();
201     }
202 
203     @Override
204     public void formatTo(final StringBuilder buffer) {
205         if (isReserved()) {
206             buffer.append(name);
207         } else {
208             buffer.append(name).append(AT_SIGN).append(enterpriseNumber);
209         }
210     }
211 }