LocalRedirector.java
/*
** Module : LocalRedirector.java
** Abstract : used by a proxy to call methods on a local instance
**
** Copyright (c) 2011-2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- -----------------------Description------------------------
** 001 GES 20111012 First version.
** 002 GES 20111018 This is now the redirector for instance methods. Static
** support was moved to LocalStaticRedirector. Added support
** for a state synchronizer.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.net;
import java.lang.reflect.*;
import java.io.*;
import java.util.*;
import com.goldencode.p2j.util.*;
/**
* Provides the proxy handler for a local object which redirects interface
* methods to target instance methods. The purpose is to allow code written
* normally for remote access to be linked together "locally" (within the same
* JVM).
* <p>
* Optionally, a {@link LocalStateSync} instance can be provided. If provided,
* it will be used to maintain the {@link StateSynchronizer} semantics which
* is missing in local redirector environments which have no {@link Session}
* object which would otherwise service that requirement.
*/
public class LocalRedirector
extends InvocationStub
{
/** Target methods. */
private Set<Method> methods = null;
/** Instance on which to invoke methods. <code>null</code> for statics. */
private Object instance = null;
/** Utility for local state synchronization. */
private LocalStateSync state = null;
/**
* Creates a unique instance of an object that can handle invocations
* of any proxied interface method by redirecting the method calls to
* instance methods in a local class that match the interface method
* signatures. Any return value and/or exceptions thrown will be handled
* as needed.
* <p>
* No state synchronization will be performed.
*
* @param instance
* The instance upon which to target the method invocations. Use
* <code>null</code> if the methods are static.
* @param methods
* The set of target interface methods. Must not be
* <code>null</code>.
*/
public LocalRedirector(Object instance, Set<Method> methods)
{
this.instance = instance;
this.methods = methods;
}
/**
* Creates a unique instance of an object that can handle invocations
* of any proxied interface method by redirecting the method calls to
* instance methods in a local class that match the interface method
* signatures. Any return value and/or exceptions thrown will be handled
* as needed.
*
* @param instance
* The instance upon which to target the method invocations. Use
* <code>null</code> if the methods are static.
* @param methods
* The set of target interface methods. Must not be
* <code>null</code>.
* @param state
* The state synchronizer on which to get and apply changes
* before invoking the method call.
*/
public LocalRedirector(Object instance,
Set<Method> methods,
LocalStateSync state)
{
this(instance, methods);
this.state = state;
}
/**
* This method acts as an interceptor which is called every time a
* method of the proxy object is invoked.
* <p>
* If a state synchronizer instance has been provided, the call to
* {@link LocalStateSync#sync} will be implemented before the proxied
* method is invoked.
*
* @param proxy
* Proxy object upon which the intercepted method is invoked.
* @param method
* Method to be invoked through reflection.
* @param args
* Arguments, if any, to <code>method</code>.
*
* @return Result of the mapped call.
*
* @throws Throwable
* if an exception/error occurs upon the invocation target,
* or if any problem occurs during pre- or post-processing.
*/
public Object invokeCore(Object proxy, Method method, Object[] args)
throws Throwable
{
if (!methods.contains(method))
{
throw new SilentUnwindException();
}
if (state != null)
{
state.sync();
}
return method.invoke(instance, args);
}
}