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 }