/* * 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.servlet.text.impl; import java.lang.reflect.Method; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Invalidate; import org.apache.felix.ipojo.annotations.Provides; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.Validate; import org.krakenapps.http.HttpServiceManager; import org.krakenapps.http.KrakenHttpService; import org.krakenapps.servlet.text.TextHttpMethod; import org.krakenapps.servlet.text.TextHttpService; import org.krakenapps.servlet.text.TextHttpServlet; import org.krakenapps.servlet.text.TextHttpServiceApi; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.http.NamespaceException; import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(name = "text-http-service-api") @Provides(specifications = { TextHttpServiceApi.class }) public class TextHttpServiceApiImpl extends ServiceTracker implements TextHttpServiceApi { final Logger logger = LoggerFactory.getLogger(TextHttpServiceApiImpl.class.getName()); @Requires private HttpServiceManager httpServiceManager; private ConcurrentMap<String, TextHttpService> serviceMap; /* * key: service name, value: TextMethod list */ private Map<String, Set<String>> methodMap; private BundleContext bc; public TextHttpServiceApiImpl(BundleContext bc) { super(bc, TextHttpService.class.getName(), null); this.bc = bc; } @SuppressWarnings("unused") @Validate private void start() { serviceMap = new ConcurrentHashMap<String, TextHttpService>(); methodMap = new ConcurrentHashMap<String, Set<String>>(); try { ServiceReference[] refs = bc.getServiceReferences(TextHttpService.class.getName(), null); if (refs != null) { for (ServiceReference ref : refs) { TextHttpService service = (TextHttpService) bc.getService(ref); logger.debug("[text] investigating filter: " + service.getName()); addTextMapping(service); } } } catch (InvalidSyntaxException e) { } open(); } @SuppressWarnings("unused") @Invalidate private void stop() { serviceMap.clear(); methodMap.clear(); close(); } @Override public Map<String, Set<String>> getAvailableFilters() { return methodMap; } @Override public Object invokeTextMethod(String serviceName, String methodName, HttpServletRequest req) throws Exception { Set<String> textMethods = methodMap.get(serviceName); if (textMethods == null) { throw new NoSuchMethodException(); } if (!textMethods.contains(methodName)) throw new NoSuchMethodException(); TextHttpService service = serviceMap.get(serviceName); if (service == null) throw new NoSuchMethodException(); logger.debug("[text-servlet] calling text method: " + methodName); Method method = service.getClass().getMethod(methodName, new Class[] { HttpServletRequest.class }); return method.invoke(service, new Object[] { req }); } @Override public Object invokeTextMethod(String serviceName, String methodName, Map<String, Object> params) throws Exception { Set<String> textMethods = methodMap.get(serviceName); if (textMethods == null) { throw new NoSuchMethodException(); } if (!textMethods.contains(methodName)) throw new NoSuchMethodException(); TextHttpService service = serviceMap.get(serviceName); if (service == null) throw new NoSuchMethodException(); logger.debug("[text-servlet] calling text method: " + methodName); Method method = service.getClass().getMethod(methodName, new Class[] { Map.class }); return method.invoke(service, new Object[] { params }); } @Override public void registerServlet(String serverId, String pathSpec) throws ServletException, NamespaceException { KrakenHttpService server = httpServiceManager.getHttpService(serverId); server.registerServlet(pathSpec, new TextHttpServlet(this), null, null); } private void addTextMapping(TextHttpService service) { Set<String> textMethods = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); Method[] methods = service.getClass().getMethods(); for (Method method : methods) { TextHttpMethod m = method.getAnnotation(TextHttpMethod.class); if (m != null) { logger.trace("[text] registering filter method: " + method.getName()); textMethods.add(method.getName()); } } if (textMethods.size() > 0) { serviceMap.put(service.getName(), service); methodMap.put(service.getName(), textMethods); } } private void removeTextMapping(TextHttpService service) { methodMap.remove(service.getName()); } @Override public Object addingService(ServiceReference reference) { TextHttpService service = (TextHttpService) super.addingService(reference); logger.trace("[text-servlet] filter loaded: " + service.getName()); addTextMapping(service); return service; } @Override public void removedService(ServiceReference reference, Object service) { TextHttpService text = (TextHttpService) service; logger.trace("[text-servlet] filter loaded: " + text.getName()); removeTextMapping(text); super.removedService(reference, service); } }