http://code.google.com/p/doubleclick/source/detail?r=46
Added:
/tags/doubleclick-1.1
/tags/doubleclick-1.1/inject
/tags/doubleclick-1.1/inject/pom.xml
/tags/doubleclick-1.1/inject/src
/tags/doubleclick-1.1/inject/src/main
/tags/doubleclick-1.1/inject/src/main/java
/tags/doubleclick-1.1/inject/src/main/java/org
/tags/doubleclick-1.1/inject/src/main/java/org/apache
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/BeanNameCache.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/Cache.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/ContextResolver.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/DependencyInjector.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/DependencyInjectorPageInterceptor.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/InjectAware.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/InjectAwarePage.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/PageCacheException.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/PageNotCachedException.java
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/annotation
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/annotation/InjectBean.java
/tags/doubleclick-1.1/inject/src/test
/tags/doubleclick-1.1/inject/src/test/java
/tags/doubleclick-1.1/inject/src/test/java/org
/tags/doubleclick-1.1/inject/src/test/java/org/apache
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject/CacheTest.java
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject/ChildPage.java
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject/ParentPage.java
/tags/doubleclick-1.1/injectspring
/tags/doubleclick-1.1/injectspring/pom.xml
/tags/doubleclick-1.1/injectspring/src
/tags/doubleclick-1.1/injectspring/src/main
/tags/doubleclick-1.1/injectspring/src/main/java
/tags/doubleclick-1.1/injectspring/src/main/java/org
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring/SpringContextResolverImpl.java
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring/SpringControl.java
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring/SpringDependencyInjector.java
/tags/doubleclick-1.1/injectspring/src/test
/tags/doubleclick-1.1/injectspring/src/test/java
/tags/doubleclick-1.1/injectspring/src/test/java/org
/tags/doubleclick-1.1/injectspring/src/test/java/org/apache
/tags/doubleclick-1.1/injectspring/src/test/java/org/apache/click
/tags/doubleclick-1.1/injectspring/src/test/java/org/apache/click/doubleclick
/tags/doubleclick-1.1/injectspring/src/test/java/org/apache/click/doubleclick/injectspring
/tags/doubleclick-1.1/injectspring/src/test/java/org/apache/click/doubleclick/injectspring/SpringContextResolverImplTest.java
/tags/doubleclick-1.1/pom.xml
/tags/doubleclick-1.1/samples
/tags/doubleclick-1.1/samples/click-spring
/tags/doubleclick-1.1/samples/click-spring/pom.xml
/tags/doubleclick-1.1/samples/click-spring/src
/tags/doubleclick-1.1/samples/click-spring/src/main
/tags/doubleclick-1.1/samples/click-spring/src/main/java
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/greetingsservice
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/greetingsservice/GreetingsServiceImpl.java
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/greetingsservice/IGreetingsService.java
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/pages
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/pages/AccessInjectAware.java
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/pages/BorderPage.java
/tags/doubleclick-1.1/samples/click-spring/src/main/java/org/apache/click/doubleclick/samples/clickspring/pages/HomePage.java
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/META-INF
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/WEB-INF
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/WEB-INF/applicationContext.xml
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/WEB-INF/click.xml
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/WEB-INF/web.xml
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/border-template.htm
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/home.htm
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/redirect.html
/tags/doubleclick-1.1/samples/click-spring/src/main/webapp/style.css
/tags/doubleclick-1.1/samples/click-spring/src/test
/tags/doubleclick-1.1/samples/click-spring/src/test/java
/tags/doubleclick-1.1/samples/click-spring/src/test/java/org
/tags/doubleclick-1.1/samples/click-spring/src/test/java/org/apache
/tags/doubleclick-1.1/samples/click-spring/src/test/java/org/apache/click
/tags/doubleclick-1.1/samples/click-spring/src/test/java/org/apache/click/doubleclick
/tags/doubleclick-1.1/samples/click-spring/src/test/java/org/apache/click/doubleclick/samples
/tags/doubleclick-1.1/samples/click-spring/src/test/java/org/apache/click/doubleclick/samples/clickspring
/tags/doubleclick-1.1/samples/pom.xml
=======================================
--- /dev/null
+++ /tags/doubleclick-1.1/inject/pom.xml Sat May 29 01:49:08 2010
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.click.doubleclick</groupId>
+ <artifactId>doubleclick</artifactId>
+ <version>1.0</version>
+ </parent>
+
+ <groupId>org.apache.click.doubleclick</groupId>
+ <artifactId>inject</artifactId>
+ <version>1.0</version>
+ <name>inject</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.click</groupId>
+ <artifactId>click</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/BeanNameCache.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,25 @@
+package org.apache.click.doubleclick.inject;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public class BeanNameCache {
+ private final ConcurrentHashMap<Class<?>, String> nameCache = new
ConcurrentHashMap<Class<?>, String>();
+
+ //TODO: find bean with interface and with bean name; and cache the
found bean names
+ //reference: AnnotProxyFieldValueFactory.java
(org.apache.wicket.spring)
+
+
+// private String getBeanName(Field field) {
+// InjectBean annotation = field.getAnnotation(InjectBean.class);
+//
+// String name = annotation.name();
+// if (name == null || name.length() == 0) {
+// name = nameCache.get(field.getType());
+// if (name == null) {
+// name =
getBeanNameOfClass(contextLocator.getSpringContext(), field.getType());
+// nameCache.put(field.getType(), name);
+// }
+// }
+// return name;
+// }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/Cache.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,88 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.Page;
+import org.apache.click.doubleclick.inject.annotation.InjectBean;
+import org.apache.commons.lang.Validate;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Responsible for caching scanned {@link org.apache.click.Page} classes
and its fields
+ * with {@link org.apache.click.doubleclick.inject.annotation.InjectBean}
annotation. The
+ * caching contains all annotated fields for the page instance and its
parent classes.
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+public class Cache {
+
+ //annotation
+ private Class<? extends Annotation> annotationClass = InjectBean.class;
+
+ //the cache
+ private ConcurrentHashMap<Class<? extends Page>, List<Field>> cache =
new ConcurrentHashMap<Class<? extends Page>, List<Field>>();
+
+ /**
+ * Returns annotated fields for supplied {@link org.apache.click.Page}.
+ *
+ * @param page The page instance.
+ * @return List of fields annotated with {@link
org.apache.click.doubleclick.inject.annotation.InjectBean}.
+ * If the page is null an empty list will be
+ * @throws PageCacheException If page null.
+ * @throws PageNotCachedException If the page is not cached yet.
+ */
+ public List<Field> getAnnotatedFieldsForPage(Page page) throws
PageCacheException, PageNotCachedException {
+ return getAnnotatedFieldsForPage(page.getClass());
+ }
+
+ /**
+ * Returns annotated fields for supplied {@link org.apache.click.Page}
class.
+ *
+ * @param clazz The page class.
+ * @return List of fields annotated with {@link
org.apache.click.doubleclick.inject.annotation.InjectBean}
+ * @throws PageCacheException If page class is null.
+ * @throws PageNotCachedException If the page is not cached yet.
+ */
+ public List<Field> getAnnotatedFieldsForPage(Class<? extends Page>
clazz) throws PageCacheException, PageNotCachedException {
+ Validate.notNull(clazz, "Page can not be null");
+ if (!isCached(clazz)) {
+ List<Field> fields = getAnnotatedFields(clazz);
+ cache.put(clazz, fields);
+ return fields;
+ }
+ return cache.get(clazz);
+ }
+
+ public boolean isCached(Class<? extends Page> clazz) throws
PageCacheException {
+ Validate.notNull(clazz, "Page can not be null");
+ return cache.containsKey(clazz);
+ }
+
+ /**
+ * Find out all fields which is annotated with {@link
org.apache.click.doubleclick.inject.annotation.InjectBean}.
+ *
+ * @param target The target class to scan.
+ * @return A list of fields annotated with {@link
org.apache.click.doubleclick.inject.annotation.InjectBean};
+ * otherwise an empty list.
+ */
+ public List<Field> getAnnotatedFields(Class<?> target) {
+ Validate.notNull(target, "The target can not be null");
+ List<Field> foundFields = new ArrayList<Field>();
+
+ // scanning until Page.class will not work for other non page
classes
+ //while (target != null && !target.equals(Page.class)) {
+ while (target != null) {
+ Field[] fields = target.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(annotationClass)) {
+ foundFields.add(field);
+ }
+ }
+ target = target.getSuperclass();
+ }
+ return foundFields;
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/ContextResolver.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,42 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.Page;
+
+/**
+ * Underlying implementation is responsible for resolving different type
of context. The context type
+ * includes {@link javax.servlet.ServletContext} and other dependency
injector contexts (Spring, Guice, etc).
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ * @param <T> The context type
+ */
+public interface ContextResolver<T> {
+ /**
+ * Resolves dependency injector context (Spring, Guice, etc).
+ *
+ * @return Resolved context.
+ */
+ public T resolveDependencyInjectorContext();
+
+ /**
+ * Resolves dependency injector context (Spring, Guice, etc) retrieved
using the page.
+ *
+ * @param page The page to retrieve the injector context.
+ * @return Resolved context.
+ */
+ public T resolveDependencyInjectorContext(Page page);
+
+// /**
+// * Resolves servlet context from thread local using {@link
org.apache.click.Context}.
+// *
+// * @return Retrieved servlet context.
+// */
+// public ServletContext resolveServletContext();
+//
+// /**
+// * Resolves servlet context for specific page using {@link
org.apache.click.Context}
+// *
+// * @param page The page instance to find the context.
+// * @return Retrieved servlet context.
+// */
+// public ServletContext resolveServletContext(Page page);
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/DependencyInjector.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,54 @@
+package org.apache.click.doubleclick.inject;
+
+/**
+ * Underlying implementation should be responsible for injecting
dependencies on all fields which is annotated
+ * with {@link org.apache.click.doubleclick.inject.annotation.InjectBean}.
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+public interface DependencyInjector {
+ /**
+ * Injects all dependencies for member and inherited variables
annotated with
+ * {@link org.apache.click.doubleclick.inject.annotation.InjectBean}.
Whether
+ * a real instance or a proxy will be injected will be determined from
the annotation.
+ *
+ * @param target The target instance to inject dependencies.
+ * @param <T> Type of the target.
+ * @return the target with all dependency injected.
+ */
+ public <T> T injectDependencies(T target);
+
+ /**
+ * Injects all dependencies for member and inherited variables
annotated with
+ * {@link org.apache.click.doubleclick.inject.annotation.InjectBean}.
A proxy will
+ * be injected if the <i>injectProxy</i> is true. Otherwise the real
instance will
+ * be injected.
+ *
+ * @param target The target instance to inject dependencies.
+ * @param injectProxy Proxy will be injected if true, otherwise real
instance
+ * will be injected.
+ * @param <T> The type of the target.
+ * @return the target with all dependencies injected.
+ */
+ public <T> T injectDependencies(T target, boolean injectProxy);
+
+ /**
+ * Gets bean for supplied class type. Always returns the first bean if
more then one
+ * bean is found for supplied class type.
+ *
+ * @param beanClass The bean class.
+ * @param <T> The type of the bean class.
+ * @return Found bean instance.
+ */
+ public <T> T getBean(Class<T> beanClass);
+
+ /**
+ * Gets bean as proxy for supplied class type. Always returns the
first bean if more
+ * then one bean is found for supplied class type.
+ *
+ * @param beanClass The bean class.
+ * @param <T> The type of the bean class.
+ * @return Generated proxy for found bean instance.
+ */
+ public <T> T getBeanAsProxy(Class<T> beanClass);
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/DependencyInjectorPageInterceptor.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,47 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.Context;
+import org.apache.click.Page;
+import org.apache.click.PageInterceptor;
+import org.apache.commons.lang.Validate;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Page interceptor to inject dependencies
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+public class DependencyInjectorPageInterceptor implements PageInterceptor {
+
+ private DependencyInjector dependencyInjector;
+ public static final String DEPENDENCY_INJECTOR
= "currentDependencyInjector";
+
+ public DependencyInjectorPageInterceptor() {
+ Validate.isTrue(Context.hasThreadLocalContext(), "Thread local
context is not available");
+ ServletContext servletContext =
Context.getThreadLocalContext().getServletContext();
+ Validate.notNull(servletContext, "Servlet context is null");
+
Validate.notNull(servletContext.getAttribute(DEPENDENCY_INJECTOR), "No
dependency injector found on servlet context.");
+ dependencyInjector = (DependencyInjector)
servletContext.getAttribute(DEPENDENCY_INJECTOR);
+ }
+
+ @Override
+ public boolean preCreate(Class<? extends Page> aClass, Context
context) {
+ return true;
+ }
+
+ @Override
+ public boolean postCreate(Page page) {
+ dependencyInjector.injectDependencies(page);
+ return true;
+ }
+
+ @Override
+ public boolean preResponse(Page page) {
+ return true;
+ }
+
+ @Override
+ public void postDestroy(Page page) {
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/InjectAware.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,46 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.Context;
+import org.apache.commons.lang.Validate;
+
+/**
+ * Inject aware implementation for non page file to use to inject
dependencies.
+ * If configured properly all click {@link org.apache.click.Page}'s
dependencies are
+ * injected when the page is instantiated. Which is not valid for
non-{@link org.apache.click.Page}
+ * classes. Non-{@link org.apache.click.Page} classes can extend this
class to
+ * inject dependencies when instantiated.
+ * <p/>
+ * If the class is already extending another class or user does not want
to extend
+ * any class for some specific reason, then they should use
org.apache.click.doubleclick.inject.InjectAware.injectDependencies(Object)
+ * <p/>
+ * <p/>
+ * <pre>
+ * {@code
+ * class MyNonPageClass {
+ * public MyNonPageClass() {
+ * InjectAware.injectDependencies(this);
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ * @see org.apache.click.doubleclick.inject.InjectAwarePage
+ */
+public class InjectAware {
+ protected InjectAware() {
+ injectDependencies(this);
+ }
+
+ public static void injectDependencies(Object target) {
+ Validate.notNull(target, "Target can not be null");
+ Validate.isTrue(Context.hasThreadLocalContext(), "Thread local
context is not available");
+ Object dependencyInjectorObj =
Context.getThreadLocalContext().getServletContext().getAttribute(DependencyInjectorPageInterceptor.DEPENDENCY_INJECTOR);
+
+ Validate.notNull(dependencyInjectorObj, "Dependency injector is
null on servlet context");
+ Validate.isTrue(dependencyInjectorObj instanceof
DependencyInjector, "Invalid dependency injector. Expected " +
DependencyInjector.class.getSimpleName() + ", but found " +
dependencyInjectorObj.getClass().getSimpleName());
+
+ DependencyInjector dependencyInjector = (DependencyInjector)
dependencyInjectorObj;
+ dependencyInjector.injectDependencies(target);
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/InjectAwarePage.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,27 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.Page;
+import org.apache.commons.lang.Validate;
+
+/**
+ * Inject aware {@link org.apache.click.Page}. User can inherit this page
to inject
+ * dependencies.
+ * <p/>
+ * <b><u>IMPORTANT</u></b>: If dependency injector control (e.g:
SpringControl,
+ * GuiceControl, etc) is configured on click.xml, Then no need to extend
this
+ * page. On that case the injection takes place automatically.
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+public class InjectAwarePage extends Page {
+ protected InjectAwarePage() {
+
+ Object dependencyInjectorObj =
getContext().getServletContext().getAttribute(DependencyInjectorPageInterceptor.DEPENDENCY_INJECTOR);
+
+ Validate.notNull(dependencyInjectorObj, "Dependency injector is
null on servlet context");
+ Validate.isTrue(dependencyInjectorObj instanceof
DependencyInjector, "Invalid dependency injector. Expected " +
DependencyInjector.class.getSimpleName() + ", but found " +
dependencyInjectorObj.getClass().getSimpleName());
+
+ DependencyInjector dependencyInjector = (DependencyInjector)
dependencyInjectorObj;
+ dependencyInjector.injectDependencies(this);
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/PageCacheException.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,14 @@
+package org.apache.click.doubleclick.inject;
+
+/**
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+public class PageCacheException extends Exception {
+ public PageCacheException(String message) {
+ super(message);
+ }
+
+ public PageCacheException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/PageNotCachedException.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,14 @@
+package org.apache.click.doubleclick.inject;
+
+/**
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+public class PageNotCachedException extends Exception {
+ public PageNotCachedException(String message) {
+ super(message);
+ }
+
+ public PageNotCachedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/main/java/org/apache/click/doubleclick/inject/annotation/InjectBean.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,33 @@
+package org.apache.click.doubleclick.inject.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to use for dependency injection.
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface InjectBean {
+
+ /**
+ * Optional attribute for specifying if proxy injection is needed
+ * or real instance. By default real instance is injected.
+ *
+ * @return Real proxy will be injected if true, otherwise instance
+ * will be injected. Default value is false.
+ */
+ //boolean injectProxy() default false;
+
+ /**
+ * Optional attribute for specifying the name of the bean. If not
specified, the bean will be
+ * looked up by the class type of the field..
+ *
+ * @return name
+ */
+ //String beanName() default "";
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject/CacheTest.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,31 @@
+package org.apache.click.doubleclick.inject;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+public class CacheTest {
+
+ @Test
+ public void getAnnotatedFieldsForPageTest() throws
PageNotCachedException, PageCacheException {
+ Cache cache = new Cache();
+ List<Field> fields =
cache.getAnnotatedFieldsForPage(ParentPage.class);
+ Assert.assertNotNull(fields);
+ Assert.assertTrue(fields.size() == 1);
+
+ fields = cache.getAnnotatedFieldsForPage(ChildPage.class);
+ Assert.assertNotNull(fields);
+ Assert.assertTrue(fields.size() == 2);
+ }
+
+ @Test
+ public void isCachedTest() throws PageCacheException,
PageNotCachedException {
+ Cache cache = new Cache();
+ Assert.assertTrue(!cache.isCached(ChildPage.class));
+
+ cache.getAnnotatedFieldsForPage(ChildPage.class);
+ Assert.assertTrue(cache.isCached(ChildPage.class));
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject/ChildPage.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,8 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.doubleclick.inject.annotation.InjectBean;
+
+public class ChildPage extends ParentPage {
+ @InjectBean
+ private String childMessage;
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/inject/src/test/java/org/apache/click/doubleclick/inject/ParentPage.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,9 @@
+package org.apache.click.doubleclick.inject;
+
+import org.apache.click.Page;
+import org.apache.click.doubleclick.inject.annotation.InjectBean;
+
+public class ParentPage extends Page {
+ @InjectBean
+ private String parentMessage;
+}
=======================================
--- /dev/null
+++ /tags/doubleclick-1.1/injectspring/pom.xml Sat May 29 01:49:08 2010
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>doubleclick</artifactId>
+ <groupId>org.apache.click.doubleclick</groupId>
+ <version>1.0</version>
+ </parent>
+
+ <groupId>org.apache.click.doubleclick</groupId>
+ <artifactId>injectspring</artifactId>
+ <version>1.0</version>
+ <name>injectspring</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.click.doubleclick</groupId>
+ <artifactId>inject</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.click</groupId>
+ <artifactId>click</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!--<dependency>-->
+ <!--<groupId>org.mockito</groupId>-->
+ <!--<artifactId>mockito-core</artifactId>-->
+ <!--</dependency>-->
+ <!--<dependency>-->
+ <!--<groupId>org.mockito</groupId>-->
+ <!--<artifactId>mockito-all</artifactId>-->
+ <!--</dependency>-->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock.modules</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock.api</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+ </dependencies>
+</project>
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring/SpringContextResolverImpl.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,33 @@
+package org.apache.click.doubleclick.injectspring;
+
+import org.apache.click.Context;
+import org.apache.click.Page;
+import org.apache.click.doubleclick.inject.ContextResolver;
+import org.apache.commons.lang.Validate;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContext;
+
+public class SpringContextResolverImpl<T extends ApplicationContext>
implements ContextResolver<T> {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T resolveDependencyInjectorContext() {
+ Validate.isTrue(Context.hasThreadLocalContext(), "Thread local
context is not available");
+ ServletContext servletContext =
Context.getThreadLocalContext().getServletContext();
+ Validate.notNull(servletContext, "Servlet context is null");
+ return (T)
WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public T resolveDependencyInjectorContext(Page page) {
+ Validate.notNull(page, "Page can not be null while resolving
servlet context");
+ ServletContext servletContext =
page.getContext().getServletContext();
+ return (T)
WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring/SpringControl.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,34 @@
+package org.apache.click.doubleclick.injectspring;
+
+import org.apache.click.control.AbstractControl;
+import
org.apache.click.doubleclick.inject.DependencyInjectorPageInterceptor;
+import org.springframework.web.context.ContextLoader;
+import org.springframework.web.context.WebApplicationContext;
+
+import javax.servlet.ServletContext;
+
+/**
+ * Responsible for loading spring context. By default it will look for
<i>applicationContext.xml</i>
+ * into <i>WEB-INF</i> directory. To override the default location we have
to declare
+ * <i>contextConfigLocation</i> context param on <i>web.xml</i>. Ex-
+ * <p/>
+ * <pre>
+ * {@code
+ * <context-param>
+ * <param-name>contextConfigLocation</param-name>
+ * <param-value>/WEB-INF/myApplicationContext.xml</param-value>
+ * </context-param>
+ * }
+ * </pre>
+ *
+ * @Author Jahid Shohel(develop...@gmail.com)
+ */
+public class SpringControl extends AbstractControl {
+ @Override
+ public void onDeploy(ServletContext servletContext) {
+ ContextLoader contextLoader = new ContextLoader();
+ WebApplicationContext applicationContext =
contextLoader.initWebApplicationContext(servletContext);
+
servletContext.setAttribute(DependencyInjectorPageInterceptor.DEPENDENCY_INJECTOR,
new SpringDependencyInjector());
+ servletContext.setAttribute("dependencyInjectorContext",
applicationContext);
+ }
+}
=======================================
--- /dev/null
+++
/tags/doubleclick-1.1/injectspring/src/main/java/org/apache/click/doubleclick/injectspring/SpringDependencyInjector.java
Sat May 29 01:49:08 2010
@@ -0,0 +1,102 @@
+package org.apache.click.doubleclick.injectspring;
+
+import org.apache.click.doubleclick.inject.Cache;
+import org.apache.click.doubleclick.inject.ContextResolver;
+import org.apache.click.doubleclick.inject.DependencyInjector;
+import org.springframework.context.ApplicationContext;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+/**
+ * Responsible for spring dependency injection.
+ *
+ * @author Jahid Shohel(develop...@gmail.com)
+ */
+
+public class SpringDependencyInjector implements DependencyInjector {
+ private ContextResolver<ApplicationContext> contextResolver;
+ private Cache cache;
+
+ public SpringDependencyInjector() {
+ this.contextResolver = new
SpringContextResolverImpl<ApplicationContext>();
+ this.cache = new Cache();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <T> T injectDependencies(T target) {
+ //TODO: instead of passing false, check in the annotation. now its
hard coded
+ return injectDependencies(target, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <T> T injectDependencies(T target, boolean injectProxy) {
+ if (target == null) {
+ throw new RuntimeException("Target can not be null when
injecting dependencies");
+ }
+
+ List<Field> fields = cache.getAnnotatedFields(target.getClass());
+
+ for (Field field : fields) {
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+
+ try {
+ if (field.get(target) == null) {
+ Class<?> fieldType = field.getType();
+ if (injectProxy) {
+ //TODO: generate and inject proxy
+ }
+ Object value = getBean(fieldType);
+ field.set(target, value);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Error happened when trying to
set bean for type: " + field.getType(), e);
+ }
+ }
+ return target;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <T> T getBean(Class<T> beanClass) {
+ ApplicationContext applicationContext =
contextResolver.resolveDependencyInjectorContext();
+ String[] beanNames =
applicationContext.getBeanNamesForType(beanClass);
+
+ if (beanNames.length == 0) {
+ throw new RuntimeException("No bean found for type: " +
beanClass);
+ } else if (beanNames.length > 1) {
+ //TODO: if more then one type found, then we look for
name(name declared on annotation)
+ throw new RuntimeException("More then one bean found for
type: " + beanClass.getSimpleName());
+ }
+ return (T) applicationContext.getBean(beanNames[0], beanClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public <T> T getBeanAsProxy(Class<T> beanClass) {
+ // TODO: for lazy init with proxy
+ return null;
+ }
+
+// private String getBeanName(Field field) {
+// InjectBean annotation = field.getAnnotation(InjectBean.class);
+//
+// String name = annotation.name();
+// if (name==null || name.length()==0) {
+// name = beanNameCache.get(field.getType());
+// if (name == null) {
+// name = getBeanNameOfClass(contextLocator.getSpringContext(),
field.getType());
+// beanNameCache.put(field.getType(), name);
+// }
+// }
+// return name;
+// }
+}
=======================================
***Additional files exist in this changeset.***