You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2016/10/28 07:33:06 UTC
[03/21] isis git commit: ISIS-1223 Upgrade Wicket to 7.x
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 <mg...@apache.org>
Authored: Mon Nov 2 21:35:42 2015 +0100
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
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);
+ }
+
+}