ingo@1805: package de.intevation.flys.artifacts; ingo@1805: ingo@3019: import java.io.File; ingo@3019: ingo@1805: import java.util.ArrayList; ingo@1805: import java.util.List; ingo@1805: ingo@1854: import java.util.regex.Pattern; ingo@1854: import java.util.regex.Matcher; ingo@1854: ingo@1805: import org.w3c.dom.Document; ingo@1805: ingo@1805: import org.apache.log4j.Logger; ingo@1805: ingo@1854: import org.hibernate.impl.SessionFactoryImpl; ingo@1854: ingo@1805: import com.vividsolutions.jts.geom.Envelope; ingo@1805: ingo@1805: import de.intevation.artifacts.Artifact; ingo@1805: import de.intevation.artifacts.ArtifactFactory; ingo@1805: import de.intevation.artifacts.CallMeta; ingo@1805: ingo@3019: import de.intevation.artifacts.common.utils.FileTools; ingo@3019: ingo@1805: import de.intevation.artifactdatabase.data.DefaultStateData; ingo@1805: import de.intevation.artifactdatabase.state.Facet; ingo@1805: import de.intevation.artifactdatabase.state.State; ingo@1805: ingo@1805: ingo@1854: import de.intevation.flys.backend.SessionFactoryProvider; ingo@1854: ingo@2683: import de.intevation.flys.artifacts.resources.Resources; ingo@1805: import de.intevation.flys.artifacts.states.DefaultState; ingo@3302: import de.intevation.flys.artifacts.model.map.WMSDBLayerFacet; ingo@1854: import de.intevation.flys.utils.FLYSUtils; ingo@3019: import de.intevation.flys.utils.MapfileGenerator; ingo@1805: ingo@1805: ingo@1805: public abstract class WMSDBArtifact extends StaticFLYSArtifact { ingo@1805: ingo@1805: private static final Logger logger = Logger.getLogger(WMSDBArtifact.class); ingo@1805: ingo@1854: public static final Pattern DB_URL_PATTERN = ingo@1854: Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z]+)"); sascha@3923: ingo@3918: public static final Pattern DB_PSQL_URL_PATTERN = ingo@3918: Pattern.compile("(.*)\\/\\/(.*):([0-9]+)\\/([a-zA-Z0-9]+)"); ingo@1854: ingo@1805: ingo@1805: @Override ingo@1805: public void setup( ingo@1805: String identifier, ingo@1805: ArtifactFactory factory, ingo@1805: Object context, ingo@1805: CallMeta callMeta, ingo@1805: Document data) ingo@1805: { ingo@1805: logger.debug("WMSDBArtifact.setup"); ingo@1805: ingo@1805: super.setup(identifier, factory, context, callMeta, data); ingo@1805: felix@2741: String ids = getDatacageIDValue(data); ingo@1805: ingo@1805: if (ids != null && ids.length() > 0) { ingo@1805: addData("ids", new DefaultStateData("ids", null, null, ids)); ingo@1805: } ingo@1805: else { ingo@1805: throw new IllegalArgumentException("No attribute 'ids' found!"); ingo@1805: } ingo@1805: ingo@1805: List fs = new ArrayList(); ingo@1805: ingo@1805: WMSDBState state = (WMSDBState) getCurrentState(context); ingo@1805: state.computeInit(this, hash(), context, callMeta, fs); ingo@1805: ingo@1805: if (!fs.isEmpty()) { ingo@1805: facets.put(getCurrentStateId(), fs); ingo@1805: } ingo@1805: } ingo@1805: ingo@1805: ingo@1805: @Override ingo@1805: protected void initialize( ingo@1805: Artifact artifact, ingo@1805: Object context, ingo@1805: CallMeta callMeta) ingo@1805: { ingo@1805: // do nothing ingo@1805: } ingo@1805: ingo@1805: ingo@3019: @Override ingo@3019: protected State getState(Object context, String stateID) { ingo@3019: return getCurrentState(context); ingo@3019: } ingo@3019: ingo@3019: ingo@1805: /** ingo@1805: * Get a list containing the one and only State. ingo@1805: * @param context ignored. ingo@1805: * @return list with one and only state. ingo@1805: */ ingo@1805: @Override ingo@1805: protected List getStates(Object context) { ingo@1805: ArrayList states = new ArrayList(); ingo@1805: states.add(getCurrentState(context)); ingo@1805: ingo@1805: return states; ingo@1805: } ingo@1805: ingo@1805: ingo@1805: ingo@1805: public static abstract class WMSDBState extends DefaultState { ingo@1805: private static final Logger logger = Logger.getLogger(WMSDBState.class); ingo@1805: raimund@2089: protected FLYSArtifact artifact; ingo@1805: ingo@2672: protected String name; ingo@2683: protected int riverId; ingo@2672: ingo@2672: raimund@2082: public WMSDBState() {} raimund@2082: raimund@2089: public WMSDBState(FLYSArtifact artifact) { ingo@1805: this.artifact = artifact; ingo@2672: this.name = null; ingo@2683: this.riverId = 0; ingo@1805: } ingo@1805: ingo@1805: @Override ingo@1805: public Object computeInit( ingo@1805: FLYSArtifact artifact, ingo@1805: String hash, ingo@1805: Object context, ingo@1805: CallMeta meta, ingo@1805: List facets ingo@1805: ) { ingo@1805: logger.debug("WMSDBState.computeInit"); ingo@1805: ingo@1805: String type = getFacetType(); ingo@1805: ingo@1805: WMSDBLayerFacet facet = new WMSDBLayerFacet( ingo@1805: 0, ingo@1805: type, ingo@1805: getTitle(meta), ingo@1805: ComputeType.INIT, ingo@1805: getID(), hash, ingo@1805: getUrl()); ingo@1805: ingo@1917: String name = type + "-" + artifact.identifier(); ingo@1805: ingo@1805: facet.addLayer(name); ingo@1805: facet.setExtent(getExtent()); ingo@3918: facet.setOriginalExtent(getExtent(true)); ingo@1805: facet.setSrid(getSrid()); ingo@1805: facet.setData(getDataString()); ingo@1805: facet.setFilter(getFilter()); ingo@1816: facet.setGeometryType(getGeometryType()); ingo@1854: facet.setConnection(getConnection()); ingo@1854: facet.setConnectionType(getConnectionType()); ingo@1876: facet.setLabelItem(getLabelItem()); ingo@1805: ingo@1805: facets.add(facet); ingo@1805: ingo@1805: return null; ingo@1805: } ingo@1805: ingo@1854: /** ingo@1854: * This method returns a connection string for databases used by ingo@1854: * Mapserver's Mapfile. ingo@1854: * ingo@1854: * @return A connection string for Mapserver. ingo@1854: */ ingo@1854: protected String getConnection() { ingo@1854: SessionFactoryImpl sf = (SessionFactoryImpl) ingo@1854: SessionFactoryProvider.getSessionFactory(); ingo@1854: ingo@1854: String user = SessionFactoryProvider.getUser(sf); ingo@1854: String pass = SessionFactoryProvider.getPass(sf); ingo@1854: String url = SessionFactoryProvider.getURL(sf); ingo@1854: ingo@1854: logger.debug("Parse connection url: " + url); ingo@1854: ingo@1854: Matcher m = DB_URL_PATTERN.matcher(url); ingo@1854: if (!m.matches()) { ingo@3918: logger.warn("Could not parse Connection string." + ingo@3918: "Try to parse PostgreSQL string."); ingo@3918: // maybe this is a PostgreSQL connection... ingo@3918: return getPostgreSQLConnection(); ingo@1854: } ingo@1854: ingo@1854: logger.debug("Groups for connection string: " + m.groupCount()); ingo@1854: int groups = m.groupCount(); ingo@1854: sascha@3087: for (int i = 0; i <= groups; i++) { ingo@1854: logger.debug("Group " + i + ": " + m.group(i)); ingo@1854: } ingo@1854: ingo@1854: String connection = null; ingo@1854: ingo@1854: if (FLYSUtils.isUsingOracle()) { ingo@1854: if (groups < 3) { ingo@1854: logger.warn("Could only partially parse connection string."); ingo@1854: return null; ingo@1854: } ingo@1854: ingo@1854: String host = m.group(2); ingo@1854: String port = m.group(3); ingo@1854: ingo@1854: connection = user + "/" + pass + "@" + host; ingo@1854: } ingo@1854: else { ingo@1854: if (groups < 4) { ingo@1854: logger.warn("Could only partially parse connection string."); ingo@1854: return null; ingo@1854: } ingo@1854: ingo@1854: String host = m.group(2); ingo@1854: String port = m.group(3); ingo@1854: String db = m.group(4); ingo@1854: ingo@1854: StringBuilder sb = new StringBuilder(); ingo@1854: sb.append("dbname=" + db); ingo@1854: sb.append("host='" + host + "'"); ingo@1854: sb.append("port=" + port); ingo@1854: sb.append("password='" + pass + "'"); ingo@1854: sb.append("sslmode=disable"); ingo@1854: ingo@1854: connection = sb.toString(); ingo@1854: } ingo@1854: ingo@1854: logger.debug("Created connection: '" + connection + "'"); ingo@1854: ingo@1854: return connection; ingo@1854: } sascha@3923: ingo@3918: protected String getPostgreSQLConnection() { ingo@3918: SessionFactoryImpl sf = (SessionFactoryImpl) ingo@3918: SessionFactoryProvider.getSessionFactory(); sascha@3923: ingo@3918: String user = SessionFactoryProvider.getUser(sf); ingo@3918: String pass = SessionFactoryProvider.getPass(sf); ingo@3918: String url = SessionFactoryProvider.getURL(sf); sascha@3923: ingo@3918: Matcher m = DB_PSQL_URL_PATTERN.matcher(url); ingo@3918: if (!m.matches()) { ingo@3918: logger.warn("Could not parse PostgreSQL Connection string."); ingo@3918: return null; ingo@3918: } ingo@3918: ingo@3918: int groups = m.groupCount(); ingo@3918: logger.debug("Groups for PostgreSQL connection string: " + groups); ingo@3918: ingo@3918: if (logger.isDebugEnabled()) { ingo@3918: for (int i = 0; i <= groups; i++) { ingo@3918: logger.debug("Group " + i + ": " + m.group(i)); ingo@3918: } ingo@3918: } ingo@3918: ingo@3918: String connection = null; ingo@3918: ingo@3918: if (groups < 4) { ingo@3918: logger.warn("Could only partially parse connection string."); ingo@3918: return null; ingo@3918: } ingo@3918: ingo@3918: String host = m.group(2); ingo@3918: String port = m.group(3); ingo@3918: String db = m.group(4); ingo@3918: ingo@3918: StringBuilder sb = new StringBuilder(); ingo@3918: sb.append("dbname=" + db); ingo@3918: sb.append(" host='" + host + "'"); ingo@3918: sb.append(" port=" + port); ingo@3918: sb.append(" user=" + user); ingo@3918: sb.append(" password='" + pass + "'"); ingo@3918: sb.append(" sslmode=disable"); ingo@3918: ingo@3918: connection = sb.toString(); ingo@3918: ingo@3918: logger.debug("Created connection: '" + connection + "'"); ingo@3918: ingo@3918: return connection; ingo@3918: } ingo@1854: ingo@1854: protected String getConnectionType() { ingo@1854: return FLYSUtils.isUsingOracle() ? "oraclespatial" : "postgis"; ingo@1854: } ingo@1854: ingo@1876: protected String getLabelItem() { ingo@1876: return null; ingo@1876: } ingo@1876: ingo@2683: public int getRiverId() { ingo@2683: if (riverId == 0) { ingo@2683: String ids = artifact.getDataAsString("ids"); ingo@2683: String[] parts = ids.split(";"); ingo@2683: ingo@2683: try { sascha@3405: riverId = Integer.parseInt(parts[0]); ingo@2683: } ingo@2683: catch (NumberFormatException nfe) { ingo@2683: logger.error("Cannot parse river id from '" + parts[0] + "'"); ingo@2683: } ingo@2683: } ingo@2683: ingo@2683: return riverId; ingo@2683: } ingo@2683: ingo@2672: /** ingo@2672: * Returns the name of the WMS layer. This method extracts the name ingo@2672: * from 'ids' data string. It is expected, that the 'ids' string is ingo@2672: * seperated by ';' and that the name is placed at index 1. ingo@2672: * ingo@2672: * @return the name of the WMS layer. ingo@2672: */ ingo@2672: public String getName() { ingo@2672: if (name == null) { ingo@2672: String ids = artifact.getDataAsString("ids"); ingo@2672: ingo@2683: String parts[] = ids != null ? ids.split(";") : null; ingo@2683: ingo@2683: if (parts != null && parts.length >= 2) { ingo@2683: name = parts[1]; ingo@2683: } ingo@2672: } ingo@2672: ingo@2672: return name; ingo@2672: } ingo@2672: ingo@2683: ingo@2683: /** ingo@2683: * Returns the name of the layer (returned by getName()) or the layer ingo@2683: * type if the name is empty. The layer type is created by an i18n ingo@2683: * string of getFacetType(). ingo@2683: * ingo@2683: * @param meta A CallMeta used for i18n. ingo@2683: * ingo@2683: * @return the name of the layer or its type if name is empty. ingo@2683: */ ingo@2683: protected String getTitle(CallMeta meta) { ingo@2683: String name = getName(); ingo@2683: ingo@2683: return name != null && name.length() > 0 ingo@2683: ? name ingo@2683: : Resources.getMsg( ingo@2683: meta, ingo@2683: getFacetType(), ingo@2683: getFacetType()); ingo@2683: } ingo@2683: ingo@2683: ingo@3019: @Override ingo@3019: public void endOfLife(Artifact owner, Object context) { ingo@3019: logger.info("Destroy WMSDBState: " + getID()); ingo@3019: ingo@3019: String p = FLYSUtils.getXPathString(FLYSUtils.XPATH_SHAPEFILE_DIR); ingo@3019: File dir = new File(p, owner.identifier()); ingo@3019: ingo@3019: if (dir != null && dir.exists()) { ingo@3019: logger.debug("Try to delete directory '" + dir + "'"); ingo@3019: ingo@3019: FileTools.deleteRecursive(dir); ingo@3019: MapfileGenerator.getInstance().update(); ingo@3019: } ingo@3019: } sascha@3923: ingo@3918: /** ingo@3918: * This method returns the extent of a DB layer in the projection of the ingo@3918: * database. sascha@3923: * ingo@3918: * @return the extent of the DB layer in the projection of the database. ingo@3918: */ ingo@3918: protected Envelope getExtent() { ingo@3918: return getExtent(false); ingo@3918: } ingo@3019: ingo@3019: ingo@1805: protected abstract String getFacetType(); ingo@1805: ingo@1805: protected abstract String getUrl(); ingo@1805: ingo@1805: protected abstract String getSrid(); ingo@1805: ingo@3918: /** ingo@3918: * This method returns the extent of the DB layer. The projection of the ingo@3918: * extent depends on the reproject parameter. If reproject is set, ingo@3918: * the extent is reprojected into the original projection which is ingo@3918: * specified in the configuration. Otherwise, the projection of the ingo@3918: * database is used. sascha@3923: * ingo@3918: * @param reproject True, to reproject the extent into the projection ingo@3918: * specified in the configuration. sascha@3923: * ingo@3918: * @return the extent of the database layer. ingo@3918: */ ingo@3918: protected abstract Envelope getExtent(boolean reproject); ingo@1805: ingo@1805: protected abstract String getFilter(); ingo@1805: ingo@1805: protected abstract String getDataString(); ingo@1816: ingo@1816: protected abstract String getGeometryType(); ingo@1805: } // end of WMSDBState ingo@1805: } ingo@1805: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :