/* * 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.xml.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 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.xml.XmlHttpService; import org.krakenapps.servlet.xml.XmlHttpMethod; import org.krakenapps.servlet.xml.XmlHttpServiceApi; import org.krakenapps.servlet.xml.XmlHttpServlet; 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 = "xml-http-service-api") @Provides(specifications = { XmlHttpServiceApi.class }) public class XmlHttpServiceApiImpl extends ServiceTracker implements XmlHttpServiceApi { final Logger logger = LoggerFactory.getLogger(XmlHttpServiceApiImpl.class.getName()); @Requires private HttpServiceManager httpServiceManager; private ConcurrentMap<String, XmlHttpService> serviceMap; /* * key: filter id, value: XmlMethod list */ private Map<String, Set<String>> methodMap; private BundleContext bc; public XmlHttpServiceApiImpl(BundleContext bc) { super(bc, XmlHttpService.class.getName(), null); this.bc = bc; } @SuppressWarnings("unused") @Validate private void start() { serviceMap = new ConcurrentHashMap<String, XmlHttpService>(); methodMap = new ConcurrentHashMap<String, Set<String>>(); try { ServiceReference[] refs = bc.getServiceReferences(XmlHttpService.class.getName(), null); if (refs != null) { for (ServiceReference ref : refs) { XmlHttpService service = (XmlHttpService) bc.getService(ref); logger.debug("[xml-servlet] investigating service: " + service.getName()); addXmlMapping(service); } } } catch (InvalidSyntaxException e) { } open(); } @SuppressWarnings("unused") @Invalidate private void stop() { serviceMap.clear(); methodMap.clear(); close(); } @Override public void registerServlet(String serverId, String pathSpec) throws ServletException, NamespaceException { KrakenHttpService http = httpServiceManager.getHttpService(serverId); http.registerServlet(pathSpec, new XmlHttpServlet(this), null, null); } private void addXmlMapping(XmlHttpService service) { Set<String> xmlMethods = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); Method[] methods = service.getClass().getMethods(); for (Method method : methods) { XmlHttpMethod m = method.getAnnotation(XmlHttpMethod.class); if (m != null) { xmlMethods.add(method.getName()); } } if (xmlMethods.size() > 0) { serviceMap.put(service.getName(), service); methodMap.put(service.getName(), xmlMethods); } } private void removeXmlMapping(XmlHttpService service) { methodMap.remove(service.getName()); } @Override public Object addingService(ServiceReference reference) { XmlHttpService svc = (XmlHttpService) super.addingService(reference); logger.trace("[xml-servlet] xml http service loaded: " + svc.getName()); addXmlMapping(svc); return svc; } @Override public void removedService(ServiceReference reference, Object service) { XmlHttpService svc = (XmlHttpService) service; logger.trace("[xml-servlet] xml http service unloaded: " + svc.getName()); removeXmlMapping(svc); super.removedService(reference, service); } @Override public Map<String, Set<String>> getXmlHttpMappings() { return methodMap; } @Override public Object invokeXmlMethod(String serviceName, String methodName, Map<String, Object> params) throws Exception { Set<String> xmlMethods = methodMap.get(serviceName); if (xmlMethods == null) { return null; } if (!xmlMethods.contains(methodName)) throw new NoSuchMethodException("no such method"); XmlHttpService service = serviceMap.get(serviceName); if (service == null) return null; logger.debug("[xml-servlet] calling xml method {}", methodName); Method method = service.getClass().getMethod(methodName, new Class[] { Map.class }); return method.invoke(service, new Object[] { params }); } }