/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.vfny.geoserver.action.data; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.geotools.data.DataStore; import org.geotools.data.DataStoreFactorySpi; import org.geotools.data.DataAccessFactory.Param; import org.opengis.feature.simple.SimpleFeatureType; import org.vfny.geoserver.action.ConfigAction; import org.vfny.geoserver.config.DataConfig; import org.vfny.geoserver.config.DataStoreConfig; import org.vfny.geoserver.config.FeatureTypeConfig; import org.vfny.geoserver.config.NameSpaceConfig; import org.vfny.geoserver.form.data.DataDataStoresEditorForm; import org.vfny.geoserver.global.GeoserverDataDirectory; import org.vfny.geoserver.global.UserContainer; import org.vfny.geoserver.util.DataStoreUtils; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.logging.Level; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * DOCUMENT ME! * * @author rgould To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class DataDataStoresEditorAction extends ConfigAction { public ActionForward execute(ActionMapping mapping, ActionForm form, UserContainer user, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { DataDataStoresEditorForm dataStoresForm = (DataDataStoresEditorForm) form; String dataStoreID = dataStoresForm.getDataStoreId(); String namespace = dataStoresForm.getNamespaceId(); String description = dataStoresForm.getDescription(); DataConfig dataConfig = (DataConfig) getDataConfig(); DataStoreConfig config = null; config = (DataStoreConfig) dataConfig.getDataStore(dataStoreID); boolean isNewDataStore = false; if (config == null) { // we are creating a new one. dataConfig.addDataStore(getUserContainer(request).getDataStoreConfig()); config = (DataStoreConfig) dataConfig.getDataStore(dataStoreID); isNewDataStore = true; } // After extracting params into a map Map connectionParams = new HashMap(); // values used for connection Map paramTexts = new HashMap(); // values as stored Map params = dataStoresForm.getParams(); DataStoreFactorySpi factory = config.getFactory(); Param[] info = factory.getParametersInfo(); // Convert Params into the kind of Map we actually need // for (Iterator i = params.keySet().iterator(); i.hasNext();) { String key = (String) i.next(); Param param = DataStoreUtils.find(info, key); if (param == null) { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.cannotProcessConnectionParams")); saveErrors(request, errors); return mapping.findForward("config.data.store.editor"); } Object value; try { value = param.lookUp(params); } catch (IOException erp) { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.cannotProcessConnectionParams")); saveErrors(request, errors); return mapping.findForward("config.data.store.editor"); } if ((value != null) && !"".equals(value)) { connectionParams.put(key, value); String text = param.text(value); paramTexts.put(key, text); } } // put magic namespace into the mix // not sure if we want to do this, as we want the full namespace, not //the id. But getParams in DataStore may override this - ch NameSpaceConfig nsConfig = getDataConfig().getNameSpace(dataStoresForm.getNamespaceId()); if(nsConfig != null) { connectionParams.put("namespace", nsConfig.getUri()); paramTexts.put("namespace", nsConfig.getUri()); } else { // just because the code before the GEOS-2383 fix looked like this, I kept it, // but we should never really get here connectionParams.put("namespace", dataStoresForm.getNamespaceId()); paramTexts.put("namespace", dataStoresForm.getNamespaceId()); } //dump("editor", connectionParams ); //dump("texts ",paramTexts ); Map fixedParams = org.vfny.geoserver.global.DataStoreInfo.getParams(connectionParams, GeoserverDataDirectory.getGeoserverDataDirectory().getAbsolutePath()); if (!factory.canProcess(fixedParams)) { // We could not use these params! // ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.cannotProcessConnectionParams")); saveErrors(request, errors); return mapping.findForward("config.data.store.editor"); } SimpleFeatureType singleFeatureType = null; DataStore victim = null; try { ServletContext sc = request.getSession().getServletContext(); victim = DataStoreUtils.acquireDataStore(paramTexts, sc); if (victim == null) { // We *really* could not use these params! // ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.invalidConnectionParams")); saveErrors(request, errors); return mapping.findForward("config.data.store.editor"); } String[] typeNames = victim.getTypeNames(); //If there's only one featureType in the datastore, then we //want to be nice to users and pass them directly to the editor, //so we need to get the featureType here. if (typeNames.length == 1) { singleFeatureType = victim.getSchema(typeNames[0]); } dump("typeNames", typeNames); } catch (Throwable throwable) { LOGGER.log(Level.WARNING, "Unable to fetch a list of FeatureType names from datastore.", throwable); ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("error.exception", throwable.getMessage())); saveErrors(request, errors); return mapping.findForward("config.data.store.editor"); } finally { if(victim != null) victim.dispose(); } boolean enabled = dataStoresForm.isEnabled(); if (dataStoresForm.isEnabledChecked() == false) { enabled = false; } config.setEnabled(enabled); config.setNameSpaceId(namespace); config.setAbstract(description); config.setConnectionParams(paramTexts); dataConfig.addDataStore(config); getUserContainer(request).setDataStoreConfig(null); getApplicationState().notifyConfigChanged(); if ((singleFeatureType == null) || !isNewDataStore) { //If there are many featureTypes, then just forward to the normal //spot. return mapping.findForward("config.data.store"); } else { //We only have one featureType, and this is the creation of a new datastore //so we should forward to the editor of this featureType, since this is what //users will be next in the vast majority of the cases. FeatureTypeConfig ftConfig = new FeatureTypeConfig(dataStoreID, singleFeatureType, false); request.getSession().setAttribute(DataConfig.SELECTED_FEATURE_TYPE, ftConfig); request.getSession().removeAttribute(DataConfig.SELECTED_ATTRIBUTE_TYPE); user.setFeatureTypeConfig(ftConfig); return mapping.findForward("config.data.type.editor"); } } /** Used to debug connection parameters */ public void dump(String msg, Map params) { if (msg != null) { System.out.print(msg + " "); } System.out.print(": { "); for (Iterator i = params.entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); System.out.print(entry.getKey()); System.out.print("="); dump(entry.getValue()); if (i.hasNext()) { System.out.print(", "); } } System.out.println("}"); } public void dump(Object obj) { if (obj == null) { System.out.print("null"); } else if (obj instanceof String) { System.out.print("\""); System.out.print(obj); System.out.print("\""); } else { System.out.print(obj); } } public void dump(String msg, Object[] array) { if (msg != null) { System.out.print(msg + " "); } System.out.print(": "); if (array == null) { System.out.print("null"); return; } System.out.print("("); for (int i = 0; i < array.length; i++) { dump(array[i]); if (i < (array.length - 1)) { System.out.print(", "); } } System.out.println(")"); } }