Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.wicket.proxy;
 
 import java.util.List;
 
A factory class that creates lazy init proxies given a type and a IProxyTargetLocator used to retrieve the object the proxy will represent.

A lazy init proxy waits until the first method invocation before it uses the IProxyTargetLocator to retrieve the object to which the method invocation will be forwarded.

This factory creates two kinds of proxies: A standard dynamic proxy when the specified type is an interface, and a CGLib proxy when the specified type is a concrete class.

The general use case for such a proxy is to represent a dependency that should not be serialized with a wicket page or org.apache.wicket.model.IModel. The solution is to serialize the proxy and the IProxyTargetLocator instead of the dependency, and be able to look up the target object again when the proxy is deserialized and accessed. A good strategy for achieving this is to have a static lookup in the IProxyTargetLocator, this keeps its size small and makes it safe to serialize.

Example:

 class UserServiceLocator implements IProxyTargetLocator
 {
  public static final IProxyTargetLocator INSTANCE = new UserServiceLocator();
 
  Object locateProxyObject()
  {
   MyApplication app = (MyApplication)Application.get();
   return app.getUserService();
  }
 }
 
 class UserDetachableModel extends LoadableModel
 {
  private UserService svc;
 
  private long userId;
 
  public UserDetachableModel(long userId, UserService svc)
  {
   this.userId = userId;
   this.svc = svc;
  }
 
  public Object load()
  {
   return svc.loadUser(userId);
  }
 }
 
 UserService service = LazyInitProxyFactory.createProxy(UserService.class,
  UserServiceLocator.INSTANCE);
 
 UserDetachableModel model = new UserDetachableModel(10, service);
 
 
The detachable model in the example above follows to good citizen pattern and is easy to unit test. These are the advantages gained through the use of the lazy init proxies.

Author(s):
Igor Vaynberg (ivaynberg)
{
Primitive java types and their object wrappers
	@SuppressWarnings({ "unchecked""rawtypes" })
	private static final List PRIMITIVES = Arrays.asList(String.classbyte.classByte.class,
		short.classShort.classint.classInteger.classlong.classLong.classfloat.class,
		Float.classdouble.classDouble.classchar.classCharacter.classboolean.class,
		Boolean.class);

Create a lazy init proxy for the specified type. The target object will be located using the provided locator upon first method invocation.

Parameters:
type type that proxy will represent
locator object locator that will locate the object the proxy represents
Returns:
lazily initializable proxy
	public static Object createProxy(final Class<?> typefinal IProxyTargetLocator locator)
	{
		if (.contains(type) || Enum.class.isAssignableFrom(type))
		{
			// We special-case primitives as sometimes people use these as
			// SpringBeans (WICKET-603, WICKET-906). Go figure.
			return locator.locateProxyTarget();
		}
		else if (type.isInterface())
		{
			JdkHandler handler = new JdkHandler(typelocator);
			try
			{
				ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
				if (Application.exists())
				{
					IClassResolver classResolver = Application.get()
					if (classResolver instanceof AbstractClassResolver)
					{
						classLoader = ((AbstractClassResolverclassResolver).getClassLoader();
					}
				}
				return Proxy.newProxyInstance(classLoader,
					new Class[] { typeSerializable.classILazyInitProxy.class,
							IWriteReplace.class }, handler);
			}
			{
				/*
				 * STW: In some clustering environments it appears the context classloader fails to
				 * load the proxied interface (currently seen in BEA WLS 9.x clusters). If this
				 * happens, we can try and fall back to the classloader (current) that actually
				 * loaded this class.
				 */
					new Class[] { typeSerializable.classILazyInitProxy.class,
							IWriteReplace.class }, handler);
			}
		}
		else
		{
			CGLibInterceptor handler = new CGLibInterceptor(typelocator);
			Enhancer e = new Enhancer();
			e.setInterfaces(new Class[] { Serializable.classILazyInitProxy.class,
					IWriteReplace.class });
			e.setCallback(handler);
			{
				public String getClassName(final String prefixfinal String source,
					final Object keyfinal Predicate names)
				{
					return super.getClassName("WICKET_" + prefixsourcekeynames);
				}
			});
			return e.create();
		}
	}

This interface is used to make the proxy forward writeReplace() call to the handler instead of invoking it on itself. This allows us to serialize the replacement objet instead of the proxy itself in case the proxy subclass is deserialized on a VM that does not have it created.

Author(s):
Igor Vaynberg (ivaynberg)
See also:
LazyInitProxyFactory.ProxyReplacement
	public static interface IWriteReplace
	{
write replace method as defined by Serializable

Returns:
object that will replace this object in serialized state
Throws:
java.io.ObjectStreamException
	}

Object that replaces the proxy when it is serialized. Upon deserialization this object will create a new proxy with the same locator.

