/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.data.wfs.protocol.wfs; import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.imageio.spi.ServiceRegistry; import org.eclipse.emf.ecore.EObject; import org.geotools.data.wfs.WFSDataStore; import org.geotools.data.wfs.v1_1_0.WFS_1_1_0_DataStore; import org.geotools.factory.FactoryNotFoundException; /** * Utility class to look up for a parser that can deal with a given WFS response and process it. * <p> * This class uses the usual GeoTools SPI (Service Provider Interface) mechanism to find out a * {@link WFSResponseParserFactory} for a given {@link WFSResponse}. As such, * {@link WFSResponseParserFactory} implementation may live outside this plugin as long as they're * declared in it's own {code * /META-INF/services/org.geotools.data.wfs.protocol.wfs.WFSResponseParserFactory} text file. * </p> * * @author Gabriel Roldan (OpenGeo) * @version $Id$ * @since 2.6 * * * @source $URL$ * http://svn.osgeo.org/geotools/trunk/modules/unsupported/wfs/src/main/java/org/geotools * /data/wfs/protocol/wfs/WFSExtensions.java $ */ @SuppressWarnings("nls") public class WFSExtensions { /** * The service registry for this manager. Will be initialized only when first needed. */ private static Set<WFSResponseParserFactory> registry; /** * Processes the result of a WFS operation and returns the parsed object. * <p> * The result can either be: * <ul> * <li>a {@link WFSException} exception if the WFS response was an exception report * <li>a {@link GetFeatureParser} if the WFS returned a FeatureCollection * </p> * * @param request * the WFS request that originated the given response * @param response * the handle to the WFS response contents * @return * @throws IOException */ public static Object process(WFS_1_1_0_DataStore wfs, WFSResponse response) throws IOException { EObject originatingRequest = response.getOriginatingRequest(); WFSResponseParserFactory pf = findParserFactory(originatingRequest); WFSResponseParser parser = pf.createParser(wfs, response); Object result = parser.parse(wfs, response); return result; } /** * @param requestType * @param outputFormat * @return * @throws FactoryNotFoundException */ static WFSResponseParserFactory findParserFactory(EObject request) { Iterator<WFSResponseParserFactory> serviceProviders; serviceProviders = getServiceProviders(); WFSResponseParserFactory factory; while (serviceProviders.hasNext()) { factory = serviceProviders.next(); if (factory.isAvailable()) { if (factory.canProcess(request)) { return factory; } } } throw new FactoryNotFoundException("Can't find a response parser factory for " + request); } private static Iterator<WFSResponseParserFactory> getServiceProviders() { if (registry == null) { synchronized (WFSExtensions.class) { if (registry == null) { /* * Set the current thread's class loader to the one that actually loaded the * WDSDataStore and related classes for while the factory lookup is performed. * This way the module is friendlier to crazy class loader hierarchies like * OSGI/Eclipse */ final ClassLoader current = Thread.currentThread().getContextClassLoader(); try { final ClassLoader tempClassLoader = WFSDataStore.class.getClassLoader(); Thread.currentThread().setContextClassLoader(tempClassLoader); /* * Now that we're on the correct classloader lets perform the lookup */ Iterator<WFSResponseParserFactory> providers; providers = ServiceRegistry.lookupProviders(WFSResponseParserFactory.class); registry = new HashSet<WFSResponseParserFactory>(); while (providers.hasNext()) { WFSResponseParserFactory provider = providers.next(); registry.add(provider); } } finally { /* * And finally restore the original thread's class loader */ Thread.currentThread().setContextClassLoader(current); } } } } return registry.iterator(); } }