changeset 4918:4a9a1e323e11 fairway-marks-import

First version of geo styles in ZIP files.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 13 Feb 2020 18:23:58 +0100
parents 0098cfd602be
children 399458e60a9b
files pkg/controllers/geostyling.go pkg/geoserver/boot.go pkg/models/intservices.go schema/updates/1317/01.migrate_styles.sql schema/version.sql
diffstat 5 files changed, 41 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/geostyling.go	Thu Feb 13 11:37:22 2020 +0100
+++ b/pkg/controllers/geostyling.go	Thu Feb 13 18:23:58 2020 +0100
@@ -31,20 +31,20 @@
 	styleName    = "style"
 )
 
-func extractStyle(req *http.Request) (string, error) {
+func extractStyle(req *http.Request) ([]byte, error) {
 
 	f, _, err := req.FormFile(styleName)
 	if err != nil {
-		return "", err
+		return nil, err
 	}
 	defer f.Close()
 
 	var buf bytes.Buffer
 
 	if _, err := io.Copy(&buf, io.LimitReader(f, maxStyleSize)); err != nil {
-		return "", err
+		return nil, err
 	}
-	return buf.String(), nil
+	return buf.Bytes(), nil
 }
 
 func supportedWMSFeature(name string) bool {
--- a/pkg/geoserver/boot.go	Thu Feb 13 11:37:22 2020 +0100
+++ b/pkg/geoserver/boot.go	Thu Feb 13 18:23:58 2020 +0100
@@ -14,6 +14,7 @@
 package geoserver
 
 import (
+	"archive/zip"
 	"bytes"
 	"encoding/json"
 	"encoding/xml"
@@ -478,20 +479,34 @@
 	return stylePreprocessors[name]
 }
 
+func isZip(data []byte) bool {
+	if len(data) == 0 {
+		return false
+	}
+	_, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
+	return err == nil
+}
+
 func updateStyle(entry *models.IntEntry, create bool) error {
 
 	log.Printf("info: creating style %s\n", entry.Name)
 
 	// Try to load the style data.
-	data, err := entry.LoadStyle()
+	binary, err := entry.LoadStyle()
 	if err != nil {
 		return err
 	}
 
-	if processor := FindStylePreprocessor(entry.Name); processor != nil {
-		if data, err = processor(data); err != nil {
-			return err
+	zip := isZip(binary)
+
+	if !zip { // We only support templating for plain XML styles.
+		data := string(binary)
+		if processor := FindStylePreprocessor(entry.Name); processor != nil {
+			if data, err = processor(data); err != nil {
+				return err
+			}
 		}
+		binary = []byte(data)
 	}
 
 	var (
@@ -548,14 +563,17 @@
 	req, err := http.NewRequest(
 		http.MethodPut,
 		styleURL+"/"+url.PathEscape(entry.Name),
-		strings.NewReader(data))
+		bytes.NewReader(binary))
 	if err != nil {
 		return err
 	}
 	auth(req)
-	if isSymbologyEncoding(data) {
+	switch {
+	case zip:
+		asContentType(req, "application/zip")
+	case isSymbologyEncoding(binary):
 		asContentType(req, "application/vnd.ogc.se+xml")
-	} else {
+	default:
 		asContentType(req, "application/vnd.ogc.sld+xml")
 	}
 	resp, err := http.DefaultClient.Do(req)
@@ -596,8 +614,8 @@
 }
 
 // isSymbologyEncoding tries to figure out if its plain SLD or SE.
-func isSymbologyEncoding(data string) bool {
-	decoder := xml.NewDecoder(strings.NewReader(data))
+func isSymbologyEncoding(data []byte) bool {
+	decoder := xml.NewDecoder(bytes.NewReader(data))
 	decoder.CharsetReader = charset.NewReaderLabel
 
 	for {
--- a/pkg/models/intservices.go	Thu Feb 13 11:37:22 2020 +0100
+++ b/pkg/models/intservices.go	Thu Feb 13 18:23:58 2020 +0100
@@ -54,20 +54,20 @@
 ORDER by name`
 
 	selectStyleSQL = `
-SELECT XMLSERIALIZE(DOCUMENT style AS text)
+SELECT style
 FROM sys_admin.published_services
 WHERE name = $1 AND schema = $2`
 
 	updateStyleSQL = `
 UPDATE sys_admin.published_services
-SET style = XMLPARSE(DOCUMENT $1)
+SET style = $1
 WHERE name = $2 AND schema = $3`
 )
 
 var InternalServices = &IntServices{}
 
-func (e *IntEntry) LoadStyle() (string, error) {
-	var style string
+func (e *IntEntry) LoadStyle() ([]byte, error) {
+	var style []byte
 	ctx := context.Background()
 	err := auth.RunAs(ctx, "sys_admin",
 		func(conn *sql.Conn) error {
@@ -79,7 +79,7 @@
 	return style, err
 }
 
-func UpdateInternalStyle(req *http.Request, name, style string) error {
+func UpdateInternalStyle(req *http.Request, name string, style []byte) error {
 	return auth.RunAsSessionUser(req, func(conn *sql.Conn) error {
 		_, err := conn.ExecContext(
 			req.Context(), updateStyleSQL,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/schema/updates/1317/01.migrate_styles.sql	Thu Feb 13 18:23:58 2020 +0100
@@ -0,0 +1,4 @@
+ALTER TABLE sys_admin.published_services ADD COLUMN bin_blob bytea;
+UPDATE sys_admin.published_services SET bin_blob = style::text::bytea WHERE style is NOT NULL;
+ALTER TABLE sys_admin.published_services DROP COLUMN style;
+ALTER TABLE sys_admin.published_services RENAME COLUMN bin_blob TO style;
--- a/schema/version.sql	Thu Feb 13 11:37:22 2020 +0100
+++ b/schema/version.sql	Thu Feb 13 18:23:58 2020 +0100
@@ -1,1 +1,1 @@
-INSERT INTO gemma_schema_version(version) VALUES (1316);
+INSERT INTO gemma_schema_version(version) VALUES (1317);