Skip to content

Instantly share code, notes, and snippets.

@gonzalad
Created November 10, 2011 20:29
Show Gist options
  • Save gonzalad/1356107 to your computer and use it in GitHub Desktop.
Save gonzalad/1356107 to your computer and use it in GitHub Desktop.
Seamfaces 147 - viewActions refactoring
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