/** * Construct a new MappedMessageHandler from the provided configuration. * * @param config the {@link MessageHandlerConfiguration} used to configure this instance * @throws ToolkitException rethrown from {@link * MessageHandlerConfigurationFactory#getConfiguration()}. */ public MappedMessageHandler(MessageHandlerConfiguration config) throws ToolkitException { supportedServices = new HashMap<String, NCIPService<NCIPInitiationData, NCIPResponseData>>(); Properties properties = config.getProperties(); for (Enumeration enumeration = properties.keys(); enumeration.hasMoreElements(); /**/ ) { String key = (String) enumeration.nextElement(); LOG.debug("Property key=" + key); if (key.compareToIgnoreCase("java.version") == 0) { LOG.debug("Java version is " + properties.get(key)); } if (key.matches("(?i)[A-Za-z]+Service\\.Class")) { String className = (String) properties.get(key); LOG.debug("Class name=" + className); if (className == null || className.isEmpty() || className.compareToIgnoreCase("null") == 0) { continue; } try { Class<?> clazz = Class.forName(className); Class<? extends NCIPService> xc = clazz.asSubclass(NCIPService.class); LOG.debug("Class as subclass=" + xc.getName()); try { NCIPService<NCIPInitiationData, NCIPResponseData> serviceInstance; try { Constructor<? extends NCIPService> propertiesCtor = xc.getConstructor(Properties.class); serviceInstance = propertiesCtor.newInstance(properties); } catch (NoSuchMethodException e) { serviceInstance = xc.newInstance(); } catch (InvocationTargetException e) { throw new ToolkitException( "Exception constructing " + className + " using Properties:", e); } Method[] methods = clazz.getMethods(); Class initDataClass = null; // TODO: Try replacing this with getMethod("performService", NCIPInitiationData.class, // ServiceContext.class, RemoteServiceManager.class); for (Method method : methods) { LOG.debug("Testing method " + method.getName()); if (method.getName().compareToIgnoreCase("performService") == 0) { LOG.debug("Method is performService."); Class[] parameterTypes = method.getParameterTypes(); // This assumes there will only be one performService method on any class, // i.e. the one required by the NCIPService interface definition. // While the definition of NCIPService doesn't actually enforce this, // it would be perverse to define an additional method with that name // taking similar parameter types. if (parameterTypes.length == NUMBER_OF_PARAMETERS_TO_PERFORM_SERVICE_METHOD) { LOG.debug("Method takes " + parameterTypes.length + " parameters."); Class parameterClass = parameterTypes[0]; LOG.debug("ParameterType[0] is " + parameterClass.getName()); if (parameterClass.getName().compareTo(Class.class.getName()) != 0) { initDataClass = parameterClass; if (initDataClass.getName().compareTo(Object.class.getName()) == 0) { LOG.warn( "Class first parameter is 'Object'; trying to use property key to get actual initDataClass."); String serviceName = key.substring(0, key.length() - "Service.Class".length()); initDataClass = ServiceHelper.constructInitiationDataClass(serviceName); } else { LOG.debug("The initDataClass is not 'Object'."); } LOG.debug("Selecting " + initDataClass.getName() + " as initDataClass."); break; } else { LOG.debug( "The performService method for class " + clazz.getName() + " takes a Class parameter, which is disallowed."); } } else { LOG.debug( "The performService method for class " + clazz.getName() + " has no parameters."); } } else { LOG.debug("Method is not performService."); } } LOG.debug("Finished checking methods."); if (initDataClass != null) { LOG.debug( "Putting " + serviceInstance.getClass().getName() + " into supportedServices map " + "with key of " + initDataClass.getName() + "."); supportedServices.put(initDataClass.getName(), serviceInstance); } else { throw new ToolkitException( "Unable to determine NCIPInitiationData sub-class with " + "name '" + className + "' for " + key); } } catch (InstantiationException e) { throw new ToolkitException("Exception while populating supported services.", e); } catch (IllegalAccessException e) { throw new ToolkitException("Exception while populating supported services.", e); } } catch (ClassNotFoundException e) { throw new ToolkitException( "Class not found exception while populating supported services.", e); } } else if (key.matches("(?i)RemoteServiceManager\\.Class")) { try { Class<?> clazz = Class.forName(properties.getProperty(key)); Constructor ctor = clazz.getConstructor(Properties.class); serviceManager = (RemoteServiceManager) ctor.newInstance(properties); } catch (ClassNotFoundException e) { throw new ToolkitException("Exception while populating supported services.", e); } catch (NoSuchMethodException e) { throw new ToolkitException("Exception while populating supported services.", e); } catch (InvocationTargetException e) { throw new ToolkitException("Exception while populating supported services.", e); } catch (InstantiationException e) { throw new ToolkitException("Exception while populating supported services.", e); } catch (IllegalAccessException e) { throw new ToolkitException("Exception while populating supported services.", e); } } } LOG.debug("Finished with properties."); if (LOG.isDebugEnabled()) { LOG.debug("Service map for " + this + ":"); for (Map.Entry<String, NCIPService<NCIPInitiationData, NCIPResponseData>> entry : supportedServices.entrySet()) { LOG.debug(entry.getKey() + "=" + entry.getValue()); } } }
@Override public NCIPResponseData performService( NCIPInitiationData initiationData, ServiceContext serviceContext) { NCIPResponseData responseData; if (initiationData != null) { NCIPService<NCIPInitiationData, NCIPResponseData> service = null; if (LOG.isDebugEnabled()) { LOG.debug( "Looking in supported services map (" + this + ") for service to handle " + initiationData.getClass().getName()); for (Map.Entry<String, NCIPService<NCIPInitiationData, NCIPResponseData>> entry : supportedServices.entrySet()) { LOG.debug(entry.getKey() + "=" + entry.getValue()); } } if (supportedServices != null) { service = supportedServices.get(initiationData.getClass().getName()); LOG.debug("service is " + service); } else { LOG.debug("supportedServices is null."); } // Try a "wildcard" match. if (service == null) { LOG.debug("service is null, trying wildcard match."); service = supportedServices.get(NCIPInitiationData.class.getName()); LOG.debug("service is " + service); } if (service != null) { LOG.debug("service is " + service + ", calling performService method."); try { responseData = service.performService(initiationData, serviceContext, serviceManager); LOG.debug("Result from performService call is " + responseData); } catch (ServiceException e) { List<Problem> problems = ServiceHelper.generateProblems( Version1GeneralProcessingError.TEMPORARY_PROCESSING_FAILURE, "NCIPMessage", null, "Exception:", e); ProblemResponseData problemResponseData = new ProblemResponseData(); problemResponseData.setProblems(problems); responseData = problemResponseData; } catch (ValidationException e) { ProblemResponseData problemResponseData = new ProblemResponseData(); problemResponseData.setProblems(e.getProblems()); responseData = problemResponseData; } } else { LOG.debug("service is null, returning Unsupported Service response."); List<Problem> problems = ServiceHelper.createUnsupportedServiceProblems(initiationData); ProblemResponseData problemResponseData = new ProblemResponseData(); problemResponseData.setProblems(problems); responseData = problemResponseData; } } else { // If this happens, there is a bug in the code that calls this; you need to find and fix that // bug. LOG.debug("initiationData is null, returning Temporary Processing Failure response."); List<Problem> problems = ServiceHelper.generateProblems( Version1GeneralProcessingError.TEMPORARY_PROCESSING_FAILURE, null, null, "Translation of initiation message failed (initiationData is null)"); ProblemResponseData problemResponseData = new ProblemResponseData(); problemResponseData.setProblems(problems); responseData = problemResponseData; } return responseData; }