Created
November 10, 2011 20:29
-
-
Save gonzalad/1356107 to your computer and use it in GitHub Desktop.
Seamfaces 147 - viewActions refactoring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ViewConfigStore { | |
private Map<String,ViewConfigDescriptor> viewConfigDescriptors = new ConcurrentHashMap<String, ViewConfigDescriptor>(); | |
private Map<String,ViewConfigDescriptor> viewConfigRuntimeDescriptors = new ConcurrentHashMap<String, ViewConfigDescriptor>(); | |
public void addViewConfigDescriptor(ViewConfigDescriptor descriptor); | |
List<ViewConfigDescriptor> getViewConfigDescriptors(); | |
ViewConfigDescriptor getViewConfigDescriptorForValue(Object value); | |
// returns 'compiled' viewConfigDescriptor | |
// this correspond to the fusioned stack of patterned-viewId descriptors | |
ViewConfigDescriptor getRuntimeViewConfigDescriptor(String viewId); | |
fireViewConfigStoreConfiguredEvent(); | |
} | |
public class ViewConfigDescriptor { | |
private String viewId; | |
private List<Object> values = new ArrayList<Object>(); | |
private List<Annotation> metaData = new ArrayList<Annotation>(); | |
private List<ViewActionHandler> viewActionHandlers; | |
private ViewControllerDescriptor viewControllerDescriptor; | |
public void addViewActionHandler(ViewActionHandler); | |
public void executeViewActionHandlers(PhaseInstant); | |
} | |
public class ViewControllerDescriptor { | |
private Map<PhaseInstant, List<ViewActionStrategy>> phaseMethods = new HashMap<PhaseInstant, List<ViewActionStrategy>>(); | |
} | |
@Target(ElementType.TYPE) | |
@Retention(RetentionPolicy.RUNTIME) | |
@Documented | |
public @interface ViewAction { | |
Class<?> value(); | |
} | |
public interface ViewActionHandler { | |
boolean handles(PhaseInstant phaseInstant); | |
Integer getOrder(); | |
Object execute(); | |
} | |
public interface ViewActionHandlerProvider<V extends ViewAction> { | |
List<ViewActionHandler> getActionHandlers(); | |
void initialize(X annotation); | |
} | |
-- | |
@Target(ElementType.TYPE) | |
@Retention(RetentionPolicy.RUNTIME) | |
@ViewAction(ElViewActionHandler.class) | |
public @interface ElViewAction { | |
String value(); | |
Class<?> phase() default RenderResponse.class; | |
boolean before() default true; | |
boolean onPostback() default true; // TODO vérifier val par défaut Seam 2 | |
} | |
//TODO : comment faire de ces Handler des beans CDI ? | |
public class ElViewActionHandler implements ViewActionHandler<ElViewAction> { | |
private PhaseInstant phaseInstant; | |
private MethodExpression methodExpression; | |
private ElViewAction annotation; | |
boolean handles(PhaseInstant phaseInstant) { | |
return this.phaseInstant.equals(phaseInstant); | |
} | |
void initialize(ElViewAction annotation) { | |
phaseInstant = new PhaseInstant(annotation.phase(), annotation.before()); | |
} | |
public Object execute() { | |
FacesContext facesContext = FacesContext.getCurrentInstance(); | |
if (methodExpression == null) { | |
methodExpression = facesContext.getApplication().getExpressionFactory() | |
.createMethodExpression(facesContext.getELContext(), annotation.value(), null, new Class[] {}); | |
} | |
return methodExpression.invoke(FacesContext.getCurrentInstance().getELContext(), null); | |
} | |
} | |
-- | |
@Target(ElementType.TYPE) | |
@Retention(RetentionPolicy.RUNTIME) | |
@ViewAction(ViewControllerHandler.class) | |
public @interface ViewController { | |
Class<?>[] value(); | |
} | |
public class ViewControllerHandler implements ViewActionHandler<ViewController> { | |
@Inject | |
private BeanManager beanManager; | |
void initialize(ElViewAction annotation) { | |
//TODO : récup d'un bean CDI du contrôleur | |
} | |
... | |
} | |
public class ViewControllerExtension implements Extension { | |
public void observeViewConfigStoreConfigured(@Observes @ViewConfigStoreConfigured ViewConfigStoreEvent event) { | |
for (ViewConfigDescriptor viewConfigDescriptor : event.getViewConfigStore().getViewConfigDescriptors()) { | |
addViewControllersIfNeeded(viewConfigDescriptor); | |
} | |
} | |
private void addViewControllersIfNeeded(ViewConfigDescriptor viewConfigDescriptor) { | |
//extraction des annotations ViewController des metadata de viewConfigDesc | |
} | |
} | |
-- | |
@Target(ElementType.TYPE) | |
@Retention(RetentionPolicy.RUNTIME) | |
@Documented | |
public @interface ViewActionBindingType { | |
} | |
//Remplace ViewActionBindingTypeDescriptor | |
public class ViewActionBindingTypeHandler implements ViewActionHandler<ViewActionBindingType> { | |
private Annotation annotation; | |
private Object viewControllerValue; | |
private AnnotatedMethod<?> annotatedMethod; | |
private PhaseInstant phaseInstant; | |
public ViewActionBindingTypeHandler() { | |
} | |
//NOOP Hack juste pour conserver signature... | |
void initialize(ViewActionBindingType annotation) { | |
} | |
... | |
} | |
public class ViewControllerExtension implements Extension { | |
private final List<ViewActionBindingTypeHandler> ViewActionBindingTypeHandlers = new ArrayList<ViewActionBindingTypeHandler>(); | |
@Inject | |
BeanManager beanManager; | |
public <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> event) { | |
AnnotatedType<T> tp = event.getAnnotatedType(); | |
for (final AnnotatedMethod<?> m : tp.getMethods()) { | |
for (final Annotation annotation : m.getAnnotations()) { | |
if (annotation.annotationType().isAnnotationPresent(ViewActionBindingType.class)) { | |
Object viewConfigValue = getValue(annotation); | |
if (viewConfigValue == null) { | |
throw new IllegalArgumentException("Annotation " + annotation | |
+ " invalid : no view specified"); | |
} | |
List<ViewActionBindingTypeDescriptor> actions = descriptors.get(viewConfigValue); | |
if (actions == null) { | |
actions = new ArrayList<ViewActionBindingTypeDescriptor>(); | |
descriptors.put(viewConfigValue, actions); | |
} | |
ViewActionBindingTypeDescriptor descriptor = new ViewActionBindingTypeDescriptor(m, annotation, viewConfigValue); | |
actions.add(descriptor); | |
} | |
} | |
} | |
} | |
public void observeViewConfigStoreConfigured(@Observes @ViewConfigStoreConfigured ViewConfigStoreEvent event) { | |
registerViewActionBindingTypes(event.getViewConfigStore()); | |
} | |
private void registerViewActionBindingTypes(ViewConfigStore viewConfigStore, BeanManager beanManager) { | |
for (ViewActionBindingTypeDescriptor> viewActionBindingTypeHandler : viewActionBindingTypeHandlers) { | |
ViewConfigDescriptor viewConfigDescriptor = viewConfigStore.getViewConfigDescriptorForValue(viewActionBindingTypeEntry.getKey(); | |
//TODO vérif non null | |
viewConfigDescriptor.addViewAction(viewActionBindingTypeHandler); | |
} | |
} | |
private Object getValue(Annotation annotation) { | |
Method valueMethod; | |
try { | |
valueMethod = annotation.annotationType().getDeclaredMethod("value"); | |
} catch (NoSuchMethodException ex) { | |
throw new IllegalArgumentException("value method must be declared and must resolve to a valid view", ex); | |
} catch (SecurityException ex) { | |
throw new IllegalArgumentException("value method must be accessible", ex); | |
} | |
try { | |
return valueMethod.invoke(annotation); | |
} catch (IllegalAccessException ex) { | |
throw new IllegalArgumentException("value method must be accessible", ex); | |
} catch (InvocationTargetException ex) { | |
throw new RuntimeException(ex); | |
} | |
} | |
} | |
--------------- | |
//Remplace ViewActionBindingTypeDescriptor | |
public class SecurityBindingTypeHandler implements ViewActionHandler<Object> { | |
List<? extends Annotation> annotations | |
private PhaseInstant phaseInstant; | |
public SecurityBindingTypeHandler() { | |
} | |
//NOOP Hack juste pour conserver signature... | |
void initialize(Object annotation) { | |
} | |
public Object execute() { | |
if (annotations == null || annotations.isEmpty()) { | |
log.debug("Annotations is null/empty"); | |
return; | |
} | |
AuthorizationCheckEvent event = new AuthorizationCheckEvent(annotations); | |
authorizationCheckEvent.fire(event); | |
if (!event.isPassed()) { | |
if (!identity.isLoggedIn()) { | |
log.debug("Access denied - not logged in"); | |
redirectToLoginPage(context, viewRoot); | |
return; | |
} else { | |
log.debug("Access denied - not authorized"); | |
notAuthorizedEventEvent.fire(new NotAuthorizedEvent()); | |
redirectToAccessDeniedView(context, viewRoot); | |
return; | |
} | |
} else { | |
log.debug("Access granted"); | |
} | |
} | |
} | |
public class SecurityBindingTypeExtension implements Extension { | |
public void observeViewConfigStoreConfigured(@Observes @ViewConfigStoreConfigured ViewConfigStoreEvent event) { | |
for (ViewConfigDescriptor viewConfigDescriptor : event.getViewConfigStore().getViewConfigDescriptors()) { | |
addSecurityBindingTypeHandlerIfNeeded(viewConfigDescriptor); | |
} | |
} | |
private void addSecurityBindingTypeHandlerIfNeeded(ViewConfigDescriptor viewConfigDescriptor) { | |
//extraction des annotations de sécu du viewConfigDescriptor | |
} | |
} | |
--------------------------- | |
public class ViewActionPhaseListener { | |
private transient final Logger log = Logger.getLogger(ViewActionPhaseListener.class); | |
@Inject | |
private ViewControllerStore viewControllerStore; | |
// TODO : should be executed after SecurityPhaseListener | |
public void observerBeforePhase(@Observes @Before PhaseEvent event) { | |
PhaseId phaseId = event.getPhaseId(); | |
log.debugf("Before {1} event", phaseId); | |
if (event.getFacesContext().getViewRoot() == null) { | |
log.debug("viewRoot null, skipping view actions"); | |
return; | |
} | |
ViewConfigDescriptor viewConfig = viewControllerStore.getRuntimeViewConfigDescriptor(event.getFacesContext() | |
.getViewRoot().getViewId()); | |
viewConfig.executeViewActions(new PhaseInstant(event.getPhaseId(), true)); | |
} | |
public void observerAfterPhase(@Observes @After PhaseEvent event) { | |
PhaseId phaseId = event.getPhaseId(); | |
log.debugf("After {1} event", phaseId); | |
ViewConfigDescriptor viewConfig = viewControllerStore.getRuntimeViewConfigDescriptor(event.getFacesContext() | |
.getViewRoot().getViewId()); | |
viewConfig.executeViewActions(new PhaseInstant(event.getPhaseId(), false)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment