Coverage report

| %line | %branch
--- | --- | ---
tsukuba_bunko.util.GenericListener |
0% |
0% |

1 |  |
     /*
2 |  |
      * Common Library for TBAS Softwares
3 |  |
      * Language: Java
4 |  |
      *
5 |  |
      * All Rights Reserved.
6 |  |
      * (c) Copyright 2002 by Tsukuba Bunko.
7 |  |
      *
8 |  |
      * $Id: GenericListener.java,v 1.1 2005/07/11 12:49:19 ppoi Exp $
9 |  |
      */
10 |  |
     package tsukuba_bunko.util;
11 |  |
12 |  |
     import	java.lang.reflect.Method;
13 |  |
     import	java.lang.reflect.InvocationHandler;
14 |  |
     import	java.lang.reflect.InvocationTargetException;
15 |  |
     import	java.lang.reflect.Proxy;
16 |  |
17 |  |
18 |  |
     /**
19 |  |
      * イベントソースとイベントハンドラを接続するための枠組みを提供します. この枠組みを利用するためには,
20 |  |
      * Dynamic Proxy Class API を VM がサポートしている必要があります.
21 |  |
      * @author	$Author: ppoi $
22 |  |
      */
23 |  |
     public class GenericListener	{
24 |  |
25 |  |
     	/**
26 |  |
     	 * <code>GenericListener</code> はインスタンスを生成できません。
27 |  |
     	 */
28 | 0 |
     	private GenericListener(){;}
29 |  |
30 |  |
31 |  |
     	/**
32 |  |
     	 * イベントソースとイベントハンドラを接続します。このメソッドで登録した場合、イベントハンドラはイベントソースと同じスレッドで実行されます。
33 |  |
     	 * @param	eventSource		イベントソース
34 |  |
     	 * @param	eventTarget		イベントハンドラ
35 |  |
     	 * @param	listenerClass	イベントソースに本来接続されるリスナクラス
36 |  |
     	 * @param	sourceMethod	イベントソースで呼び出されるメソッド名
37 |  |
     	 * @param	targetMethod	イベントハンドラで実際にイベントを処理するメソッド名
38 |  |
     	 * @return	イベントソースとイベントハンドラが接続された場合 <code>true</code>
39 |  |
     	 */
40 |  |
     	public static boolean connect( Object eventSource, Object eventTarget, Class listenerClass, String sourceMethod, String targetMethod )
41 |  |
     	{
42 | 0 |
     		return connect( eventSource, eventTarget, listenerClass, sourceMethod, targetMethod, false );
43 |  |
     	}
44 |  |
45 |  |
     	/**
46 |  |
     	 * イベントソースとイベントハンドラを接続します。
47 |  |
     	 * 新しいスレッドを起動してイベントハンドラを実行する場合、戻り値を返すことは出来ません。また、例外の発生は通知されません。
48 |  |
     	 * @param	eventSource		イベントソース
49 |  |
     	 * @param	eventTarget		イベントハンドラ
50 |  |
     	 * @param	listenerClass	イベントソースに本来接続されるリスナクラス
51 |  |
     	 * @param	sourceMethod	イベントソースで呼び出されるメソッド名
52 |  |
     	 * @param	targetMethod	イベントハンドラで実際にイベントを処理するメソッド名
53 |  |
     	 * @param	newThread	新しいスレッドを起動してイベントハンドラを実行する場合 <code>true</code>、それ以外の場合 <code>false</code>
54 |  |
     	 * @return	イベントソースとイベントハンドラが接続された場合 <code>true</code>
55 |  |
     	 */
56 |  |
     	public static boolean connect( Object eventSource, Object eventTarget, Class listenerClass, String sourceMethod, String targetMethod, class="keyword">boolean newThread )
57 |  |
     	{
58 |  |
     		try	{
59 |  |
     		//	"add" メソッドの取得.
60 | 0 |
     		Method	addMethod = eventSource.getClass().getMethod( ("add" + identifierOf(listenerClass)), new Class[]{listenerClass} );
61 | 0 |
     		if( addMethod == null )	{
62 |  |
     			//	エラー
63 | 0 |
     			return false;
64 |  |
     		}
65 |  |
66 |  |
     		//	リスナのインスタンスの取得.
67 | 0 |
     		Method	sourceMethodObject = getListenerMethod( listenerClass, sourceMethod );
68 | 0 |
     		Method	targetMethodObject = getTargetMethod( eventTarget.getClass(), targetMethod, sourceMethodObject.getParameterTypes() );
69 | 0 |
     		Object	listenerImple = Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class[]{listenerClass}, class="keyword">new InvocHandler(eventTarget, targetMethodObject, sourceMethodObject, class="keyword">newThread) );
70 |  |
71 | 0 |
     		addMethod.invoke( eventSource, new Object[]{listenerImple} );
72 |  |
     		}
73 | 0 |
     		catch( Exception e )
74 |  |
     		{
75 | 0 |
     			e.printStackTrace();
76 | 0 |
     			return false;
77 | 0 |
     		}
78 |  |
79 | 0 |
     		return true;
80 |  |
     	}
