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 EventLinker
039 {
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 {
049 _errorLog = errorLog;
050 }
051
052 public void addEventListener(Object producer, String eventSetName, Object consumer,
053 Location location)
054 {
055 EventSetDescriptor[] sets = getEventSets(producer);
056 boolean nameMatch = HiveMind.isNonBlank(eventSetName);
057 Class consumerClass = consumer.getClass();
058
059 int count = 0;
060 for (int i = 0; i < sets.length; i++)
061 {
062 EventSetDescriptor set = sets[i];
063 String name = set.getName();
064
065 if (nameMatch)
066 {
067 if (!eventSetName.equals(name))
068 continue;
069
070 if (isAssignable(set, consumerClass))
071 addEventListener(producer, set, consumer, location);
072 else
073 {
074 _errorLog.error(
075 ServiceMessages.notCompatibleWithEvent(consumer, set, producer),
076 location,
077 null);
078 }
079
080 return;
081 }
082
083 // Not matching on name, add anything that fits!
084
085 if (isAssignable(set, consumerClass))
086 {
087 addEventListener(producer, set, consumer, location);
088 count++;
089 }
090 }
091
092 if (count == 0)
093 {
094 if (nameMatch)
095 _errorLog.error(
096 ServiceMessages.noSuchEventSet(producer, eventSetName),
097 location,
098 null);
099 else
100 _errorLog.error(ServiceMessages.noEventMatches(consumer, producer), location, null);
101 }
102 }
103
104 private boolean isAssignable(EventSetDescriptor set, Class consumerClass)
105 {
106 return set.getListenerType().isAssignableFrom(consumerClass);
107 }
108
109 private void addEventListener(Object producer, EventSetDescriptor set, Object consumer,
110 Location location)
111 {
112 Method m = set.getAddListenerMethod();
113
114 try
115 {
116 m.invoke(producer, new Object[]
117 { consumer });
118 }
119 catch (Exception ex)
120 {
121 _errorLog.error(ServiceMessages.unableToAddListener(
122 producer,
123 set,
124 consumer,
125 location,
126 ex), location, ex);
127
128 }
129 }
130
131 private EventSetDescriptor[] getEventSets(Object producer)
132 {
133 return getEventSets(producer.getClass());
134 }
135
136 private synchronized EventSetDescriptor[] getEventSets(Class producerClass)
137 {
138 EventSetDescriptor[] result = null;
139
140 if (_producerEventSets == null)
141 _producerEventSets = new HashMap();
142 else
143 result = (EventSetDescriptor[]) _producerEventSets.get(producerClass);
144
145 if (result == null)
146 {
147 result = findEventSets(producerClass);
148
149 _producerEventSets.put(producerClass, result);
150 }
151
152 return result;
153 }
154
155 private EventSetDescriptor[] findEventSets(Class producerClass)
156 {
157 synchronized (HiveMind.INTROSPECTOR_MUTEX)
158 {
159 try
160 {
161 BeanInfo beanInfo = Introspector.getBeanInfo(producerClass);
162
163 // Will return an empty array (not null) when the class contains
164 // no event sets.
165
166 return beanInfo.getEventSetDescriptors();
167 }
168 catch (IntrospectionException ex)
169 {
170 _errorLog.error(
171 ServiceMessages.unableToIntrospectClass(producerClass, ex),
172 null,
173 ex);
174
175 return new EventSetDescriptor[0];
176 }
177 }
178 }
179
180 }