Author(s):
Igor Vaynberg (ivaynberg)
	static class ProxyReplacement implements IClusterable
	{
		private static final long serialVersionUID = 1L;
		private final IProxyTargetLocator locator;
		private final String type;

Constructor

Parameters:
type
locator
		public ProxyReplacement(final String typefinal IProxyTargetLocator locator)
		{
			this. = type;
			this. = locator;
		}
		{
			Class<?> clazz = WicketObjects.resolveClass();
			if (clazz == null)
			{
					"Could not resolve type [" +  +
						"] with the currently configured org.apache.wicket.application.IClassResolver");
				throw new WicketRuntimeException(cause);
			}
			return LazyInitProxyFactory.createProxy(clazz);
		}
	}

Method interceptor for proxies representing concrete object not backed by an interface. These proxies are representing by cglib proxies.

Author(s):
Igor Vaynberg (ivaynberg)
	private static class CGLibInterceptor
		implements
	{
		private static final long serialVersionUID = 1L;
		private final IProxyTargetLocator locator;
		private final String typeName;
		private transient Object target;

Constructor

Parameters:
type class of the object this proxy was created for
locator object locator used to locate the object this proxy represents
		public CGLibInterceptor(final Class<?> typefinal IProxyTargetLocator locator)
		{
			super();
			 = type.getName();
			this. = locator;
		}

		public Object intercept(final Object objectfinal Method methodfinal Object[] args,
			final MethodProxy proxythrows Throwable
		{
			if (isFinalizeMethod(method))
			{
				// swallow finalize call
				return null;
			}
			else if (isEqualsMethod(method))
			{
				return (equals(args[0])) ? . : .;
			}
			else if (isHashCodeMethod(method))
			{
				return hashCode();
			}
			else if (isToStringMethod(method))
			{
				return toString();
			}
			else if (isWriteReplaceMethod(method))
			{
				return writeReplace();
			}
			else if (method.getDeclaringClass().equals(ILazyInitProxy.class))
			{
			}
			if ( == null)
			{
			}
			return proxy.invoke(args);
		}

		{
			return ;
		}

		{
		}
	}

Invocation handler for proxies representing interface based object. For interface backed objects dynamic jdk proxies are used.

Author(s):
Igor Vaynberg (ivaynberg)
	private static class JdkHandler
		implements
	{
		private static final long serialVersionUID = 1L;
		private final IProxyTargetLocator locator;
		private final String typeName;
		private transient Object target;

Constructor

Parameters:
type class of object this handler will represent
locator object locator used to locate the object this proxy represents
		public JdkHandler(final Class<?> typefinal IProxyTargetLocator locator)
		{
			super();
			this. = locator;
			 = type.getName();
		}

		public Object invoke(final Object proxyfinal Method methodfinal Object[] args)
			throws Throwable
		{
			if (isFinalizeMethod(method))
			{
				// swallow finalize call
				return null;
			}
			else if (isEqualsMethod(method))
			{
				return (equals(args[0])) ? . : .;
			}
			else if (isHashCodeMethod(method))
			{
				return hashCode();
			}
			else if (isToStringMethod(method))
			{
				return toString();
			}
			else if (method.getDeclaringClass().equals(ILazyInitProxy.class))
			{
			}
			else if (isWriteReplaceMethod(method))
			{
				return writeReplace();
			}
			if ( == null)
			{
			}
			try
			{
				method.setAccessible(true);
				return method.invoke(args);
			}
			{
			}
		}

		{
			return ;
		}

		{
		}
	}

Checks if the method is derived from Object.equals()

Parameters:
method method being tested
Returns:
true if the method is derived from Object.equals(), false otherwise
	protected static boolean isEqualsMethod(final Method method)
	{
		return (method.getReturnType() == boolean.class) &&
			(method.getParameterTypes().length == 1) &&
			(method.getParameterTypes()[0] == Object.class) && method.getName().equals("equals");
	}

Checks if the method is derived from Object.hashCode()

Parameters:
method method being tested
Returns:
true if the method is defined from Object.hashCode(), false otherwise
	protected static boolean isHashCodeMethod(final Method method)
	{
		return (method.getReturnType() == int.class) && (method.getParameterTypes().length == 0) &&
			method.getName().equals("hashCode");
	}

Checks if the method is derived from Object.toString()

Parameters:
method method being tested
Returns:
true if the method is defined from Object.toString(), false otherwise
	protected static boolean isToStringMethod(final Method method)
	{
		return (method.getReturnType() == String.class) &&
			(method.getParameterTypes().length == 0) && method.getName().equals("toString");
	}

Checks if the method is derived from Object.finalize()

Parameters:
method method being tested
Returns:
true if the method is defined from Object.finalize(), false otherwise
	protected static boolean isFinalizeMethod(final Method method)
	{
		return (method.getReturnType() == void.class) && (method.getParameterTypes().length == 0) &&
			method.getName().equals("finalize");
	}

Checks if the method is the writeReplace method

Parameters:
method method being tested
Returns:
true if the method is the writeReplace method, false otherwise
	protected static boolean isWriteReplaceMethod(final Method method)
	{
		return (method.getReturnType() == Object.class) &&
			(method.getParameterTypes().length == 0) && method.getName().equals("writeReplace");
	}
New to GrepCode? Check out our FAQ X