001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.remoting.support;
018:
019: import java.lang.reflect.InvocationTargetException;
020:
021: /**
022: * Abstract base class for remote service exporters that are based
023: * on deserialization of {@link RemoteInvocation} objects.
024: *
025: * <p>Provides a "remoteInvocationExecutor" property, with a
026: * {@link DefaultRemoteInvocationExecutor} as default strategy.
027: *
028: * @author Juergen Hoeller
029: * @since 1.1
030: * @see RemoteInvocationExecutor
031: * @see DefaultRemoteInvocationExecutor
032: */
033: public abstract class RemoteInvocationBasedExporter extends
034: RemoteExporter {
035:
036: private RemoteInvocationExecutor remoteInvocationExecutor = new DefaultRemoteInvocationExecutor();
037:
038: /**
039: * Set the RemoteInvocationExecutor to use for this exporter.
040: * Default is a DefaultRemoteInvocationExecutor.
041: * <p>A custom invocation executor can extract further context information
042: * from the invocation, for example user credentials.
043: */
044: public void setRemoteInvocationExecutor(
045: RemoteInvocationExecutor remoteInvocationExecutor) {
046: this .remoteInvocationExecutor = remoteInvocationExecutor;
047: }
048:
049: /**
050: * Return the RemoteInvocationExecutor used by this exporter.
051: */
052: public RemoteInvocationExecutor getRemoteInvocationExecutor() {
053: return this .remoteInvocationExecutor;
054: }
055:
056: /**
057: * Apply the given remote invocation to the given target object.
058: * The default implementation delegates to the RemoteInvocationExecutor.
059: * <p>Can be overridden in subclasses for custom invocation behavior,
060: * possibly for applying additional invocation parameters from a
061: * custom RemoteInvocation subclass. Note that it is preferable to use
062: * a custom RemoteInvocationExecutor which is a reusable strategy.
063: * @param invocation the remote invocation
064: * @param targetObject the target object to apply the invocation to
065: * @return the invocation result
066: * @throws NoSuchMethodException if the method name could not be resolved
067: * @throws IllegalAccessException if the method could not be accessed
068: * @throws InvocationTargetException if the method invocation resulted in an exception
069: * @see RemoteInvocationExecutor#invoke
070: */
071: protected Object invoke(RemoteInvocation invocation,
072: Object targetObject) throws NoSuchMethodException,
073: IllegalAccessException, InvocationTargetException {
074:
075: if (logger.isTraceEnabled()) {
076: logger.trace("Executing " + invocation);
077: }
078: try {
079: return getRemoteInvocationExecutor().invoke(invocation,
080: targetObject);
081: } catch (NoSuchMethodException ex) {
082: if (logger.isDebugEnabled()) {
083: logger.warn("Could not find target method for "
084: + invocation, ex);
085: }
086: throw ex;
087: } catch (IllegalAccessException ex) {
088: if (logger.isDebugEnabled()) {
089: logger.warn("Could not access target method for "
090: + invocation, ex);
091: }
092: throw ex;
093: } catch (InvocationTargetException ex) {
094: if (logger.isDebugEnabled()) {
095: logger.debug("Target method failed for " + invocation,
096: ex.getTargetException());
097: }
098: throw ex;
099: }
100: }
101:
102: /**
103: * Apply the given remote invocation to the given target object, wrapping
104: * the invocation result in a serializable RemoteInvocationResult object.
105: * The default implementation creates a plain RemoteInvocationResult.
106: * <p>Can be overridden in subclasses for custom invocation behavior,
107: * for example to return additional context information. Note that this
108: * is not covered by the RemoteInvocationExecutor strategy!
109: * @param invocation the remote invocation
110: * @param targetObject the target object to apply the invocation to
111: * @return the invocation result
112: * @see #invoke
113: */
114: protected RemoteInvocationResult invokeAndCreateResult(
115: RemoteInvocation invocation, Object targetObject) {
116: try {
117: Object value = invoke(invocation, targetObject);
118: return new RemoteInvocationResult(value);
119: } catch (Throwable ex) {
120: return new RemoteInvocationResult(ex);
121: }
122: }
123:
124: }
|