001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.proxy.interceptor;
019
020 import EDU.oswego.cs.dl.util.concurrent.Executor;
021 import org.apache.commons.proxy.Invocation;
022 import org.apache.commons.proxy.Interceptor;
023
024 /**
025 * A method interceptor that uses an {@link Executor} to execute the method invocation.
026 * <p/>
027 * <b>Note</b>: Only <em>void</em> methods can be intercepted using this class! Any attempts to intercept non-void
028 * methods will result in an {@link IllegalArgumentException}. If the proxy interfaces include non-void methods, try
029 * using a {@link FilteredInterceptor} along with a
030 * {@link org.apache.commons.proxy.interceptor.filter.ReturnTypeFilter} to wrap an instance of this class.
031 *
032 * <p>
033 * <b>Dependencies</b>:
034 * <ul>
035 * <li>Concurrent API version 1.3.4 or greater</li>
036 * </ul>
037 * </p>
038 * @author James Carman
039 * @since 1.0
040 */
041 public class ExecutorInterceptor implements Interceptor
042 {
043 private final Executor executor;
044
045 public ExecutorInterceptor( Executor executor )
046 {
047 this.executor = executor;
048 }
049
050 public Object intercept( final Invocation invocation ) throws Throwable
051 {
052 if( Void.TYPE.equals( invocation.getMethod().getReturnType() ) )
053 {
054 // Special case for finalize() method (should not be run in a different thread)...
055 if( !( invocation.getMethod().getName().equals( "finalize" ) &&
056 invocation.getMethod().getParameterTypes().length == 0 ) )
057 {
058 executor.execute( new Runnable()
059 {
060 public void run()
061 {
062 try
063 {
064 invocation.proceed();
065 }
066 catch( Throwable t )
067 {
068 // What to do here? I can't convey the failure back to the caller.
069 }
070 }
071 } );
072 return null;
073 }
074 else
075 {
076 return invocation.proceed();
077 }
078 }
079 else
080 {
081 throw new IllegalArgumentException( "Only void methods can be executed in a different thread." );
082 }
083 }
084 }