/* * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springmodules.lucene.index.core.concurrent; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springmodules.lucene.index.core.LuceneIndexTemplate; /** * This class is the dedicated channel listener implementation. It * then delegates the execution of the requests to the injected * template. * @author Thierry Templier * @see org.springmodules.lucene.index.core.LuceneIndexTemplate * @see org.springmodules.lucene.index.core.concurrent.LuceneChannel */ public class ConcurrentLuceneIndexTemplateListener implements InitializingBean,DisposableBean { public final static String STOP_LISTENER_KEYWORD="stop"; private LuceneIndexTemplate template; private LuceneChannel channel; private static final Log logger = LogFactory.getLog(ConcurrentLuceneIndexTemplateListener.class); /** * Set the channel used to manage concurrent calls on the index. */ public void setChannel(LuceneChannel channel) { this.channel = channel; } /** * Return the channel used to manage concurrent calls on the index. */ public LuceneChannel getChannel() { return channel; } /** * Set a configured template. */ public void setTemplate(LuceneIndexTemplate template) { this.template = template; } /** * Return the LuceneIndexTemplate to use. */ public LuceneIndexTemplate getTemplate() { return template; } /** * This method initializes the listener thread to manage the * requests sent on the channel. It is responsible to execute * the corresponding method on the injected template. * * This thread is stopped when a request with the method name * 'stop' is received. This request is sent by the destroy method * at the closing of the context. */ public void afterPropertiesSet() throws Exception { if( template==null ) { throw new IllegalArgumentException("template is required."); } Runnable manager=new Runnable() { public void run() { try { for(;;) { LuceneChannelRequest request=(LuceneChannelRequest)channel.getRequest(); // Manage the stop of the thread if( request.getMethodName().equals(STOP_LISTENER_KEYWORD) ) { break; } // Delegate operations on the Lucene template Object returnObject=invokeMethod(request); if( returnObject!=null ) { LuceneChannelResponse response=new LuceneChannelResponse(returnObject); channel.putResponse(response); } System.out.println(request); } } catch(InterruptedException ex) { logger.error("An error occured on the channel.",ex); logger.info("Concurent Lucene worker stopped."); } } }; (new Thread(manager)).start(); logger.info("Concurent Lucene worker started."); } /** * This method is used to get the Method object corresponding to the * method based on the parameters contained in the request object. * @param request the request representing the method to execute * @return the Method instance representing the method of the request */ private Method getMethod(LuceneChannelRequest request) throws SecurityException, NoSuchMethodException { Object[] parameters=request.getMethodParameters(); Class[] parameterClasses=request.getMethodParameterClasses(); Class returnType=request.getReturnType(); return LuceneIndexTemplate.class.getDeclaredMethod( request.getMethodName(),parameterClasses); } /** * This method is used to invoke the target method based on the * parameters contained in the request object. * @param request the request representing the method to execute * @return the object returned to the call of the method */ private Object invokeMethod(LuceneChannelRequest request) { try { Method method=getMethod(request); System.out.println("method = "+method); System.err.println("Avant invoke"); return method.invoke(template,request.getMethodParameters()); } catch(Exception ex) { // TODO Manage exception ex.printStackTrace(); } return null; } /** * This method stops the thread to manage the requests of the * channel. A request with the method name 'stop' is sent. */ public void destroy() throws Exception { // Stopping the listener channel.executeWithoutReturn(new LuceneChannelRequest(STOP_LISTENER_KEYWORD,null,null,null)); logger.info("Concurent Lucene worker stopped."); System.err.println("Concurent Lucene worker stopped."); } }