/*************************************************************** Copyright (C) 2009-2013 by 52 North Initiative for Geospatial Open Source Software GmbH Contact: Andreas Wytzisk 52 North Initiative for Geospatial Open Source Software GmbH Martin-Luther-King-Weg 24 48155 Muenster, Germany info@52north.org This program is free software; you can redistribute and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed WITHOUT ANY WARRANTY; even without the implied WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see gnu-gpl v2.txt). If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or visit the Free Software Foundation web page, http://www.fsf.org. ***************************************************************/ package org.n52.wps.ags.workspace; import java.io.IOException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import com.esri.arcgis.interop.AutomationException; import com.esri.arcgis.server.IServerContext; import com.esri.arcgis.server.IServerObjectManager; import com.esri.arcgis.server.ServerConnection; import com.esri.arcgis.system.ServerInitializer; import com.esri.arcgis.system.VarArray; /** * Factory class for server contexts. This class caches available contexts * and initializes new contexts if needed. * * @author matthes rieke * */ public class ServerContextFactory { private static final Object mutex = new Object(); private static Logger LOGGER = LoggerFactory.getLogger(ServerContextFactory.class); private static List<LockedServerContext> contexts = new ArrayList<LockedServerContext>(); private static IServerContext initializeContext() throws IOException { if (LOGGER.isInfoEnabled()) { if (System.getProperty("JINTEGRA_NATIVE_MODE") == null) { LOGGER.info("Running geoprocessor in DCOM Mode"); } else { LOGGER.info("Running geoprocessor in Native Mode"); } } try { if (LOGGER.isInfoEnabled()) LOGGER.info("Getting AGS connection object ..."); ServerConnection connection = getAGSConnection(); IServerObjectManager som = connection.getServerObjectManager(); IServerContext context = som.createServerContext("", ""); return context; } catch (AutomationException ae){ LOGGER.error("Caught J-Integra AutomationException: " + ae.getMessage() + "\n"); throw new IOException(ae); } catch (IOException e){ LOGGER.error("Caught IOException: " + e.getMessage() + "\n"); throw e; } } private static final ServerConnection getAGSConnection() throws IOException { if (LOGGER.isInfoEnabled()) LOGGER.info("initializing server ..."); AGSPropertiesWrapper agsProps = AGSPropertiesWrapper.getInstance(); ServerInitializer serverInitializer = new ServerInitializer(); serverInitializer.initializeServer(agsProps.getDomain(), agsProps.getUser(), agsProps.getPass()); ServerConnection connection = null; try { connection = new ServerConnection(); connection.connect(agsProps.getIP()); if (LOGGER.isInfoEnabled()) LOGGER.info("server initialized!"); } catch (UnknownHostException e) { LOGGER.error("UnknownHostException - Could not connect to AGS host " + agsProps.getDomain() + " with user " + agsProps.getUser()); throw new IOException("Error connecting to ArcGIS Server."); } catch (IOException e) { LOGGER.error("IOException - Could not connect to AGS host " + agsProps.getDomain() + " with user " + agsProps.getUser()); LOGGER.info("Please check firewall setup! - and maybe the folder permissions, too"); throw new IOException("Error connecting to ArcGIS Server."); } return connection; } /** * Returns a {@link LockedServerContext} object, either * cached or newly created. */ public static LockedServerContext retrieveContext() throws IOException { LockedServerContext result = null; List<LockedServerContext> toBeRemoved = new ArrayList<LockedServerContext>(); synchronized (mutex) { for (LockedServerContext lsc : contexts) { if (lsc.lockAndGet()) { if (!ensureLiveness(lsc)) { toBeRemoved.add(lsc); continue; } result = lsc; break; } } if (result == null) { result = new LockedServerContext(initializeContext()); result.lockAndGet(); contexts.add(result); } if (!toBeRemoved.isEmpty()) { contexts.removeAll(toBeRemoved); } } return result; } /** * Checks if a context is still alive by * trying to create a Arcobject instance. */ private static boolean ensureLiveness(LockedServerContext lsc) { try { Object object = lsc.getContext().createObject(VarArray.getClsid()); return object != null && object instanceof VarArray; } catch (Exception e) { return false; } } /** * Return the context and make it usable for other * processes. */ public static void returnContext(LockedServerContext context) { context.releaseLock(); } /** * Release all cached contexts. */ public static void releaseAllCachedContexts() throws IOException { synchronized (mutex) { for (LockedServerContext lsc : contexts) { lsc.releaseContext(); } } } /** * Class for providing mutual exclusion access to an * {@link IServerContext} object. * * @author matthes rieke * */ public static class LockedServerContext { IServerContext context; private boolean locked; public LockedServerContext(IServerContext c) { context = c; } public synchronized boolean lockAndGet() { if (this.locked) return false; this.locked = true; return true; } public synchronized void releaseLock() { this.locked = false; } public IServerContext getContext() { return context; } private void releaseContext() throws IOException { context.releaseContext(); } } }