ISIS-1223 Upgrade Wicket to 7.x

Copy temporarily Wicket's Guice classes to workaround issue 
https://issues.apache.org/jira/browse/WICKET-6020.
Once Wicket 7.2.0 is released these classes should be removed!


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/5625c6c4
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/5625c6c4
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/5625c6c4

Branch: refs/heads/master
Commit: 5625c6c4cec59c57e00cffa0159a89795b46addc
Parents: 8eab457
Author: Martin Tzvetanov Grigorov <[email protected]>
Authored: Mon Nov 2 21:35:42 2015 +0100
Committer: Martin Tzvetanov Grigorov <[email protected]>
Committed: Mon Nov 2 21:35:42 2015 +0100

----------------------------------------------------------------------
 .../wicket/viewer/IsisWicketApplication.java    |   4 +-
 .../viewer/guice/GuiceComponentInjector.java    | 137 ++++++++++++++++
 .../viewer/guice/GuiceFieldValueFactory.java    | 161 ++++++++++++++++++
 .../viewer/guice/GuiceProxyTargetLocator.java   | 162 +++++++++++++++++++
 4 files changed, 461 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/5625c6c4/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index 401a4b5..a04290e 100644
--- 
a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -46,7 +46,6 @@ import org.apache.wicket.SharedResources;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
 import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
 import org.apache.wicket.core.request.mapper.MountedMapper;
-import org.apache.wicket.guice.GuiceComponentInjector;
 import org.apache.wicket.markup.head.IHeaderResponse;
 import 
org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse;
 import org.apache.wicket.markup.html.IHeaderContributor;
@@ -100,6 +99,7 @@ import 
org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.pages.accmngt.AccountConfirmationMap;
 import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
+import org.apache.isis.viewer.wicket.viewer.guice.GuiceComponentInjector;
 import 
org.apache.isis.viewer.wicket.viewer.integration.isis.DeploymentTypeWicketAbstract;
 import org.apache.isis.viewer.wicket.viewer.integration.isis.WicketServer;
 import 
