Derek Hulley 0c10d61a48 Merged V2.0 to HEAD
svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V2.0@5141 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V2.0@51352 .
      - FLOSS
      - Some files will need a follow-up
         -root/projects/repository/source/java/org/alfresco/repo/avm/wf/AVMRemoveWFStoreHandler.java (not yet on HEAD: 5094)
         -root/projects/repository/source/java/org/alfresco/filesys/server/state/FileStateLockManager.java (not yet on HEAD: 5093)
         -onContentUpdateRecord (not on HEAD)


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5167 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2007-02-16 06:44:46 +00:00

222 lines
7.2 KiB
Java

/*
* Copyright (C) 2005 Alfresco, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.policy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.alfresco.util.ParameterCheck;
/**
* Java based Behaviour.
*
* A behavior acts like a delegate (a method pointer). The pointer is
* represented by an instance object and method name.
*
* @author David Caruana
*
*/
public class JavaBehaviour extends BaseBehaviour
{
// The object instance holding the method
Object instance;
// The method name
String method;
/**
* Construct.
*
* @param instance the object instance holding the method
* @param method the method name
*/
public JavaBehaviour(Object instance, String method)
{
this(instance, method, NotificationFrequency.EVERY_EVENT);
}
/**
* Construct.
*
* @param instance the object instance holding the method
* @param method the method name
*/
public JavaBehaviour(Object instance, String method, NotificationFrequency frequency)
{
super(frequency);
ParameterCheck.mandatory("Instance", instance);
ParameterCheck.mandatory("Method", method);
this.method = method;
this.instance = instance;
}
@Override
public String toString()
{
return "Java method[class=" + instance.getClass().getName() + ", method=" + method + "]";
}
@SuppressWarnings("unchecked")
public synchronized <T> T getInterface(Class<T> policy)
{
ParameterCheck.mandatory("Policy class", policy);
Object proxy = proxies.get(policy);
if (proxy == null)
{
InvocationHandler handler = getInvocationHandler(instance, method, policy);
proxy = Proxy.newProxyInstance(policy.getClassLoader(), new Class[]{policy}, handler);
proxies.put(policy, proxy);
}
return (T)proxy;
}
/**
* Gets the Invocation Handler.
*
* @param <T> the policy interface class
* @param instance the object instance
* @param method the method name
* @param policyIF the policy interface class
* @return the invocation handler
*/
<T> InvocationHandler getInvocationHandler(Object instance, String method, Class<T> policyIF)
{
Method[] policyIFMethods = policyIF.getMethods();
if (policyIFMethods.length != 1)
{
throw new PolicyException("Policy interface " + policyIF.getCanonicalName() + " must have only one method");
}
try
{
Class instanceClass = instance.getClass();
Method delegateMethod = instanceClass.getMethod(method, (Class[])policyIFMethods[0].getParameterTypes());
return new JavaMethodInvocationHandler(this, delegateMethod);
}
catch (NoSuchMethodException e)
{
throw new PolicyException("Method " + method + " not found or accessible on " + instance.getClass(), e);
}
}
/**
* Java Method Invocation Handler
*
* @author David Caruana
*/
private static class JavaMethodInvocationHandler implements InvocationHandler
{
private JavaBehaviour behaviour;
private Method delegateMethod;
/**
* Constuct.
*
* @param instance the object instance holding the method
* @param delegateMethod the method to invoke
*/
private JavaMethodInvocationHandler(JavaBehaviour behaviour, Method delegateMethod)
{
this.behaviour = behaviour;
this.delegateMethod = delegateMethod;
}
/* (non-Javadoc)
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
// Handle Object level methods
if (method.getName().equals("toString"))
{
return toString();
}
else if (method.getName().equals("hashCode"))
{
return hashCode();
}
else if (method.getName().equals("equals"))
{
if (Proxy.isProxyClass(args[0].getClass()))
{
return equals(Proxy.getInvocationHandler(args[0]));
}
return false;
}
// Delegate to designated method pointer
if (behaviour.isEnabled())
{
try
{
behaviour.disable();
return delegateMethod.invoke(behaviour.instance, args);
}
catch (InvocationTargetException e)
{
throw e.getTargetException();
}
finally
{
behaviour.enable();
}
}
return null;
}
@Override
public boolean equals(Object obj)
{
if (obj == this)
{
return true;
}
else if (obj == null || !(obj instanceof JavaMethodInvocationHandler))
{
return false;
}
JavaMethodInvocationHandler other = (JavaMethodInvocationHandler)obj;
return behaviour.instance.equals(other.behaviour.instance) && delegateMethod.equals(other.delegateMethod);
}
@Override
public int hashCode()
{
return 37 * behaviour.instance.hashCode() + delegateMethod.hashCode();
}
@Override
public String toString()
{
return "JavaBehaviour[instance=" + behaviour.instance.hashCode() + ", method=" + delegateMethod.toString() + "]";
}
}
}