1 28 29 30 package com.caucho.widget; 31 32 import com.caucho.util.L10N; 33 34 import java.io.IOException ; 35 import java.lang.reflect.InvocationTargetException ; 36 import java.lang.reflect.Method ; 37 import java.util.Collections ; 38 import java.util.HashMap ; 39 import java.util.Map ; 40 import java.util.logging.Level ; 41 import java.util.logging.Logger ; 42 43 class RendererCache 44 { 45 private static L10N L = new L10N( RendererCache.class ); 46 47 static protected final Logger log = 48 Logger.getLogger( RendererCache.class.getName() ); 49 50 static final WidgetRenderer<Object > NULL_RENDERER 51 = new WidgetRenderer<Object >(){ 52 public void render( WidgetConnection connection, 53 Object widgetState ) 54 throws WidgetException, IOException 55 { 56 } 57 }; 58 59 private Map <String , WidgetRenderer> _rendererCache 60 = Collections.synchronizedMap(new HashMap <String , WidgetRenderer>()); 61 62 public <S extends WidgetState> 63 WidgetRenderer<S> getRenderer( WidgetConnection connection, 64 Widget<S> widget, 65 S widgetState ) 66 { 67 String contentType = connection.getContentType(); 68 WidgetMode widgetMode = widgetState.getWidgetMode(); 69 70 String cacheKey = contentType + Character.MAX_VALUE + widgetMode.toString(); 71 72 WidgetRenderer renderer = _rendererCache.get( cacheKey ); 73 74 if ( renderer != null ) 75 return (WidgetRenderer<S>) renderer; 76 77 if ( renderer == NULL_RENDERER ) { 78 if ( log.isLoggable( Level.FINEST ) ) 79 log.finest( 80 L.l( "no WidgetRenderer for contentType {0} for widget type {1}", 81 contentType, widget.getClass().getName() ) ); 82 83 return null; 84 } 85 86 String methodName = createMethodName( contentType ); 87 88 Class widgetClass = widget.getClass(); 89 Class widgetStateClass = widgetState.getClass(); 90 91 93 95 96 100 while ( renderer == null && widgetStateClass != null ) { 101 102 104 renderer 105 = createMethodNameRenderer( widget, widgetClass, widgetStateClass, methodName ); 106 107 109 if ( renderer == null ) 110 renderer 111 = createContentTypeRenderer( widget, widgetClass, widgetStateClass, contentType ); 112 113 115 widgetStateClass = widgetStateClass.getSuperclass(); 116 } 117 118 if ( renderer == null ) { 119 if ( log.isLoggable( Level.FINE ) ) 120 log.fine( 121 L.l( "no WidgetRenderer for contentType {0} for widget type {1}", 122 contentType, widget.getClass().getName() ) ); 123 124 renderer = NULL_RENDERER; 125 } 126 127 _rendererCache.put( cacheKey, renderer ); 128 129 return (WidgetRenderer<S>) renderer; 130 } 131 132 133 private <S extends WidgetState> 134 WidgetRenderer<S> createMethodNameRenderer( final Widget<S> widget, 135 Class widgetClass, 136 Class widgetStateClass, 137 String methodName ) 138 { 139 Class [] methodArgs 140 = new Class [] { WidgetConnection.class, widgetStateClass }; 141 142 Method findMethod = null; 143 144 try { 145 findMethod = widgetClass.getMethod( methodName, methodArgs ); 146 } 147 catch (NoSuchMethodException ex) { 148 } 149 150 if ( findMethod != null ) { 151 if ( log.isLoggable( Level.FINEST ) ) 152 log.finest( L.l( "WidgetRenderer for widget type {0} is method {1}()", 153 widget.getClass().getName(), methodName ) ); 154 155 final Method method = findMethod; 156 157 return new WidgetRenderer<S>() { 158 public void render( WidgetConnection connection, S widgetState ) 159 throws WidgetException, IOException 160 { 161 try { 162 method.invoke( widget, 163 new Object [] { connection, widgetState }); 164 } 165 catch (IllegalAccessException ex) { 166 throw new WidgetException(ex); 167 } 168 catch (InvocationTargetException ex) { 169 throw new WidgetException(ex); 170 } 171 } 172 }; 173 } 174 else 175 return null; 176 } 177 178 private <S extends WidgetState> 179 WidgetRenderer createContentTypeRenderer( final Widget<S> widget, 180 Class widgetClass, 181 Class widgetStateClass, 182 final String contentType ) 183 { 184 Class [] methodArgs 185 = new Class [] { String .class, WidgetConnection.class, widgetStateClass }; 186 187 Method findMethod = null; 188 189 try { 190 findMethod = widgetClass.getMethod( "render", methodArgs ); 191 } 192 catch (NoSuchMethodException ex) { 193 } 194 195 196 if ( findMethod != null ) { 197 if ( log.isLoggable( Level.FINEST ) ) 198 log.finest( L.l( "WidgetRenderer for contentType {0} for widget type {1} is method {2}()", contentType, widget.getClass().getName(), "render" ) ); 199 200 final Method method = findMethod; 201 202 return new WidgetRenderer<S>() { 203 public void render( WidgetConnection connection, S widgetState ) 204 throws WidgetException, IOException 205 { 206 try { 207 method.invoke( widget, 208 new Object [] {contentType, connection, widgetState}); 209 } 210 catch (IllegalAccessException ex) { 211 throw new WidgetException(ex); 212 } 213 catch (InvocationTargetException ex) { 214 throw new WidgetException(ex); 215 } 216 } 217 }; 218 } 219 else 220 return null; 221 } 222 223 private String createMethodName( String contentType ) 224 { 225 StringBuffer methodName = new StringBuffer (); 226 methodName.append("render"); 227 228 boolean toUpper = true; 229 230 for (int i = 0; i < contentType.length(); i++) { 231 char ch = contentType.charAt( i ); 232 233 boolean isIdentifier = 234 i == 0 ? Character.isJavaIdentifierStart( ch ) 235 : Character.isJavaIdentifierPart( ch ); 236 237 if ( ! isIdentifier ) { 238 if ( toUpper ) 239 ch = '_'; 240 else { 241 toUpper = true; 242 continue; 243 } 244 } 245 246 if ( toUpper ) 247 ch = Character.toUpperCase( ch ); 248 249 methodName.append( ch ); 250 251 toUpper = false; 252 253 } 254 255 return methodName.toString(); 256 } 257 } 258 | Popular Tags |