1 /*======================================================================*
2 * Copyright (c) 2008, Yahoo! Inc. All rights reserved. *
4 * Licensed under the New BSD License (the "License"); you may not use *
5 * this file except in compliance with the License. Unless required *
6 * by applicable law or agreed to in writing, software distributed *
7 * under the License is distributed on an "AS IS" BASIS, WITHOUT *
8 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
9 * See the License for the specific language governing permissions and *
10 * limitations under the License. See accompanying LICENSE file. *
11 *======================================================================*/
15 import org
.apache
.commons
.logging
.Log
;
16 import org
.apache
.commons
.logging
.LogFactory
;
17 import org
.lwes
.BaseType
;
18 import org
.lwes
.EventAttributeSizeException
;
19 import org
.lwes
.EventSystemException
;
20 import org
.lwes
.TypeID
;
21 import org
.lwes
.util
.IPAddress
;
24 import java
.io
.InputStream
;
25 import java
.math
.BigInteger
;
26 import java
.util
.Arrays
;
27 import java
.util
.Collections
;
28 import java
.util
.Enumeration
;
29 import java
.util
.List
;
31 import java
.util
.TreeMap
;
32 import java
.util
.concurrent
.ConcurrentHashMap
;
35 * Provides type checking for the event system. Also provides a place for
36 * globally accessible information.
38 * @author Anthony Molinaro
39 * @author Michael P. Lum
40 * @author Frank Maritato
42 public class EventTemplateDB
{
44 private static transient Log log
= LogFactory
.getLog(EventTemplateDB
.class);
46 * the meta event info inherent to every event
48 private static final String META_EVENT_INFO
= "MetaEventInfo";
51 * esfFile for this event system.
53 private File esfFile
= null;
54 private InputStream esfInputStream
= null;
59 private Map
<String
, Map
<String
, BaseType
>> events
= null;
60 private Map
<String
, BaseType
> knownTypes
= null;
61 private Map
<String
, BaseType
> reservedWords
= null;
64 * This is the EventTemplateDB constructor.
66 public EventTemplateDB() {
67 events
= new ConcurrentHashMap
<String
, Map
<String
, BaseType
>>();
68 knownTypes
= new ConcurrentHashMap
<String
, BaseType
>();
69 reservedWords
= new ConcurrentHashMap
<String
, BaseType
>();
70 initializeKnownTypes();
74 * Sets the Event Specification file for this system
76 * @param anEsfFile the ESF file for this system.
78 public void setESFFile(File anEsfFile
) {
83 * Gets the ESF file, in case you want to look at it
85 * @return the ESF file used in this system.
87 public File
getESFFile() {
92 * Sets the Event Specification file as an InputStream
94 * @param esfInputStream the InputStream representing an ESF file
96 public void setESFInputStream(InputStream esfInputStream
) {
97 this.esfInputStream
= esfInputStream
;
101 * Ges the ESF InputStream
103 * @return the ESF InputStream used in the system
105 public InputStream
getESFInputStream() {
106 return esfInputStream
;
110 * Initializes the EventTemplateDB, assumes that setESFFile() has been
113 * @return true if the EventTemplateDB initializes correctly; false if it
114 * does not. false means the event system is unable to perform validation
116 public synchronized boolean initialize() {
118 * Call the parser to parse the file. Any errors cause the
119 * initialization to fail.
123 if (getESFInputStream() != null) {
124 parser
= new ESFParser(getESFInputStream());
126 else if (getESFFile() != null) {
127 parser
= new ESFParser(
128 new java
.io
.FileInputStream(getESFFile()));
134 parser
.setEventTemplateDB(this);
137 catch (java
.io
.FileNotFoundException e
) {
138 log
.warn("File not found ", e
);
141 * treat this as just a warning and allow things to continue, this
142 * allows an empty EventTemplateDB to work when type checking is
146 catch (ParseException e
) {
147 log
.warn("Parser error in ESF file " + getESFFile(), e
);
150 catch (Exception e
) {
151 log
.error("Error parsing ESF file " + getESFFile(), e
);
152 /* catch IO, NPEs and other exceptions but still continue */
160 * Add an Event to the EventTemplateDB
162 * @param anEventName the name of the Event to add
163 * @return true if the event was added, false if it was not
165 public synchronized boolean addEvent(String anEventName
) {
166 if (anEventName
== null) {
171 if (anEventName
.equals(META_EVENT_INFO
)) {
175 if (events
.containsKey(anEventName
)) {
176 if (log
.isInfoEnabled()) {
177 log
.info("Event " + anEventName
+ " already exists in event DB");
182 Map
<String
, BaseType
> evtHash
= new ConcurrentHashMap
<String
, BaseType
>();
183 if (!(reservedWords
.isEmpty())) {
184 /* insert reserved words into new event */
185 for (String key
: reservedWords
.keySet()) {
187 evtHash
.put(key
, reservedWords
.get(key
));
192 events
.put(anEventName
, evtHash
);
194 catch (Exception e
) {
195 log
.warn("Error adding event to EventTemplateDB", e
);
201 public synchronized boolean addEventAttribute(String anEventName
,
202 String anAttributeName
,
203 String anAttributeType
) {
204 return addEventAttribute(anEventName
,
211 public synchronized boolean addEventAttribute(String anEventName
,
212 String anAttributeName
,
213 String anAttributeType
,
216 return addEventAttribute(anEventName
, anAttributeName
, anAttributeType
, size
, required
, null);
220 * Add an attribute to an Event in the EventTemplateDB
222 * @param anEventName the name of the event to add this attribute to
223 * @param anAttributeName the name of the attribute to add
224 * @param anAttributeType the type of the attribute, should be the name of the type
225 * given in the ESF Specification.
226 * @param size The size restriction for this attribute
227 * @param required Is this attribute required
228 * @return true if the attribute can be added, false if it can not.
230 public synchronized boolean addEventAttribute(String anEventName
,
231 String anAttributeName
,
232 String anAttributeType
,
235 Object defaultValue
) {
237 if (anEventName
== null || anAttributeName
== null || anAttributeType
== null) {
242 if (anEventName
.equals(META_EVENT_INFO
)) {
243 if (checkForType(anAttributeType
)) {
244 BaseType bt
= knownTypes
.get(anAttributeType
).cloneBaseType();
245 bt
.setRequired(required
);
246 bt
.setSizeRestriction(size
);
247 if (defaultValue
!= null) {
248 bt
.setDefaultValue(defaultValue
);
250 reservedWords
.put(anAttributeName
, bt
);
254 if (log
.isInfoEnabled()) {
255 log
.info("Meta keyword " + anEventName
+ "." + anAttributeName
+
256 "has unknown type " + anAttributeType
+ ", skipping");
262 if (reservedWords
.containsKey(anEventName
)) {
263 if (log
.isWarnEnabled()) {
264 log
.warn("Unable to add attribute named " + anAttributeName
+
265 "as it is a reserved word, skipping");
270 if (events
.containsKey(anEventName
)) {
271 Map
<String
, BaseType
> evtHash
= events
.get(anEventName
);
272 if (checkForType(anAttributeType
)) {
273 BaseType bt
= knownTypes
.get(anAttributeType
).cloneBaseType();
274 bt
.setRequired(required
);
275 bt
.setSizeRestriction(size
);
276 if (defaultValue
!= null) {
277 bt
.setDefaultValue(defaultValue
);
279 evtHash
.put(anAttributeName
, bt
);
283 if (log
.isWarnEnabled()) {
284 log
.warn("Type " + anAttributeType
+ " does not exist for " +
285 anAttributeName
+ ", skipping");
291 if (log
.isWarnEnabled()) {
292 log
.warn("No such event " + anEventName
+ ", skipping");
297 catch (Exception e
) {
298 log
.error("Error adding attribute " + anAttributeName
+ " to " + anEventName
, e
);
304 * Returns an enumeration of all defined events
306 * @return an enumeration of all defined events
308 public Enumeration
<String
> getEventNames() {
309 return Collections
.enumeration(this.events
.keySet());
313 * Returns true if the type given by aTypeName is a valid type in the DB.
315 * @param aTypeName a type name according to the ESF Specification
316 * @return true if the type exists in the DB, false otherwise
318 public boolean checkForType(String aTypeName
) {
319 if (aTypeName
== null) {
322 return knownTypes
.containsKey(aTypeName
);
325 public void checkForSize(String eventName
,
326 String attributeName
,
327 BaseType attributeValue
) throws EventAttributeSizeException
{
329 if (!attributeValue
.getTypeName().startsWith("[L")) {
330 if (log
.isDebugEnabled()) {
331 log
.debug("value for attribute " + attributeName
+ " is not an array.");
336 Map
<String
, BaseType
> evtMap
= events
.get(eventName
);
337 if (evtMap
== null) {
338 log
.error("event definition did not exist");
341 BaseType attrBaseType
= evtMap
.get(attributeName
);
342 if (attrBaseType
== null) {
343 log
.error("attribute definition did not exist");
348 int size
= attrBaseType
.getSizeRestriction();
349 Object o
= attributeValue
.getTypeObject();
350 if (o
instanceof short[]) {
351 sizeToCheck
= ((short[]) o
).length
;
353 else if (o
instanceof int[]) {
354 sizeToCheck
= ((int[]) o
).length
;
356 else if (o
instanceof long[]) {
357 sizeToCheck
= ((long[]) o
).length
;
359 else if (o
instanceof boolean[]) {
360 sizeToCheck
= ((boolean[]) o
).length
;
362 else if (o
instanceof byte[]) {
363 sizeToCheck
= ((byte[]) o
).length
;
365 else if (o
instanceof double[]) {
366 sizeToCheck
= ((double[]) o
).length
;
368 else if (o
instanceof float[]) {
369 sizeToCheck
= ((float[]) o
).length
;
371 else if (o
instanceof List
) {
372 List arr
= (List
) attributeValue
.getTypeObject();
373 sizeToCheck
= arr
.size();
376 throw new EventAttributeSizeException("Cannot determine size for "+attributeName
);
378 if (log
.isTraceEnabled()) {
379 log
.trace("sizeToCheck: " + sizeToCheck
+ " size: " + size
);
381 if (size
> 0 && sizeToCheck
> size
) {
382 throw new EventAttributeSizeException(attributeName
, sizeToCheck
, size
);
387 * Checks to see if an Event exists in the EventTemplateDB
389 * @param anEventName the name of the event to check the existence of
390 * @return true if the event with the name <tt>anEventName</tt> exists in
391 * the EventTemplateDB, false otherwise.
393 public boolean checkForEvent(String anEventName
) {
394 if (anEventName
== null) {
397 return events
.containsKey(anEventName
);
401 * Checks to see if an attribute <tt>anAttributeName</tt> exists for the
402 * event <tt>anEventName</tt>
404 * @param anEventName the name of an Event
405 * @param anAttributeName the name of an attribute of Event to check
406 * @return true if the attribute exists as a member of event, false
409 public boolean checkForAttribute(String anEventName
, String anAttributeName
) {
410 if (anEventName
== null || anAttributeName
== null) {
414 if (checkForEvent(anEventName
)) {
415 Map
<String
, BaseType
> evtHash
= events
.get(anEventName
);
416 return evtHash
.containsKey(anAttributeName
);
422 * Checks to see if the type of an attribute is proper. (i.e. if the given
423 * attribute of the given event has the same type assigned to it as the type
424 * of the given objects value)
426 * @param anEventName the name of an Event.
427 * @param anAttributeName the name of the attribute whose type is being checked
428 * @param anAttributeValue the Object containing the possible value of the attribute.
429 * @return true if the event and attribute exist and if the type of the
430 * attribute matches the type assigned to this attribute in the
431 * EventTemplateDB, false otherwise.
433 public boolean checkTypeForAttribute(String anEventName
,
434 String anAttributeName
,
435 Object anAttributeValue
) {
436 if (anEventName
== null || anAttributeName
== null || anAttributeValue
== null) {
440 if (checkForAttribute(anEventName
, anAttributeName
)) {
441 Map
<String
, BaseType
> evtHash
= events
.get(anEventName
);
442 Object storedTypeObject
= evtHash
.get(anAttributeName
);
443 byte type1
= ((BaseType
) anAttributeValue
).getTypeToken();
444 byte type2
= ((BaseType
) storedTypeObject
).getTypeToken();
445 if (type1
== type2
) {
454 * Checks to see if the type of an attribute is proper. (i.e. if the given
455 * attribute of the given event has the same type assigned to it as the type
458 * @param anEventName the name of an Event.
459 * @param anAttributeName the name of the attribute whose type is being checked
460 * @param anAttributeType the String containing the possible type value of the
462 * @return true if the event and attribute exist and if the type of the
463 * attribute matches the type assigned to this attribute in the
464 * EventTemplateDB, false otherwise.
466 public boolean checkTypeForAttribute(String anEventName
,
467 String anAttributeName
, String anAttributeType
) {
468 if (anEventName
== null || anAttributeName
== null || anAttributeType
== null) {
472 if (checkForAttribute(anEventName
, anAttributeName
)) {
473 Map
<String
, BaseType
> evtHash
= events
.get(anEventName
);
474 String storedTypeName
= evtHash
.get(anAttributeName
).getTypeName();
475 if (log
.isDebugEnabled()) {
483 if (anAttributeType
.equals(storedTypeName
)) {
492 * Given an Object which is the attribute value of the attribute
493 * <tt>attributeName</tt> of event <tt>eventName</tt>, return the internal
494 * representation (i.e. <tt>BaseType</tt>) of this Object
496 * @param eventName the name of an Event.
497 * @param attributeName the name of an attribute of <tt>eventName</tt>
498 * @param attributeValue the value of the attribute
499 * @return the <tt>BaseType</tt> representation of <tt>attributeValue</tt>
501 public BaseType
getBaseTypeForObjectAttribute(String eventName
,
502 String attributeName
,
503 Object attributeValue
) {
504 if (eventName
== null || attributeName
== null || attributeValue
== null) {
508 Map
<String
, BaseType
> evtHash
= events
.get(eventName
);
509 BaseType tmpBaseType
= evtHash
.get(attributeName
);
510 BaseType retBaseType
= tmpBaseType
.cloneBaseType();
511 retBaseType
.setTypeObject(attributeValue
);
516 * Returns the base types for this event
519 * @return a map of event fields to base types
521 public Map
<String
, BaseType
> getBaseTypesForEvent(String eventName
) {
522 if (eventName
== null) {
526 Map
<String
, BaseType
> map
= events
.get(eventName
);
528 return map
== null ?
new ConcurrentHashMap
<String
, BaseType
>() : map
;
532 * Parses the string representation of an event attribute into the
533 * appropriate objectt.
535 * @param anEventName the name of an Event.
536 * @param anAttributeName the name of the attribute we are parsing
537 * @param stringAttributeValue a string representation of the value of the attribute given by
539 * @return the object represented by the string
540 * <tt>stringAttributeValue</tt>
542 public Object
parseAttribute(String anEventName
, String anAttributeName
,
543 String stringAttributeValue
) {
544 Object retObject
= null;
546 if (anEventName
== null || anAttributeName
== null || stringAttributeValue
== null) {
550 if (log
.isTraceEnabled()) {
551 log
.trace("parseAttribute: " + anEventName
+ "." + anAttributeName
+ "=" +
552 stringAttributeValue
);
555 if (checkForAttribute(anEventName
, anAttributeName
)) {
556 if (log
.isTraceEnabled()) {
557 log
.trace("parseAttribute: passed first if attribute exists");
560 Map
<String
, BaseType
> evtHash
= events
.get(anEventName
);
562 BaseType bt
= evtHash
.get(anAttributeName
);
564 throw new EventSystemException("Null BaseType for "
568 retObject
= bt
.parseFromString(stringAttributeValue
);
569 if (log
.isTraceEnabled()) {
570 log
.trace("parseAttribute: parsed " + retObject
);
573 catch (EventSystemException btpe
) {
574 log
.error("Unable to parseAttribute", btpe
);
578 if (log
.isTraceEnabled()) {
579 log
.trace("parseAttribute: returning " + retObject
);
585 * Returns a HTML rendering of the EventTemplateDB
587 * @return HTML string of the EventTemplateDB
589 public String
toHtmlString() {
590 StringBuffer sb
= new StringBuffer();
591 sb
.append("<table>\n");
592 sb
.append("<tr><th>" + META_EVENT_INFO
593 + "</th><th>Type</th><th>Name</th></tr>\n");
594 for (String key
: reservedWords
.keySet()) {
595 BaseType tv
= reservedWords
.get(key
);
596 String type
= tv
.getTypeName();
597 sb
.append("<tr><td></td><td>").append(type
).append("</td><td>").append(key
).append("</td></tr>\n");
599 for (String EventKey
: events
.keySet()) {
600 sb
.append("<tr><th>").append(EventKey
).append("</th><th>Type</th><th>Name</th></tr>\n");
601 if (EventKey
!= null) {
602 Map
<String
, BaseType
> event
= events
.get(EventKey
);
603 for (Enumeration
<String
> att
= Collections
.enumeration(event
.keySet()); att
604 .hasMoreElements();) {
605 String key
= att
.nextElement();
606 BaseType tv
= event
.get(key
);
607 String type
= tv
.getTypeName();
608 sb
.append("<tr><td></td><td>")
611 .append(key
).append("</td></tr>\n");
616 sb
.append("</table>\n");
617 return sb
.toString();
622 * Returns a rather long string Representation of the EventTemplateDB
624 * @return a string Representation of the EventTemplateDB
626 public String
toString() {
627 StringBuffer sb
= new StringBuffer();
628 sb
.append("\n").append(META_EVENT_INFO
).append("\n{\n");
629 String
[] reservedKeys
= new String
[reservedWords
.size()];
632 for (String s1
: reservedWords
.keySet()) {
633 reservedKeys
[i
] = s1
;
636 Arrays
.sort(reservedKeys
);
638 for (i
= 0; i
< reservedKeys
.length
; ++i
) {
639 BaseType tv
= reservedWords
.get(reservedKeys
[i
]);
640 String type
= tv
.getTypeName();
641 sb
.append("\t").append(type
).append(" ").append(reservedKeys
[i
]).append(";\n");
645 String
[] eventKeys
= new String
[events
.size()];
647 for (String s
: events
.keySet()) {
651 Arrays
.sort(eventKeys
);
653 for (i
= 0; i
< eventKeys
.length
; ++i
) {
654 sb
.append(eventKeys
[i
]).append("\n{\n");
655 if (eventKeys
[i
] != null) {
656 Map
<String
, BaseType
> event
= events
.get(eventKeys
[i
]);
658 String
[] attributeKeys
= new String
[event
.size()];
659 for (Enumeration
<String
> att
= Collections
.enumeration(event
.keySet());
660 att
.hasMoreElements();) {
661 attributeKeys
[j
] = att
.nextElement();
664 Arrays
.sort(attributeKeys
);
666 for (j
= 0; j
< attributeKeys
.length
; ++j
) {
667 BaseType tv
= event
.get(attributeKeys
[j
]);
668 String type
= tv
.getTypeName();
669 sb
.append("\t").append(type
).append(" ").append(attributeKeys
[j
]).append(";\n");
674 return sb
.toString();
677 public String
toStringOneLine() {
678 return toString().replace("\n", " ");
682 * Creates a map of known types
684 private void initializeKnownTypes() {
685 /* initialize the list of known types */
686 knownTypes
.put(TypeID
.UINT16_STRING
, new BaseType(TypeID
.UINT16_STRING
,
687 TypeID
.UINT16_TOKEN
, 0));
688 knownTypes
.put(TypeID
.INT16_STRING
, new BaseType(TypeID
.INT16_STRING
,
689 TypeID
.INT16_TOKEN
, (short) 0));
690 knownTypes
.put(TypeID
.UINT32_STRING
, new BaseType(TypeID
.UINT32_STRING
,
691 TypeID
.UINT32_TOKEN
, (long) 0));
692 knownTypes
.put(TypeID
.INT32_STRING
, new BaseType(TypeID
.INT32_STRING
,
693 TypeID
.INT32_TOKEN
, 0));
694 knownTypes
.put(TypeID
.STRING_STRING
, new BaseType(TypeID
.STRING_STRING
,
695 TypeID
.STRING_TOKEN
, ""));
696 knownTypes
.put(TypeID
.IPADDR_STRING
, new BaseType(TypeID
.IPADDR_STRING
,
697 TypeID
.IPADDR_TOKEN
, new IPAddress()));
698 knownTypes
.put(TypeID
.INT64_STRING
, new BaseType(TypeID
.INT64_STRING
,
699 TypeID
.INT64_TOKEN
, (long) 0));
700 knownTypes
.put(TypeID
.UINT64_STRING
, new BaseType(TypeID
.UINT64_STRING
,
701 TypeID
.UINT64_TOKEN
, BigInteger
.ZERO
));
702 knownTypes
.put(TypeID
.BOOLEAN_STRING
, new BaseType(TypeID
.BOOLEAN_STRING
,
703 TypeID
.BOOLEAN_TOKEN
, true));
704 knownTypes
.put(TypeID
.STRING_ARRAY_STRING
,
705 new BaseType(TypeID
.STRING_ARRAY_STRING
,
706 TypeID
.STRING_ARRAY_TOKEN
, null));
707 knownTypes
.put(TypeID
.INT16_ARRAY_STRING
,
708 new BaseType(TypeID
.INT16_ARRAY_STRING
,
709 TypeID
.INT16_ARRAY_TOKEN
, null));
710 knownTypes
.put(TypeID
.INT32_ARRAY_STRING
,
711 new BaseType(TypeID
.INT32_ARRAY_STRING
,
712 TypeID
.INT32_ARRAY_TOKEN
, null));
713 knownTypes
.put(TypeID
.INT64_ARRAY_STRING
,
714 new BaseType(TypeID
.INT64_ARRAY_STRING
,
715 TypeID
.INT64_ARRAY_TOKEN
, null));
716 knownTypes
.put(TypeID
.UINT16_ARRAY_STRING
,
717 new BaseType(TypeID
.UINT16_ARRAY_STRING
,
718 TypeID
.UINT16_ARRAY_TOKEN
, null));
719 knownTypes
.put(TypeID
.UINT32_ARRAY_STRING
,
720 new BaseType(TypeID
.UINT32_ARRAY_STRING
,
721 TypeID
.UINT32_ARRAY_TOKEN
, null));
722 knownTypes
.put(TypeID
.UINT64_ARRAY_STRING
,
723 new BaseType(TypeID
.UINT64_ARRAY_STRING
,
724 TypeID
.UINT64_ARRAY_TOKEN
, null));
725 knownTypes
.put(TypeID
.BOOLEAN_ARRAY_STRING
,
726 new BaseType(TypeID
.BOOLEAN_ARRAY_STRING
,
727 TypeID
.BOOLEAN_ARRAY_TOKEN
, null));
728 knownTypes
.put(TypeID
.BYTE_ARRAY_STRING
,
729 new BaseType(TypeID
.BYTE_ARRAY_STRING
,
730 TypeID
.BYTE_ARRAY_TOKEN
, null));
731 knownTypes
.put(TypeID
.DOUBLE_ARRAY_STRING
,
732 new BaseType(TypeID
.DOUBLE_ARRAY_STRING
,
733 TypeID
.DOUBLE_ARRAY_TOKEN
, null));
734 knownTypes
.put(TypeID
.FLOAT_ARRAY_STRING
,
735 new BaseType(TypeID
.FLOAT_ARRAY_STRING
,
736 TypeID
.FLOAT_ARRAY_TOKEN
, null));
737 knownTypes
.put(TypeID
.DOUBLE_STRING
,
738 new BaseType(TypeID
.DOUBLE_STRING
,
739 TypeID
.DOUBLE_TOKEN
, null));
740 knownTypes
.put(TypeID
.FLOAT_STRING
,
741 new BaseType(TypeID
.FLOAT_STRING
,
742 TypeID
.FLOAT_TOKEN
, null));
743 knownTypes
.put(TypeID
.IPV4_STRING
,
744 new BaseType(TypeID
.IPV4_STRING
,
745 TypeID
.IPV4_TOKEN
, null));
746 knownTypes
.put(TypeID
.IPV4_ARRAY_STRING
,
747 new BaseType(TypeID
.IPV4_ARRAY_STRING
,
748 TypeID
.IPV4_ARRAY_TOKEN
, null));
751 public Map
<String
, BaseType
> getMetaFields() {
752 Map
<String
, BaseType
> m
= new TreeMap
<String
, BaseType
>();
753 m
.putAll(reservedWords
);
757 public Map
<String
, Map
<String
, BaseType
>> getEvents() {
758 Map
<String
, Map
<String
, BaseType
>> cp
= new TreeMap
<String
, Map
<String
, BaseType
>>();