Skip to content

Commit 9cbeb4f

Browse files
Added initial support for Structured Data.
Things left to do: - verify proper encoding to match the RFC - verify reserved SD-ID's
1 parent b680b9c commit 9cbeb4f

File tree

4 files changed

+374
-1
lines changed

4 files changed

+374
-1
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright 2010-2014, CloudBees Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.cloudbees.syslog;
17+
18+
import java.io.Serializable;
19+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.List;
22+
import java.util.Objects;
23+
24+
/**
25+
* A SD-ELEMENT
26+
*
27+
* @author <a href="mailto:[email protected]">Brett Bergquist</a>
28+
*/
29+
public class SDElement implements Serializable {
30+
31+
private static final long serialVersionUID = 1L;
32+
33+
public SDElement(String sdID) {
34+
validateSDID(sdID);
35+
this.sdID = sdID;
36+
}
37+
38+
public SDElement(String sdID, SDParam... sdParams) {
39+
validateSDID(sdID);
40+
this.sdID = sdID;
41+
this.sdParams.addAll(Arrays.asList(sdParams));
42+
}
43+
44+
private String sdID;
45+
46+
/**
47+
* Get the value of sdID
48+
*
49+
* @return the value of sdID
50+
*/
51+
public String getSdID() {
52+
return sdID;
53+
}
54+
55+
private List<SDParam> sdParams = new ArrayList<SDParam>();
56+
57+
/**
58+
* Get the value of sdParams
59+
*
60+
* @return the value of sdParams
61+
*/
62+
public List<SDParam> getSdParams() {
63+
return sdParams;
64+
}
65+
66+
/**
67+
* Set the value of sdParams
68+
*
69+
* @param sdParams new value of sdParams
70+
*/
71+
public void setSdParams(List<SDParam> sdParams) {
72+
if (null == sdParams) {
73+
throw new IllegalArgumentException("sdParams list cannot be null");
74+
}
75+
this.sdParams.addAll(sdParams);
76+
}
77+
78+
/**
79+
* Adds a SDParam
80+
* @param paramName the PARAM-NAME
81+
* @param paramValue the PARAM-VALUE
82+
* @return
83+
*/
84+
public SDElement addSDParam(String paramName, String paramValue) {
85+
return addSDParam(new SDParam(paramName, paramValue));
86+
}
87+
88+
public SDElement addSDParam(SDParam sdParam) {
89+
this.sdParams.add(sdParam);
90+
return this;
91+
}
92+
93+
@Override
94+
public int hashCode() {
95+
int hash = 7;
96+
hash = 97 * hash + Objects.hashCode(this.sdID);
97+
return hash;
98+
}
99+
100+
@Override
101+
public boolean equals(Object obj) {
102+
if (this == obj) {
103+
return true;
104+
}
105+
if (obj == null) {
106+
return false;
107+
}
108+
if (getClass() != obj.getClass()) {
109+
return false;
110+
}
111+
final SDElement other = (SDElement) obj;
112+
return Objects.equals(this.sdID, other.sdID);
113+
}
114+
115+
private void validateSDID(String sdName) {
116+
if (null == sdName) {
117+
throw new IllegalArgumentException("SD-ID cannot be null");
118+
}
119+
if (sdName.length() > 32) {
120+
throw new IllegalArgumentException("SD-ID must be less than 32 characters: " + sdName);
121+
}
122+
if (sdName.contains("=")) {
123+
throw new IllegalArgumentException("SD-ID cannot contain '='");
124+
}
125+
if (sdName.contains(" ")) {
126+
throw new IllegalArgumentException("SD-ID cannot contain ' '");
127+
}
128+
if (sdName.contains("]")) {
129+
throw new IllegalArgumentException("SD-ID cannot contain ']'");
130+
}
131+
if (sdName.contains("\"")) {
132+
throw new IllegalArgumentException("SD-ID cannot contain '\"'");
133+
}
134+
}
135+
136+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright 2010-2014, CloudBees Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.cloudbees.syslog;
17+
18+
import java.io.Serializable;
19+
import java.util.Objects;
20+
21+
/**
22+
*
23+
* @author <a href="mailto:[email protected]">Brett Bergquist</a>
24+
*/
25+
public class SDParam implements Serializable {
26+
27+
private static final long serialVersionUID = 1L;
28+
29+
public SDParam(String paramName, String paramValue) {
30+
validateParamName(paramName);
31+
this.paramName = paramName;
32+
this.paramValue = paramValue;
33+
}
34+
35+
private String paramName;
36+
37+
/**
38+
* Get the value of paramName
39+
*
40+
* @return the value of paramName
41+
*/
42+
public String getParamName() {
43+
return paramName;
44+
}
45+
46+
/**
47+
* Set the value of paramName
48+
*
49+
* @param paramName new value of paramName
50+
*/
51+
public void setParamName(String paramName) {
52+
validateParamName(paramName);
53+
this.paramName = paramName;
54+
}
55+
56+
private String paramValue;
57+
58+
/**
59+
* Get the value of paramValue
60+
*
61+
* @return the value of paramValue
62+
*/
63+
public String getParamValue() {
64+
return paramValue;
65+
}
66+
67+
/**
68+
* Set the value of paramValue
69+
*
70+
* @param paramValue new value of paramValue
71+
*/
72+
public void setParamValue(String paramValue) {
73+
this.paramValue = paramValue;
74+
}
75+
76+
private void validateParamName(String sdName) {
77+
if (null == sdName) {
78+
throw new IllegalArgumentException("PARAM-NAME cannot be null");
79+
}
80+
if (sdName.length() > 32) {
81+
throw new IllegalArgumentException("PARAM-NAME must be less than 32 characters: " + sdName);
82+
}
83+
if (sdName.contains("=")) {
84+
throw new IllegalArgumentException("PARAM-NAME cannot contain '='");
85+
}
86+
if (sdName.contains(" ")) {
87+
throw new IllegalArgumentException("PARAM-NAME cannot contain ' '");
88+
}
89+
if (sdName.contains("]")) {
90+
throw new IllegalArgumentException("PARAM-NAME cannot contain ']'");
91+
}
92+
if (sdName.contains("\"")) {
93+
throw new IllegalArgumentException("PARAM-NAME cannot contain '\"'");
94+
}
95+
}
96+
97+
@Override
98+
public int hashCode() {
99+
int hash = 7;
100+
hash = 59 * hash + Objects.hashCode(this.paramName);
101+
hash = 59 * hash + Objects.hashCode(this.paramValue);
102+
return hash;
103+
}
104+
105+
@Override
106+
public boolean equals(Object obj) {
107+
if (this == obj) {
108+
return true;
109+
}
110+
if (obj == null) {
111+
return false;
112+
}
113+
if (getClass() != obj.getClass()) {
114+
return false;
115+
}
116+
final SDParam other = (SDParam) obj;
117+
if (!Objects.equals(this.paramName, other.paramName)) {
118+
return false;
119+
}
120+
if (!Objects.equals(this.paramValue, other.paramValue)) {
121+
return false;
122+
}
123+
return true;
124+
}
125+
126+
@Override
127+
public String toString() {
128+
return "SDParam{" + "paramName=" + paramName + ", paramValue=" + paramValue + '}';
129+
}
130+
131+
}

src/main/java/com/cloudbees/syslog/SyslogMessage.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
import java.net.InetAddress;
2828
import java.net.UnknownHostException;
2929
import java.util.Date;
30+
import java.util.HashSet;
3031
import java.util.Locale;
32+
import java.util.Set;
3133
import java.util.TimeZone;
3234
import java.util.concurrent.TimeUnit;
3335

@@ -91,6 +93,7 @@ protected String newObject() {
9193
private String appName;
9294
private String procId;
9395
private String msgId;
96+
private Set<SDElement> sdElements;
9497
/**
9598
* Use a {@link java.io.CharArrayWriter} instead of a {@link String} or a {@code char[]} because middlewares like
9699
* Apache Tomcat use {@code CharArrayWriter} and it's convenient for pooling objects.
@@ -213,6 +216,26 @@ public SyslogMessage withMsg(final String msg) {
213216
}
214217
});
215218
}
219+
220+
public Set<SDElement> getSDElements() {
221+
Set<SDElement> ssde = sdElements;
222+
if (ssde == null) {
223+
ssde = new HashSet<SDElement>(0);
224+
}
225+
return ssde;
226+
}
227+
228+
public void setSDElements(Set<SDElement> ssde) {
229+
this.sdElements = ssde;
230+
}
231+
232+
public SyslogMessage withSDElement(SDElement sde) {
233+
if (sdElements == null) {
234+
sdElements = new HashSet<SDElement>();
235+
}
236+
sdElements.add(sde);
237+
return this;
238+
}
216239

217240
/**
218241
* Generates a Syslog message complying to the <a href="http://tools.ietf.org/html/rfc5424">RFC-5424</a> format
@@ -287,7 +310,7 @@ public void toRfc5424SyslogMessage(Writer out) throws IOException {
287310
out.write(SP);
288311
writeNillableValue(msgId, out);// Message ID
289312
out.write(SP);
290-
out.write(NILVALUE); // structured data
313+
writeStructuredDataOrNillableValue(sdElements, out);
291314
if (msg != null) {
292315
out.write(SP);
293316
msg.writeTo(out);
@@ -339,4 +362,53 @@ protected void writeNillableValue(@Nullable String value, @Nonnull Writer out) t
339362
out.write(value);
340363
}
341364
}
365+
366+
protected void writeStructuredDataOrNillableValue(@Nullable Set<SDElement> ssde, @Nonnull Writer out) throws IOException {
367+
if (ssde == null || ssde.isEmpty()) {
368+
out.write(NILVALUE);
369+
} else {
370+
for (SDElement sde : ssde) {
371+
writeSDElement(sde, out);
372+
}
373+
}
374+
}
375+
376+
protected void writeSDElement(@Nonnull SDElement sde, @Nonnull Writer out) throws IOException {
377+
out.write("[");
378+
out.write(sde.getSdID());
379+
for (SDParam sdp : sde.getSdParams()) {
380+
writeSDParam(sdp, out);
381+
}
382+
out.write("]");
383+
}
384+
385+
protected void writeSDParam(@Nonnull SDParam sdp, @Nonnull Writer out) throws IOException {
386+
out.write(SP);
387+
out.write(sdp.getParamName());
388+
out.write('=');
389+
out.write('"');
390+
out.write(getEscapedParamValue(sdp.getParamValue()));
391+
out.write('"');
392+
}
393+
394+
protected String getEscapedParamValue(String paramValue) {
395+
StringBuilder sb = new StringBuilder(paramValue.length());
396+
397+
for (int i = 0; i < paramValue.length(); i++) {
398+
char c = paramValue.charAt(i);
399+
switch (c) {
400+
// Falls through
401+
case '"':
402+
case '\\':
403+
case ']':
404+
sb.append('\\');
405+
break;
406+
default:
407+
break;
408+
}
409+
sb.append(c);
410+
}
411+
412+
return sb.toString();
413+
}
342414
}

0 commit comments

Comments
 (0)