org.apache.isis.viewer.wicket.viewer.integration.isis.WicketServerPrototype;
@@ -689,8 +689,6 @@ public class IsisWicketApplication
 
 
     protected void initWicketComponentInjection(final Injector injector) {
-        // if serializable, then brings in dependency on cglib, and in turn 
asm.
-        // This would block us from migrating to DN 4.0.x
         getComponentInstantiationListeners().add(new 
GuiceComponentInjector(this, injector, false));
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/5625c6c4/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceComponentInjector.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceComponentInjector.java
 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceComponentInjector.java
new file mode 100644
index 0000000..b80ba1d
--- /dev/null
+++ 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceComponentInjector.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.viewer.guice;
+
+import com.google.inject.Guice;
+import com.google.inject.ImplementedBy;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Stage;
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.IBehaviorInstantiationListener;
+import org.apache.wicket.Session;
+import org.apache.wicket.application.IComponentInstantiationListener;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.guice.GuiceInjectorHolder;
+import org.apache.wicket.injection.IFieldValueFactory;
+import org.apache.wicket.model.Model;
+
+/**
+ * Injects field members of components and behaviors using Guice.
+ * <p>
+ * Add this to your application in its {@link Application#init()} method like 
so:
+ * 
+ * <pre>
+ * getComponentInstantiationListeners().add(new GuiceComponentInjector(this));
+ * </pre>
+ * 
+ * <p>
+ * There are different constructors for this object depending on how you want 
to wire things. See
+ * the javadoc for the constructors for more information.
+ * </p>
+ * <p>
+ * Only Wicket {@link Component}s and {@link Behavior}s are automatically 
injected, other classes
+ * such as {@link Session}, {@link Model}, and any other POJO can be injected 
by calling
+ * <code>Injector.get().inject(this)</code> in their constructor.
+ * </p>
+ * 
+ * @author Alastair Maw
+ */
+public class GuiceComponentInjector extends 
org.apache.wicket.injection.Injector
+       implements
+               IComponentInstantiationListener,
+               IBehaviorInstantiationListener
+{
+       private final IFieldValueFactory fieldValueFactory;
+
+       /**
+        * Creates a new Wicket GuiceComponentInjector instance.
+        * <p>
+        * Internally this will create a new Guice {@link Injector} instance, 
with no {@link Module}
+        * instances. This is only useful if your beans have appropriate {@link 
ImplementedBy}
+        * annotations on them so that they can be automatically picked up with 
no extra configuration
+        * code.
+        * 
+        * @param app
+        */
+       public GuiceComponentInjector(final Application app)
+       {
+               this(app, new Module[0]);
+       }
+
+       /**
+        * Creates a new Wicket GuiceComponentInjector instance, using the 
supplied Guice {@link Module}
+        * instances to create a new Guice {@link Injector} instance internally.
+        * 
+        * @param app
+        * @param modules
+        */
+       public GuiceComponentInjector(final Application app, final Module... 
modules)
+       {
+               this(app, Guice.createInjector(app.usesDeploymentConfig() ? 
Stage.PRODUCTION
+                       : Stage.DEVELOPMENT, modules), true);
+       }
+
+       /**
+        * Constructor
+        * 
+        * @param app
+        * @param injector
+        */
+       public GuiceComponentInjector(final Application app, final Injector 
injector)
+       {
+               this(app, injector, true);
+       }
+
+       /**
+        * Creates a new Wicket GuiceComponentInjector instance, using the 
provided Guice
+        * {@link Injector} instance.
+        * 
+        * @param app
+        * @param injector
+        * @param wrapInProxies
+        *            whether or not wicket should wrap dependencies with 
specialized proxies that can
+        *            be safely serialized. in most cases this should be set to 
true.
+        */
+       public GuiceComponentInjector(final Application app, final Injector 
injector,
+               final boolean wrapInProxies)
+       {
+               app.setMetaData(GuiceInjectorHolder.INJECTOR_KEY, new 
GuiceInjectorHolder(injector));
+               fieldValueFactory = new GuiceFieldValueFactory(wrapInProxies);
+               app.getBehaviorInstantiationListeners().add(this);
+               bind(app);
+       }
+
+       @Override
+       public void inject(final Object object)
+       {
+               inject(object, fieldValueFactory);
+       }
+
+       @Override
+       public void onInstantiation(final Component component)
+       {
+               inject(component);
+       }
+
+       @Override
+       public void onInstantiation(Behavior behavior)
+       {
+               inject(behavior);
+       }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5625c6c4/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceFieldValueFactory.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceFieldValueFactory.java
 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceFieldValueFactory.java
new file mode 100644
index 0000000..70d3568
--- /dev/null
+++ 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceFieldValueFactory.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.viewer.guice;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.inject.Qualifier;
+
+import org.apache.wicket.injection.IFieldValueFactory;
+import org.apache.wicket.proxy.LazyInitProxyFactory;
+
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Inject;
+import org.apache.wicket.util.lang.Generics;
+
+/**
+ *
+ */
+public class GuiceFieldValueFactory implements IFieldValueFactory
+{
+       private final ConcurrentMap<GuiceProxyTargetLocator, Object> cache = 
Generics.newConcurrentHashMap();
+       private static final Object NULL_SENTINEL = new Object();
+
+       private final boolean wrapInProxies;
+
+       /**
+        * Construct.
+        *
+        * @param wrapInProxies
+        */
+       GuiceFieldValueFactory(final boolean wrapInProxies)
+       {
+               this.wrapInProxies = wrapInProxies;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public Object getFieldValue(final Field field, final Object fieldOwner)
+       {
+               Object target = null;
+
+               if (supportsField(field))
+               {
+                       Inject injectAnnotation = 
field.getAnnotation(Inject.class);
+                       javax.inject.Inject javaxInjectAnnotation = 
field.getAnnotation(javax.inject.Inject.class);
+                       if (!Modifier.isStatic(field.getModifiers()) && 
(injectAnnotation != null || javaxInjectAnnotation != null))
+                       {
+                               try
+                               {
+                                       boolean optional = injectAnnotation != 
null && injectAnnotation.optional();
+                                       Annotation bindingAnnotation = 
findBindingAnnotation(field.getAnnotations());
+                                       final GuiceProxyTargetLocator locator = 
new GuiceProxyTargetLocator(field, bindingAnnotation, optional);
+
+                                       Object cachedValue = cache.get(locator);
+                                       if (cachedValue != null)
+                                       {
+                                               return cachedValue == 
NULL_SENTINEL ? null : cachedValue;
+                                       }
+
+                                       target = locator.locateProxyTarget();
+                                       if (target == null)
+                                       {
+                                               // Optional without a binding, 
return null
+                                       }
+                                       else
+                                       {
+                                               if (wrapInProxies)
+                                               {
+                                                       target = 
LazyInitProxyFactory.createProxy(field.getType(), locator);
+                                               }
+                                       }
+
+                                       if (locator.isSingletonScope())
+                                       {
+                                               Object tmpTarget = 
cache.putIfAbsent(locator, target == null ? NULL_SENTINEL : target);
+                                               if (tmpTarget != null)
+                                               {
+                                                       target = tmpTarget;
+                                               }
+                                       }
+
+                                       if (!field.isAccessible())
+                                       {
+                                               field.setAccessible(true);
+                                       }
+                               }
+                               catch (MoreThanOneBindingException e)
+                               {
+                                       throw new RuntimeException(
+                                                       "Can't have more than 
one BindingAnnotation on field " + field.getName() +
+                                                                       " of 
class " + fieldOwner.getClass().getName());
+                               }
+                       }
+               }
+
+               return target == NULL_SENTINEL ? null : target;
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       @Override
+       public boolean supportsField(final Field field)
+       {
+               return field.isAnnotationPresent(Inject.class) || 
field.isAnnotationPresent(javax.inject.Inject.class);
+       }
+
+       /**
+        *
+        * @param annotations
+        * @return Annotation
+        * @throws MoreThanOneBindingException
+        */
+       private Annotation findBindingAnnotation(final Annotation[] annotations)
+                       throws MoreThanOneBindingException
+       {
+               Annotation bindingAnnotation = null;
+
+               // Work out if we have a BindingAnnotation on this parameter.
+               for (Annotation annotation : annotations)
+               {
+                       if 
(annotation.annotationType().getAnnotation(BindingAnnotation.class) != null ||
+                                       
annotation.annotationType().getAnnotation(Qualifier.class) != null)
+                       {
+                               if (bindingAnnotation != null)
+                               {
+                                       throw new MoreThanOneBindingException();
+                               }
+                               bindingAnnotation = annotation;
+                       }
+               }
+               return bindingAnnotation;
+       }
+
+       /**
+        *
+        */
+       public static class MoreThanOneBindingException extends Exception
+       {
+               private static final long serialVersionUID = 1L;
+       }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/5625c6c4/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceProxyTargetLocator.java
----------------------------------------------------------------------
diff --git 
a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceProxyTargetLocator.java
 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceProxyTargetLocator.java
new file mode 100644
index 0000000..dcf11e7
--- /dev/null
+++ 
b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/guice/GuiceProxyTargetLocator.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.isis.viewer.wicket.viewer.guice;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+
+import com.google.inject.ConfigurationException;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.guice.GuiceInjectorHolder;
+import org.apache.wicket.proxy.IProxyTargetLocator;
+import org.apache.wicket.core.util.lang.WicketObjects;
+import org.apache.wicket.util.lang.Objects;
+
+class GuiceProxyTargetLocator implements IProxyTargetLocator
+{
+       private static final long serialVersionUID = 1L;
+
+       private final Annotation bindingAnnotation;
+
+       private final boolean optional;
+
+       private final String className;
+
+       private final String fieldName;
+
+       private Boolean isSingletonCache = null;
+
+       public GuiceProxyTargetLocator(final Field field, final Annotation 
bindingAnnotation,
+                                                                  final 
boolean optional)
+       {
+               this.bindingAnnotation = bindingAnnotation;
+               this.optional = optional;
+               className = field.getDeclaringClass().getName();
+               fieldName = field.getName();
+       }
+
+       @Override
+       public Object locateProxyTarget()
+       {
+               Injector injector = getInjector();
+
+               final Key<?> key = newGuiceKey();
+
+               // if the Inject annotation is marked optional and no binding 
is found
+               // then skip this injection (WICKET-2241)
+               if (optional)
+               {
+                       // Guice 2.0 throws a ConfigurationException if no 
binding is find while 1.0 simply
+                       // returns null.
+                       try
+                       {
+                               if (injector.getBinding(key) == null)
+                               {
+                                       return null;
+                               }
+                       }
+                       catch (RuntimeException e)
+                       {
+                               return null;
+                       }
+               }
+
+               return injector.getInstance(key);
+       }
+
+       private Key<?> newGuiceKey()
+       {
+               final Type type;
+               try
+               {
+                       Class<?> clazz = WicketObjects.resolveClass(className);
+                       final Field field = clazz.getDeclaredField(fieldName);
+                       type = field.getGenericType();
+               }
+               catch (Exception e)
+               {
+                       throw new WicketRuntimeException("Error accessing 
member: " + fieldName +
+                               " of class: " + className, e);
+               }
+
+               // using TypeLiteral to retrieve the key gives us automatic 
support for
+               // Providers and other injectable TypeLiterals
+               if (bindingAnnotation == null)
+               {
+                       return Key.get(TypeLiteral.get(type));
+               }
+               else
+               {
+                       return Key.get(TypeLiteral.get(type), 
bindingAnnotation);
+               }
+       }
+
+       public boolean isSingletonScope()
+       {
+               if (isSingletonCache == null)
+               {
+                       try
+                       {
+                               isSingletonCache = 
Scopes.isSingleton(getInjector().getBinding(newGuiceKey()));
+                       }
+                       catch (ConfigurationException ex)
+                       {
+                               // No binding, if optional can pretend this is 
null singleton
+                               if (optional)
+                                       isSingletonCache = true;
+                               else
+                                       throw ex;
+                       }
+               }
+               return isSingletonCache;
+       }
+
+       private Injector getInjector()
+       {
+               final GuiceInjectorHolder holder = 
Application.get().getMetaData(
+                       GuiceInjectorHolder.INJECTOR_KEY);
+
+               return holder.getInjector();
+       }
+
+       @Override
+       public boolean equals(Object o)
+       {
+               if (this == o)
+                       return true;
+               if (!(o instanceof GuiceProxyTargetLocator))
+                       return false;
+               GuiceProxyTargetLocator that = (GuiceProxyTargetLocator) o;
+               return Objects.equal(optional, that.optional) &&
+                               Objects.equal(bindingAnnotation, 
that.bindingAnnotation) &&
+                               Objects.equal(className, that.className) &&
+                               Objects.equal(fieldName, that.fieldName);
+       }
+
+       @Override
+       public int hashCode()
+       {
+               return Objects.hashCode(bindingAnnotation, optional, className, 
fieldName);
+       }
+
+}

Reply via email to