blob: b0df6eed53d8e38a05f72cfe6bffb1f3aad03dcc [file] [log] [blame]
/*
* $Header: /cvshome/build/org.osgi.service.event/src/org/osgi/service/event/Event.java,v 1.8 2006/07/12 13:17:04 hargrave Exp $
*
* Copyright (c) OSGi Alliance (2005, 2006). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.osgi.service.event;
import java.util.*;
import org.osgi.framework.Filter;
/**
* An event.
*
* <code>Event</code> objects are delivered to <code>EventHandler</code>
* services which subsrcibe to the topic of the event.
*
* @version $Revision: 1.8 $
*/
public class Event {
/**
* The topic of this event.
*/
String topic;
/**
* The properties carried by this event. Keys are strings and values are
* objects
*/
Hashtable properties;
/**
* Constructs an event.
*
* @param topic The topic of the event.
* @param properties The event's properties (may be <code>null</code>).
*
* @throws IllegalArgumentException If topic is not a valid topic name.
*/
public Event(String topic, Dictionary properties) {
this.topic = topic;
validateTopicName();
this.properties = new Hashtable();
if (properties != null) {
for (Enumeration e = properties.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
Object value = properties.get(key);
this.properties.put(key, value);
}
}
this.properties.put(EventConstants.EVENT_TOPIC, topic);
}
/**
* Retrieves a property.
*
* @param name the name of the property to retrieve
*
* @return The value of the property, or <code>null</code> if not found.
*/
public final Object getProperty(String name) {
return properties.get(name);
}
/**
* Returns a list of this event's property names.
*
* @return A non-empty array with one element per property.
*/
public final String[] getPropertyNames() {
String[] names = new String[properties.size()];
Enumeration keys = properties.keys();
for (int i = 0; keys.hasMoreElements(); i++) {
names[i] = (String) keys.nextElement();
}
return names;
}
/**
* Returns the topic of this event.
*
* @return The topic of this event.
*/
public final String getTopic() {
return topic;
}
/**
* Tests this event's properties against the given filter.
*
* @param filter The filter to test.
*
* @return true If this event's properties match the filter, false
* otherwise.
*/
public final boolean matches(Filter filter) {
return filter.matchCase(properties);
}
/**
* Compares this <code>Event</code> object to another object.
*
* <p>
* An event is considered to be <b>equal to </b> another
* event if the topic is equal and the properties are equal.
*
* @param object The <code>Event</code> object to be compared.
* @return <code>true</code> if <code>object</code> is a
* <code>Event</code> and is equal to this object;
* <code>false</code> otherwise.
*/
public boolean equals(Object object) {
if (object == this) { // quicktest
return true;
}
if (!(object instanceof Event)) {
return false;
}
Event event = (Event) object;
return topic.equals(event.topic) && properties.equals(event.properties);
}
/**
* Returns a hash code value for the object.
*
* @return An integer which is a hash code value for this object.
*/
public int hashCode() {
return topic.hashCode() ^ properties.hashCode();
}
/**
* Returns the string representation of this event.
*
* @return The string representation of this event.
*/
public String toString() {
return getClass().getName() + " [topic=" + topic + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
private static final String SEPARATOR = "/"; //$NON-NLS-1$
/**
* Called by the constructor to validate the topic name.
*
* @throws IllegalArgumentException If the topic name is invalid.
*/
private void validateTopicName() {
try {
StringTokenizer st = new StringTokenizer(topic, SEPARATOR, true);
validateToken(st.nextToken());
while (st.hasMoreTokens()) {
st.nextToken(); // consume delimiter
validateToken(st.nextToken());
}
}
catch (NoSuchElementException e) {
throw new IllegalArgumentException("invalid topic"); //$NON-NLS-1$
}
}
private static final String tokenAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"; //$NON-NLS-1$
/**
* Validate a token.
*
* @throws IllegalArgumentException If the token is invalid.
*/
private void validateToken(String token) {
int length = token.length();
if (length < 1) { // token must contain at least one character
throw new IllegalArgumentException("invalid topic"); //$NON-NLS-1$
}
for (int i = 0; i < length; i++) { // each character in the token must be from the token alphabet
if (tokenAlphabet.indexOf(token.charAt(i)) == -1) { //$NON-NLS-1$
throw new IllegalArgumentException("invalid topic"); //$NON-NLS-1$
}
}
}
}