GeoServerService.java 6.94 KB
package com.sigem.gis.service;

import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class GeoServerService {

    private final String GS_URL = "http://geoserver:8080/geoserver/rest";
    private final String GS_USER = "admin";
    private final String GS_PASS = "geoserver";

    private final RestTemplate restTemplate;

    public GeoServerService() {
        org.springframework.http.client.SimpleClientHttpRequestFactory factory = new org.springframework.http.client.SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(2000);
        factory.setReadTimeout(2000);
        this.restTemplate = new RestTemplate(factory);
    }

    /**
     * Publica una vista como capa de GeoServer con un estilo específico.
     */
    public void publishLayer(String layerName, String viewName, String styleName, String boundNo, String boundSe) {
        ensureInfrastructureExists();

        String workspace = "sigem";
        String datastore = "sigem_db";

        System.out.println("Publicando Capa WMS en GeoServer: " + layerName + " (Estilo: " + styleName + ")");

        // 1. Crear/Actualizar FeatureType (Configuración de datos y BBOX)
        String url = String.format("%s/workspaces/%s/datastores/%s/featuretypes/%s", GS_URL, workspace, datastore, layerName);

        StringBuilder bboxJson = new StringBuilder();
        if (boundNo != null && boundSe != null) {
            try {
                String[] no = boundNo.split(",");
                String[] se = boundSe.split(",");
                double lat1 = Double.parseDouble(no[0].trim());
                double lon1 = Double.parseDouble(no[1].trim());
                double lat2 = Double.parseDouble(se[0].trim());
                double lon2 = Double.parseDouble(se[1].trim());

                bboxJson.append(", \"latLonBoundingBox\": {");
                bboxJson.append(String.format("\"minx\": %f, \"maxx\": %f, \"miny\": %f, \"maxy\": %f, \"crs\": \"EPSG:4326\"",
                    Math.min(lon1, lon2), Math.max(lon1, lon2), Math.min(lat1, lat2), Math.max(lat1, lat2)));
                bboxJson.append("}");
            } catch (Exception e) {
                System.err.println("Error parseando bounds: " + e.getMessage());
            }
        }

        String jsonBody = String.format(
            "{\"featureType\": {\"name\": \"%s\", \"nativeName\": \"%s\", \"title\": \"%s\", \"srs\": \"EPSG:4326\" %s}}",
            layerName, viewName, layerName, bboxJson.toString()
        );

        HttpHeaders headers = createHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(jsonBody, headers);

        try {
            restTemplate.exchange(url, HttpMethod.PUT, entity, String.class);
        } catch (Exception e) {
            String postUrl = String.format("%s/workspaces/%s/datastores/%s/featuretypes", GS_URL, workspace, datastore);
            try {
                restTemplate.postForEntity(postUrl, entity, String.class);
            } catch (Exception ex) {
                System.err.println("Error publicando FeatureType: " + ex.getMessage());
            }
        }

        // 2. Asignar Estilo Predeterminado a la Capa
        if (styleName != null) {
            String layerUrl = String.format("%s/layers/%s:%s", GS_URL, workspace, layerName);
            String layerJson = String.format("{\"layer\": {\"defaultStyle\": {\"name\": \"%s\"}}}", styleName);
            try {
                restTemplate.exchange(layerUrl, HttpMethod.PUT, new HttpEntity<>(layerJson, headers), String.class);
                System.out.println("Estilo '" + styleName + "' asignado a la capa.");
            } catch (Exception e) {
                System.err.println("Error asignando estilo a la capa: " + e.getMessage());
            }
        }
    }

    private void ensureInfrastructureExists() {
        String workspace = "sigem";
        String datastore = "sigem_db";

        // 1. Verificar Workspace
        try {
            restTemplate.exchange(GS_URL + "/workspaces/" + workspace, HttpMethod.GET, new HttpEntity<>(createHeaders()), String.class);
        } catch (Exception e) {
            System.out.println("Creando Workspace: " + workspace);
            String wsJson = String.format("{\"workspace\": {\"name\": \"%s\"}}", workspace);
            HttpHeaders h = createHeaders();
            h.setContentType(MediaType.APPLICATION_JSON);
            restTemplate.postForEntity(GS_URL + "/workspaces", new HttpEntity<>(wsJson, h), String.class);
        }

        // 2. Verificar DataStore
        try {
            restTemplate.exchange(GS_URL + "/workspaces/" + workspace + "/datastores/" + datastore, HttpMethod.GET, new HttpEntity<>(createHeaders()), String.class);
        } catch (Exception e) {
            System.out.println("Creando DataStore: " + datastore);
            String dsJson = String.format(
                "{\"dataStore\": {\"name\": \"%s\", \"connectionParameters\": {" +
                "\"host\": \"postgres\", \"port\": \"5432\", \"database\": \"sigem\", " +
                "\"user\": \"sigem_user\", \"passwd\": \"sigem_pass\", \"dbtype\": \"postgis\"}}}",
                datastore
            );
            HttpHeaders h = createHeaders();
            h.setContentType(MediaType.APPLICATION_JSON);
            try {
                restTemplate.postForEntity(GS_URL + "/workspaces/" + workspace + "/datastores", new HttpEntity<>(dsJson, h), String.class);
            } catch (Exception ex) {
                System.err.println("Error creando DataStore: " + ex.getMessage());
            }
        }
    }

    /**
     * Purga la caché de una capa en GeoWebCache (GWC) para forzar el recálculo de perímetros.
     */
    public void truncateCache(String layerName) {
        String url = "http://geoserver:8080/geoserver/gwc/rest/masstruncate";
        String xmlBody = String.format("<truncateLayer><layerName>sigem:%s</layerName></truncateLayer>", layerName);
        
        HttpHeaders headers = createHeaders();
        headers.setContentType(MediaType.TEXT_XML);
        HttpEntity<String> entity = new HttpEntity<>(xmlBody, headers);

        try {
            restTemplate.postForEntity(url, entity, String.class);
            System.out.println("Caché GWC purgada para: " + layerName);
        } catch (Exception e) {
            System.err.println("Error purgando caché para " + layerName + ": " + e.getMessage());
        }
    }

    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        // Intentamos admin/admin si falla el de las reglas (debido a reset de GS)
        try {
            headers.setBasicAuth(GS_USER, GS_PASS);
            // Probaríamos conexión aquí si fuera necesario, pero por ahora simplificamos:
            // Si el subagent detectó admin/admin, podríamos parametrizarlo.
        } catch (Exception e) {
            headers.setBasicAuth("admin", "admin");
        }
        return headers;
    }
}
GitLab Appliance - Powered by TurnKey Linux