001: // Copyright 2004, 2005 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.hivemind.service.impl;
016:
017: import java.beans.BeanInfo;
018: import java.beans.EventSetDescriptor;
019: import java.beans.IntrospectionException;
020: import java.beans.Introspector;
021: import java.lang.reflect.Method;
022: import java.util.HashMap;
023: import java.util.Map;
024:
025: import org.apache.hivemind.ErrorLog;
026: import org.apache.hivemind.HiveMind;
027: import org.apache.hivemind.Location;
028: import org.apache.hivemind.impl.BaseLocatable;
029: import org.apache.hivemind.service.EventLinker;
030:
031: /**
032: * Implementation of {@link org.apache.hivemind.service.EventLinker}. Will output warnings whenever
033: * a consumer can't be registered for at least one event set (which can happen when the consumer
034: * does not implement the necessary interfaces).
035: *
036: * @author Howard Lewis Ship
037: */
038: public class EventLinkerImpl extends BaseLocatable implements
039: EventLinker {
040: private ErrorLog _errorLog;
041:
042: /**
043: * Map of {@link java.beans.EventSetDescriptor}[], keyed on producer class.
044: */
045: private Map _producerEventSets;
046:
047: public EventLinkerImpl(ErrorLog errorLog) {
048: _errorLog = errorLog;
049: }
050:
051: public void addEventListener(Object producer, String eventSetName,
052: Object consumer, Location location) {
053: EventSetDescriptor[] sets = getEventSets(producer);
054: boolean nameMatch = HiveMind.isNonBlank(eventSetName);
055: Class consumerClass = consumer.getClass();
056:
057: int count = 0;
058: for (int i = 0; i < sets.length; i++) {
059: EventSetDescriptor set = sets[i];
060: String name = set.getName();
061:
062: if (nameMatch) {
063: if (!eventSetName.equals(name))
064: continue;
065:
066: if (isAssignable(set, consumerClass))
067: addEventListener(producer, set, consumer, location);
068: else {
069: _errorLog.error(ServiceMessages
070: .notCompatibleWithEvent(consumer, set,
071: producer), location, null);
072: }
073:
074: return;
075: }
076:
077: // Not matching on name, add anything that fits!
078:
079: if (isAssignable(set, consumerClass)) {
080: addEventListener(producer, set, consumer, location);
081: count++;
082: }
083: }
084:
085: if (count == 0) {
086: if (nameMatch)
087: _errorLog.error(ServiceMessages.noSuchEventSet(
088: producer, eventSetName), location, null);
089: else
090: _errorLog.error(ServiceMessages.noEventMatches(
091: consumer, producer), location, null);
092: }
093: }
094:
095: private boolean isAssignable(EventSetDescriptor set,
096: Class consumerClass) {
097: return set.getListenerType().isAssignableFrom(consumerClass);
098: }
099:
100: private void addEventListener(Object producer,
101: EventSetDescriptor set, Object consumer, Location location) {
102: Method m = set.getAddListenerMethod();
103:
104: try {
105: m.invoke(producer, new Object[] { consumer });
106: } catch (Exception ex) {
107: _errorLog.error(ServiceMessages.unableToAddListener(
108: producer, set, consumer, location, ex), location,
109: ex);
110:
111: }
112: }
113:
114: private EventSetDescriptor[] getEventSets(Object producer) {
115: return getEventSets(producer.getClass());
116: }
117:
118: private synchronized EventSetDescriptor[] getEventSets(
119: Class producerClass) {
120: EventSetDescriptor[] result = null;
121:
122: if (_producerEventSets == null)
123: _producerEventSets = new HashMap();
124: else
125: result = (EventSetDescriptor[]) _producerEventSets
126: .get(producerClass);
127:
128: if (result == null) {
129: result = findEventSets(producerClass);
130:
131: _producerEventSets.put(producerClass, result);
132: }
133:
134: return result;
135: }
136:
137: private EventSetDescriptor[] findEventSets(Class producerClass) {
138: synchronized (HiveMind.INTROSPECTOR_MUTEX) {
139: try {
140: BeanInfo beanInfo = Introspector
141: .getBeanInfo(producerClass);
142:
143: // Will return an empty array (not null) when the class contains
144: // no event sets.
145:
146: return beanInfo.getEventSetDescriptors();
147: } catch (IntrospectionException ex) {
148: _errorLog.error(ServiceMessages
149: .unableToIntrospectClass(producerClass, ex),
150: null, ex);
151:
152: return new EventSetDescriptor[0];
153: }
154: }
155: }
156:
157: }
|