81 |  |
82 |  |
     	/**
83 |  |
     	 * 指定されたクラスの Identifier を取得します. ここでの Identidier はクラス宣言の際に
84 |  |
     	 *用いられるクラス名のことを指します.
85 |  |
     	 * @param	c	Identifier を取得するクラス
86 |  |
     	 * @return	Identifier
87 |  |
     	 */
88 |  |
     	private static String identifierOf( Class c )
89 |  |
     	{
90 | 0 |
     		String	className = c.getName();
91 | 0 |
     		return className.substring( className.lastIndexOf('.') + 1, className.length() );
92 |  |
     	}
93 |  |
94 |  |
     	/**
95 |  |
     	 * イベントソースで呼び出されるメソッドを取得します.
96 |  |
     	 * @param	listenerClass	リスナクラス
97 |  |
     	 * @param	methodName		メソッド名
98 |  |
     	 */
99 |  |
     	private static Method getListenerMethod( Class listenerClass, String methodName )
100 |  |
     		throws NoSuchMethodException
101 |  |
     	{
102 | 0 |
     		Method	methods[] = listenerClass.getMethods();
103 | 0 |
     		for( int i = methods.length - 1; i >= 0; --i )	{
104 | 0 |
     			if( methodName.equals(methods[i].getName()) )	{
105 | 0 |
     				return methods[i];
106 |  |
     			}
107 |  |
     		}
108 | 0 |
     		throw new NoSuchMethodException( "No such method \"" + methodName + "\" in \"" + listenerClass.getName() + "\"." );
109 |  |
     	}
110 |  |
111 |  |
     	/**
112 |  |
     	 * 指定されたクラスにおいて指定された名前で定義されたメソッドを取得します.
113 |  |
     	 * @param	c	メソッドが定義されているクラス
114 |  |
     	 * @param	methodName	メソッド名
115 |  |
     	 * @param	parameterTypes	仮引数の型リスト
116 |  |
     	 */
117 |  |
     	private static Method getTargetMethod( Class c, String methodName, Class[] parameterTypes )
118 |  |
     		throws NoSuchMethodException
119 |  |
     	{
120 | 0 |
     		Method	method = null;
121 |  |
     		try	{
122 | 0 |
     			method = c.getDeclaredMethod( methodName, parameterTypes );
123 |  |
     		}
124 | 0 |
     		catch( NoSuchMethodException nsme )	{
125 | 0 |
     			method = c.getDeclaredMethod( methodName, null );
126 | 0 |
     		}
127 |  |
128 |  |
     		try	{
129 | 0 |
     			method.setAccessible( true );
130 |  |
     		}
131 | 0 |
     		catch( SecurityException se )	{
132 |  |
     			//	ignore.
133 | 0 |
     		}
134 | 0 |
     		return method;
135 |  |
     	}
136 |  |
     }
137 |  |
138 |  |
139 |  |
     /**
140 |  |
      * <code>InvocationHandler</code> の実装です.
141 |  |
      */
