/* * Copyright 2009 NCHOVY * * 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.krakenapps.filter; import java.util.Dictionary; import java.util.Properties; import org.apache.felix.ipojo.ConfigurationException; import org.apache.felix.ipojo.PrimitiveHandler; import org.apache.felix.ipojo.metadata.Element; import org.apache.felix.ipojo.parser.FieldMetadata; import org.apache.felix.ipojo.parser.PojoMetadata; import org.krakenapps.filter.exception.AlreadyBoundException; import org.krakenapps.filter.exception.FilterNotFoundException; import org.krakenapps.filter.exception.MessageSpecMismatchException; import org.krakenapps.filter.impl.DefaultFilterChain; import org.krakenapps.filter.impl.FilterConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This handler class provides filter extension of iPOJO component instance. * FilterHanler injects a {@link FilterChain} instance and loads all properties. * Dynamic filter binding feature is implemented based on iPOJO code injection. * * @author xeraph * @since 1.0.0 */ public class FilterHandler extends PrimitiveHandler { /** * the slf4j logger */ final Logger logger = LoggerFactory.getLogger(FilterHandler.class.getName()); /** * the filter manager instance */ private FilterManager filterManager; /** * the filter config instance */ private FilterConfig filterConfig; /** * the injected filter chain instance */ private volatile FilterChain filterChain; /** * the filter id */ private String filterId; /** * Invoked when a filter component instance is created. Inject filter chain * field here. */ @SuppressWarnings("rawtypes") @Override public void configure(Element metadata, Dictionary config) throws ConfigurationException { filterManager = (FilterManager) config.get("filter.manager"); filterConfig = (FilterConfig) config.get("filter.config"); filterId = (String) config.get("instance.name"); // inspects all fields and inject filter chain field. PojoMetadata pojoMetadata = getPojoMetadata(); for (FieldMetadata fieldMetadata : pojoMetadata.getFields()) { if (fieldMetadata.getFieldType().equals("org.krakenapps.filter.FilterChain")) { getInstanceManager().register(fieldMetadata, this); } } // set instance.name property. Filter filter = getFilter(); filter.setProperty("instance.name", filterId); // creates a filter chain instance with empty filter bindings. filterChain = new DefaultFilterChain(filter, new Filter[0]); logger.trace("filter [{}] configuration succeeded.", filterId); } /** * Invoked when a filter is validated. Register the filter instance and * restore previous states. (properties and bind states) */ @Override public void start() { logger.debug("Kraken filter handler is started."); Filter filter = getFilter(); filterManager.registerFilter(this, filterId, filter); loadProperties(filter); bindAutomatically(filterId); } private void loadProperties(Filter filter) { int filterType = 0; if (filter instanceof ActiveFilter) { filterType = 1; } // write filter instance information to data store. filterConfig.addFilterInstance(filterId, filter.getClass().getName(), filterType); // load properties from data store if exists. Properties props = filterConfig.getFilterProperties(filterId); for (Object key : props.keySet()) { filter.setProperty((String) key, (String) props.get(key)); } } /** * Invoked when a filter is invalidated. */ @Override public void stop() { logger.debug("Kraken filter handler is stopped."); filterManager.unregisterFilter(filterId); } private void bindAutomatically(String pid) { for (String target : filterConfig.getOutputFilters(pid)) { if (filterManager.getFilter(target) != null) try { filterManager.bindFilter(pid, target); logger.trace(pid + " -> " + target + " binded."); } catch (FilterNotFoundException e) { logger.warn("filter not found:", e); } catch (AlreadyBoundException e) { logger.warn("filter is already bound:", e); } catch (MessageSpecMismatchException e) { logger.warn("message spec mismatch:", e); } } for (String from : filterConfig.getInputFilters(pid)) { if (filterManager.getFilter(from) != null) try { filterManager.bindFilter(from, pid); logger.info(from + " -> " + pid + " binded."); } catch (FilterNotFoundException e) { logger.warn("filter not found:", e); } catch (AlreadyBoundException e) { logger.warn("filter is already bound:", e); } catch (MessageSpecMismatchException e) { logger.warn("message spec mismatch:", e); } } } /** * Invoked when the registered filter chain field is accessed. */ @Override public Object onGet(Object pojo, String fieldName, Object value) { return filterChain; } private Filter getFilter() { return (Filter) getInstanceManager().getPojoObject(); } /** * Invoked when a filter's binding states are changed cause of bind command * or unbind command. * * @param boundOutputFilters * the bound output filters */ public void stateChanged(Filter[] boundOutputFilters) { filterChain = new DefaultFilterChain(getFilter(), boundOutputFilters); } }