142 |  |
     class InvocHandler	implements InvocationHandler	{
143 |  |
144 |  |
     	/**
145 |  |
     	 * 処理を実際に行うクラス
146 |  |
     	 */
147 |  |
     	private Object	_target =null;
148 |  |
149 |  |
     	/**
150 |  |
     	 * 処理を実際に行うメソッド
151 |  |
     	 */
152 |  |
     	private Method	_targetMethod = null;
153 |  |
154 |  |
     	/**
155 |  |
     	 * イベントソースによって呼び出されるメソッド
156 |  |
     	 */
157 |  |
     	private Method	_sourceMethod = null;
158 |  |
159 |  |
     	/**
160 |  |
     	 * 別スレッドを起動するかどうか
161 |  |
     	 */
162 |  |
     	private boolean	_newThread = false;
163 |  |
164 |  |
165 |  |
     	/**
166 |  |
     	 * <code>InvocHandler</code> のインスタンスを生成します.
167 |  |
     	 * @param	target	実際のイベントハンドラ
168 |  |
     	 * @param	targetMethod	実際に処理を行うメソッド
169 |  |
     	 * @param	sourceMethod	イベントソースによって呼び出されるメソッド
170 |  |
     	 */
171 |  |
     	InvocHandler( Object target, Method targetMethod, Method sourceMethod, boolean newThread )
172 |  |
     	{
173 |  |
     		_target = target;
174 |  |
     		_targetMethod = targetMethod;
175 |  |
     		_sourceMethod = sourceMethod;
176 |  |
     		_newThread = newThread;
177 |  |
     	}
178 |  |
179 |  |
180 |  |
     //
181 |  |
     //	InvocationHandler の実装
182 |  |
     //
183 |  |
     	/**
184 |  |
     	 * Processes a method invocation on a proxy instance and returns the result. This method
185 |  |
     	 * will be invoked on an invocation handler when a method is invoked on a proxy instance
186 |  |
     	 * that it is associated with.
187 |  |
     	 * @param	proxy	the proxy instance that the method was invoked on
188 |  |
     	 * @param	meth	the Method instance corresponding to the interface method invoked on
189 |  |
     	 * the proxy instance. The declaring class of the Method object will be the interface that
190 |  |
     	 * the method was declared in, which may be a superinterface of the proxy interface that
191 |  |
     	 * the proxy class inherits the method through.
192 |  |
     	 * @param	args	an array of objects containing the values of the arguments passed in
193 |  |
     	 * the method invocation on the proxy instance, or null if interface method takes no arguments.
194 |  |
     	 * Arguments of primitive types are wrapped in instances of the appropriate primitive wrapper
195 |  |
     	 * class, such as <code>java.lang.Integer</code> or <code>java.lang.Boolean</code>.
196 |  |
     	 * @return	the value to return from the method invocation on the proxy instance. If the
197 |  |
     	 * declared return type of the interface method is a primitive type, then the value returned
198 |  |
     	 * by this method must be an instance of the corresponding primitive wrapper class; otherwise,
199 |  |
     	 * it must be a type assignable to the declared return type. If the value returned by this
200 |  |
     	 * method is <code>null</code> and the interface method's return type is primitive, then a
201 |  |
     	 * <code>NullPointerException<code> will be thrown by the method invocation on the proxy
202 |  |
     	 * instance. If the value returned by this method is otherwise not compatible with the
203 |  |
     	 * interface method's declared return type as described above, a <code>ClassCastException</code>
204 |  |
     	 * will be thrown by the method invocation on the proxy instance
205 |  |
     	 */
206 |  |
     	public Object invoke( Object proxy, Method meth, Object[] args )
207 |  |
     		throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
208 |  |
     	{
209 |  |
     		if( !_sourceMethod.equals(meth) )	{
210 |  |
     			return null;
211 |  |
     		}
212 |  |
213 |  |
     		if( _targetMethod.getParameterTypes().length == 0 )	{
214 |  |
     			args = null;
215 |  |
     		}
216 |  |
217 |  |
     		if( _newThread )	{
218 |  |
     			new Thread( class="keyword">new InvokerRunner(_target, _targetMethod, args) ).start();
219 |  |
     			return null;
220 |  |
     		}
221 |  |
     		else	{
222 |  |
     			return _targetMethod.invoke( _target, args );
223 |  |
     		}
224 |  |
     	}
225 |  |
     }
226 |  |
227 |  |
     class InvokerRunner implements Runnable	{
228 |  |
229 |  |
     	protected Object	_target = null;
230 |  |
231 |  |
     	protected Method	_method = null;
232 |  |
233 |  |
     	protected Object[]	_args = null;
234 |  |
235 |  |
236 |  |
     	InvokerRunner( Object target, Method method, Object[] args )
237 |  |
     	{
238 |  |
     		super();
239 |  |
     		_target = target;
240 |  |
     		_method = method;
241 |  |
     		_args = args;
242 |  |
     	}
243 |  |
244 |  |
245 |  |
     	public void run()
246 |  |
     	{
247 |  |
     		try	{
248 |  |
     			_method.invoke( _target, _args );
249 |  |
     		}
250 |  |
     		catch( Exception e )	{
251 |  |
     			//ignore.
252 |  |
     		}
253 |  |
     	}
254 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.