From: Mathieu Baudier Date: Wed, 20 Dec 2023 08:01:13 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/unstable' into testing X-Git-Tag: v2.1.32~4 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=32e6fcd7f2607415b3e6be7295756bb0b645ca7a;hp=7116b01025b89de2397b6d25dde926ac04e3e671;p=gpl%2Fargeo-suite.git Merge remote-tracking branch 'origin/unstable' into testing --- diff --git a/org.argeo.app.core/src/org/argeo/app/ux/js/JsClient.java b/org.argeo.app.core/src/org/argeo/app/ux/js/JsClient.java index 2503cf0..708daff 100644 --- a/org.argeo.app.core/src/org/argeo/app/ux/js/JsClient.java +++ b/org.argeo.app.core/src/org/argeo/app/ux/js/JsClient.java @@ -65,7 +65,12 @@ public interface JsClient { } default boolean isInstanceOf(String reference, String jsClass) { - return (Boolean) evaluate("return "+getJsVarName(reference) + " instanceof " + jsClass); + try { + return (Boolean) evaluate("return " + getJsVarName(reference) + " instanceof " + jsClass); + } catch (Exception e) { + // TODO better understand why instanceof is often failing with SWT Browser + return false; + } } /* diff --git a/org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java b/org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java index 641c14b..47cae24 100644 --- a/org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java +++ b/org.argeo.app.geo/src/org/argeo/app/geo/http/WfsHttpHandler.java @@ -2,10 +2,8 @@ package org.argeo.app.geo.http; import java.io.BufferedOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; -import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -33,35 +31,22 @@ import org.argeo.app.api.geo.WfsKvp; import org.argeo.app.geo.CqlUtils; import org.argeo.app.geo.GeoJson; import org.argeo.app.geo.GeoUtils; -import org.argeo.app.geo.GpxUtils; -import org.argeo.app.geo.JTS; import org.argeo.app.geo.acr.GeoEntityUtils; import org.argeo.cms.acr.json.AcrJsonUtils; import org.argeo.cms.auth.RemoteAuthUtils; import org.argeo.cms.http.HttpHeader; +import org.argeo.cms.http.HttpStatus; import org.argeo.cms.http.RemoteAuthHttpExchange; import org.argeo.cms.http.server.HttpServerUtils; import org.argeo.cms.util.LangUtils; -import org.geotools.api.feature.GeometryAttribute; -import org.geotools.api.feature.simple.SimpleFeature; -import org.geotools.api.feature.simple.SimpleFeatureType; -import org.geotools.api.feature.type.AttributeDescriptor; -import org.geotools.api.feature.type.Name; import org.geotools.api.referencing.FactoryException; import org.geotools.api.referencing.crs.CoordinateReferenceSystem; import org.geotools.api.referencing.operation.MathTransform; import org.geotools.api.referencing.operation.TransformException; -import org.geotools.feature.DefaultFeatureCollection; -import org.geotools.feature.NameImpl; -import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.referencing.CRS; -import org.geotools.referencing.crs.DefaultGeographicCRS; -import org.geotools.wfs.GML; -import org.geotools.wfs.GML.Version; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.Polygon; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; @@ -78,180 +63,182 @@ public class WfsHttpHandler implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { - ContentSession session = HttpServerUtils.getContentSession(contentRepository, exchange); - - String path = HttpServerUtils.subPath(exchange); - - // content path - final String pathToUse = path; - String fileName = null; - boolean zipped = false; -// int lastSlash = path.lastIndexOf('/'); -// if (lastSlash > 0) { -// fileName = path.substring(lastSlash + 1); -// } -// if (fileName != null) { -// pathToUse = path.substring(0, lastSlash); -// if (path.endsWith(".zip")) { -// zipped = true; -// } -// } else { -// pathToUse = path; -// } - - Map> parameters = HttpServerUtils.parseParameters(exchange); - - // PARAMETERS - String cql = getKvpParameter(parameters, WfsKvp.CQL_FILTER); - String typeNamesStr = getKvpParameter(parameters, WfsKvp.TYPE_NAMES); - String outputFormat = getKvpParameter(parameters, WfsKvp.OUTPUT_FORMAT); - if (outputFormat == null) { - outputFormat = "application/json"; - } + try { + ContentSession session = HttpServerUtils.getContentSession(contentRepository, exchange); - // TODO deal with multiple - String formatOption = getKvpParameter(parameters, WfsKvp.FORMAT_OPTIONS); - if (formatOption != null) { - if (formatOption.startsWith(WfsKvp.FILENAME_)) - fileName = formatOption.substring(WfsKvp.FILENAME_.length()); - } - if (fileName != null && fileName.endsWith(".zip")) - zipped = true; + String path = HttpServerUtils.subPath(exchange); - // bbox - String bboxStr = getKvpParameter(parameters, WfsKvp.BBOX); - if (log.isTraceEnabled()) - log.trace(bboxStr); - final Envelope bbox; - if (bboxStr != null) { - String srs; - String[] arr = bboxStr.split(","); - // TODO check SRS and convert to WGS84 - double minLat = Double.parseDouble(arr[0]); - double minLon = Double.parseDouble(arr[1]); - double maxLat = Double.parseDouble(arr[2]); - double maxLon = Double.parseDouble(arr[3]); - if (arr.length == 5) { - srs = arr[4]; - } else { - srs = null; + // content path + final String pathToUse = path; + String fileName = null; + boolean zipped = false; + + Map> parameters = HttpServerUtils.parseParameters(exchange); + + // PARAMETERS + String cql = getKvpParameter(parameters, WfsKvp.CQL_FILTER); + String typeNamesStr = getKvpParameter(parameters, WfsKvp.TYPE_NAMES); + String outputFormat = getKvpParameter(parameters, WfsKvp.OUTPUT_FORMAT); + if (outputFormat == null) { + outputFormat = "application/json"; } - if (srs != null && !srs.equals(GeoUtils.EPSG_4326)) { - try { - // TODO optimise - CoordinateReferenceSystem sourceCRS = CRS.decode(srs); - CoordinateReferenceSystem targetCRS = CRS.decode(GeoUtils.EPSG_4326); - MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true); - bbox = org.geotools.geometry.jts.JTS.transform( - new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon)), transform); - } catch (FactoryException | TransformException e) { - throw new IllegalArgumentException("Cannot convert bounding box", e); - // bbox = null; + // TODO deal with multiple + String formatOption = getKvpParameter(parameters, WfsKvp.FORMAT_OPTIONS); + if (formatOption != null) { + if (formatOption.startsWith(WfsKvp.FILENAME_)) + fileName = formatOption.substring(WfsKvp.FILENAME_.length()); + } + if (fileName != null && fileName.endsWith(".zip")) + zipped = true; + + // bbox + String bboxStr = getKvpParameter(parameters, WfsKvp.BBOX); + if (log.isTraceEnabled()) + log.trace(bboxStr); + final Envelope bbox; + if (bboxStr != null) { + String srs; + String[] arr = bboxStr.split(","); + // TODO check SRS and convert to WGS84 + double minLat = Double.parseDouble(arr[0]); + double minLon = Double.parseDouble(arr[1]); + double maxLat = Double.parseDouble(arr[2]); + double maxLon = Double.parseDouble(arr[3]); + if (arr.length == 5) { + srs = arr[4]; + } else { + srs = null; + } + + if (srs != null && !srs.equals(GeoUtils.EPSG_4326)) { + try { + // TODO optimise + CoordinateReferenceSystem sourceCRS = CRS.decode(srs); + CoordinateReferenceSystem targetCRS = CRS.decode(GeoUtils.EPSG_4326); + MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS, true); + bbox = org.geotools.geometry.jts.JTS.transform( + new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon)), + transform); + } catch (FactoryException | TransformException e) { + throw new IllegalArgumentException("Cannot convert bounding box", e); + // bbox = null; + } + } else { + bbox = new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon)); } } else { - bbox = new Envelope(new Coordinate(minLat, minLon), new Coordinate(maxLat, maxLon)); + bbox = null; } - } else { - bbox = null; - } - // response headers - exchange.getResponseHeaders().set(HttpHeader.DATE.getHeaderName(), Long.toString(System.currentTimeMillis())); + // response headers + exchange.getResponseHeaders().set(HttpHeader.DATE.getHeaderName(), + Long.toString(System.currentTimeMillis())); - if (fileName != null) { - exchange.getResponseHeaders().set(HttpHeader.CONTENT_DISPOSITION.getHeaderName(), - HttpHeader.ATTACHMENT + ";" + HttpHeader.FILENAME + "=\"" + fileName + "\""); + if (fileName != null) { + exchange.getResponseHeaders().set(HttpHeader.CONTENT_DISPOSITION.getHeaderName(), + HttpHeader.ATTACHMENT + ";" + HttpHeader.FILENAME + "=\"" + fileName + "\""); - } + } - // content type - if (zipped) { - exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/zip"); + // content type + if (zipped) { + exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/zip"); - } else { - switch (outputFormat) { - case "application/json" -> { - exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/json"); - } - case "GML3" -> { + } else { + switch (outputFormat) { + case "application/json" -> { + exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/json"); + } + case "GML3" -> { // exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/gml+xml"); - exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/xml"); - } + exchange.getResponseHeaders().set(HttpHeader.CONTENT_TYPE.getHeaderName(), "application/xml"); + } - default -> throw new IllegalArgumentException("Unexpected value: " + outputFormat); + default -> throw new IllegalArgumentException("Unexpected value: " + outputFormat); + } } - } - List typeNames = new ArrayList<>(); - if (typeNamesStr != null) { - String[] arr = typeNamesStr.split(","); - for (int i = 0; i < arr.length; i++) { - typeNames.add(NamespaceUtils.parsePrefixedName(arr[i])); + List typeNames = new ArrayList<>(); + if (typeNamesStr != null) { + String[] arr = typeNamesStr.split(","); + for (int i = 0; i < arr.length; i++) { + typeNames.add(NamespaceUtils.parsePrefixedName(arr[i])); + } + } else { + typeNames.add(EntityType.local.qName()); } - } else { - typeNames.add(EntityType.local.qName()); - } - if (typeNames.size() > 1) - throw new UnsupportedOperationException("Only one type name is currently supported"); + if (typeNames.size() > 1) + throw new UnsupportedOperationException("Only one type name is currently supported"); - // QUERY - Stream res = session.search((search) -> { - if (cql != null) { - CqlUtils.filter(search.from(pathToUse), cql); - } else { - search.from(pathToUse); - } - for (QName typeName : typeNames) { - FeatureAdapter featureAdapter = featureAdapters.get(typeName); - if (featureAdapter == null) - throw new IllegalStateException("No feature adapter found for " + typeName); - // f.isContentClass(typeName); - RemoteAuthUtils.doAs(() -> { - featureAdapter.addConstraintsForFeature((AndFilter) search.getWhere(), typeName); - return null; - }, new RemoteAuthHttpExchange(exchange)); - } + // QUERY + Stream res = session.search((search) -> { + if (cql != null) { + CqlUtils.filter(search.from(pathToUse), cql); + } else { + search.from(pathToUse); + } + for (QName typeName : typeNames) { + FeatureAdapter featureAdapter = featureAdapters.get(typeName); + if (featureAdapter == null) + throw new IllegalStateException("No feature adapter found for " + typeName); + // f.isContentClass(typeName); + RemoteAuthUtils.doAs(() -> { + featureAdapter.addConstraintsForFeature((AndFilter) search.getWhere(), typeName); + return null; + }, new RemoteAuthHttpExchange(exchange)); + } - if (bbox != null) { - search.getWhere().any((or) -> { - // box overlap, see - // https://stackoverflow.com/questions/20925818/algorithm-to-check-if-two-boxes-overlap - // isOverlapping = (x1min < x2max AND x2min < x1max AND y1min < y2max AND y2min - // < y1max) - // x1 = entity, x2 = bbox - or.all((and) -> { - and.lte(EntityName.minLat, bbox.getMaxX()); - and.gte(EntityName.maxLat, bbox.getMinX()); - and.lte(EntityName.minLon, bbox.getMaxY()); - and.gte(EntityName.maxLon, bbox.getMinY()); + if (bbox != null) { + search.getWhere().any((or) -> { + // box overlap, see + // https://stackoverflow.com/questions/20925818/algorithm-to-check-if-two-boxes-overlap + // isOverlapping = (x1min < x2max AND x2min < x1max AND y1min < y2max AND y2min + // < y1max) + // x1 = entity, x2 = bbox + or.all((and) -> { + and.lte(EntityName.minLat, bbox.getMaxX()); + and.gte(EntityName.maxLat, bbox.getMinX()); + and.lte(EntityName.minLon, bbox.getMaxY()); + and.gte(EntityName.maxLon, bbox.getMinY()); + }); + or.all((and) -> { + and.gte(WGS84PosName.lat, bbox.getMinX()); + and.gte(WGS84PosName.lon, bbox.getMinY()); + and.lte(WGS84PosName.lat, bbox.getMaxX()); + and.lte(WGS84PosName.lon, bbox.getMaxY()); + }); }); - or.all((and) -> { - and.gte(WGS84PosName.lat, bbox.getMinX()); - and.gte(WGS84PosName.lon, bbox.getMinY()); - and.lte(WGS84PosName.lat, bbox.getMaxX()); - and.lte(WGS84PosName.lon, bbox.getMaxY()); - }); - }); - } - }); + } + }); - exchange.sendResponseHeaders(200, 0); + exchange.sendResponseHeaders(HttpStatus.OK.getCode(), 0); - final int BUFFER_SIZE = 100 * 1024; - try (OutputStream out = zipped ? new ZipOutputStream(exchange.getResponseBody()) - : new BufferedOutputStream(exchange.getResponseBody(), BUFFER_SIZE)) { - if (out instanceof ZipOutputStream zipOut) { - String unzippedFileName = fileName.substring(0, fileName.length() - ".zip".length()); - zipOut.putNextEntry(new ZipEntry(unzippedFileName)); - } + final int BUFFER_SIZE = 100 * 1024; + try (OutputStream out = zipped ? new ZipOutputStream(exchange.getResponseBody()) + : new BufferedOutputStream(exchange.getResponseBody(), BUFFER_SIZE)) { + if (out instanceof ZipOutputStream zipOut) { + String unzippedFileName = fileName.substring(0, fileName.length() - ".zip".length()); + zipOut.putNextEntry(new ZipEntry(unzippedFileName)); + } - if ("GML3".equals(outputFormat)) { - encodeCollectionAsGML(res, out); - } else if ("application/json".equals(outputFormat)) { - encodeCollectionAsGeoJSon(res, out, typeNames); + if ("GML3".equals(outputFormat)) { + throw new UnsupportedOperationException(); +// encodeCollectionAsGML(res, out); + } else if ("application/json".equals(outputFormat)) { + encodeCollectionAsGeoJSon(res, out, typeNames); + } + } + } catch (Exception e) { + log.error("Cannot process WFS request " + exchange, e); + try { + exchange.sendResponseHeaders(HttpStatus.INTERNAL_SERVER_ERROR.getCode(), -1); + } catch (IOException e1) { + // silent } + if (e instanceof IOException) + throw (IOException) e; } } @@ -306,29 +293,6 @@ public class WfsHttpHandler implements HttpHandler { } boolean geometryWritten = false; -// if (typeName.getLocalPart().equals("fieldSimpleFeature")) { -// Content area = c.getContent("place.geom.json").orElse(null); -// if (area != null) { -// generator.writeStartObject(); -// generator.write("type", "Feature"); -// String featureId = getFeatureId(c); -// if (featureId != null) -// generator.write("id", featureId); -// -// generator.flush(); -// try (InputStream in = area.open(InputStream.class)) { -// out.write(",\"geometry\":".getBytes()); -// StreamUtils.copy(in, out); -// //out.flush(); -// } catch (Exception e) { -// log.error(c.getPath() + " : " + e.getMessage()); -// } finally { -// } -// geometryWritten = true; -// }else { -// return; -// } -// } if (!geometryWritten) { @@ -398,82 +362,82 @@ public class WfsHttpHandler implements HttpHandler { } - protected void encodeCollectionAsGML(Stream features, OutputStream out) throws IOException { - String entityType = "entity"; - URL schemaLocation = getClass().getResource("/org/argeo/app/api/entity.xsd"); - String namespace = "http://www.argeo.org/ns/entity"; - - GML gml = new GML(Version.WFS1_1); - gml.setCoordinateReferenceSystem(DefaultGeographicCRS.WGS84); - gml.setNamespace("local", namespace); - - SimpleFeatureType featureType = gml.decodeSimpleFeatureType(schemaLocation, - new NameImpl(namespace, entityType + "Feature")); - -// CoordinateReferenceSystem crs=DefaultGeographicCRS.WGS84; -// QName featureName = new QName(namespace,"apafFieldFeature"); -// GMLConfiguration configuration = new GMLConfiguration(); -// FeatureType parsed = GTXML.parseFeatureType(configuration, featureName, crs); -// SimpleFeatureType featureType = DataUtilities.simple(parsed); - - SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); - - DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(); - - features.forEach((c) -> { -// boolean gpx = false; - Geometry the_geom = null; - Polygon the_area = null; -// if (gpx) { - Content area = c.getContent("gpx/area.gpx").orElse(null); - if (area != null) { - - try (InputStream in = area.open(InputStream.class)) { - the_area = GpxUtils.parseGpxTrackTo(in, Polygon.class); - } catch (IOException e) { - throw new UncheckedIOException("Cannot parse " + c, e); - } - } -// } else { - if (c.hasContentClass(EntityType.geopoint)) { - double latitude = c.get(WGS84PosName.lat, Double.class).get(); - double longitude = c.get(WGS84PosName.lon, Double.class).get(); - - Coordinate coordinate = new Coordinate(longitude, latitude); - the_geom = JTS.GEOMETRY_FACTORY.createPoint(coordinate); - } - +// protected void encodeCollectionAsGML(Stream features, OutputStream out) throws IOException { +// String entityType = "entity"; +// URL schemaLocation = getClass().getResource("/org/argeo/app/api/entity.xsd"); +// String namespace = "http://www.argeo.org/ns/entity"; +// +// GML gml = new GML(Version.WFS1_1); +// gml.setCoordinateReferenceSystem(DefaultGeographicCRS.WGS84); +// gml.setNamespace("local", namespace); +// +// SimpleFeatureType featureType = gml.decodeSimpleFeatureType(schemaLocation, +// new NameImpl(namespace, entityType + "Feature")); +// +//// CoordinateReferenceSystem crs=DefaultGeographicCRS.WGS84; +//// QName featureName = new QName(namespace,"apafFieldFeature"); +//// GMLConfiguration configuration = new GMLConfiguration(); +//// FeatureType parsed = GTXML.parseFeatureType(configuration, featureName, crs); +//// SimpleFeatureType featureType = DataUtilities.simple(parsed); +// +// SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); +// +// DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(); +// +// features.forEach((c) -> { +//// boolean gpx = false; +// Geometry the_geom = null; +// Polygon the_area = null; +//// if (gpx) { +// Content area = c.getContent("gpx/area.gpx").orElse(null); +// if (area != null) { +// +// try (InputStream in = area.open(InputStream.class)) { +// the_area = GpxUtils.parseGpxTrackTo(in, Polygon.class); +// } catch (IOException e) { +// throw new UncheckedIOException("Cannot parse " + c, e); +// } // } - if (the_geom != null) - featureBuilder.set(new NameImpl(namespace, "geopoint"), the_geom); - if (the_area != null) - featureBuilder.set(new NameImpl(namespace, "area"), the_area); - - List attrDescs = featureType.getAttributeDescriptors(); - for (AttributeDescriptor attrDesc : attrDescs) { - if (attrDesc instanceof GeometryAttribute) - continue; - Name name = attrDesc.getName(); - QName qName = new QName(name.getNamespaceURI(), name.getLocalPart()); - String value = c.attr(qName); - if (value == null) { - value = c.attr(name.getLocalPart()); - } - if (value != null) { - featureBuilder.set(name, value); - } - } - - String uuid = c.attr(LdapAttr.entryUUID); - - SimpleFeature feature = featureBuilder.buildFeature(uuid); - featureCollection.add(feature); - - }); - gml.encode(out, featureCollection); - out.close(); - - } +//// } else { +// if (c.hasContentClass(EntityType.geopoint)) { +// double latitude = c.get(WGS84PosName.lat, Double.class).get(); +// double longitude = c.get(WGS84PosName.lon, Double.class).get(); +// +// Coordinate coordinate = new Coordinate(longitude, latitude); +// the_geom = JTS.GEOMETRY_FACTORY.createPoint(coordinate); +// } +// +//// } +// if (the_geom != null) +// featureBuilder.set(new NameImpl(namespace, "geopoint"), the_geom); +// if (the_area != null) +// featureBuilder.set(new NameImpl(namespace, "area"), the_area); +// +// List attrDescs = featureType.getAttributeDescriptors(); +// for (AttributeDescriptor attrDesc : attrDescs) { +// if (attrDesc instanceof GeometryAttribute) +// continue; +// Name name = attrDesc.getName(); +// QName qName = new QName(name.getNamespaceURI(), name.getLocalPart()); +// String value = c.attr(qName); +// if (value == null) { +// value = c.attr(name.getLocalPart()); +// } +// if (value != null) { +// featureBuilder.set(name, value); +// } +// } +// +// String uuid = c.attr(LdapAttr.entryUUID); +// +// SimpleFeature feature = featureBuilder.buildFeature(uuid); +// featureCollection.add(feature); +// +// }); +// gml.encode(out, featureCollection); +// out.close(); +// +// } /* * DEPENDENCY INJECTION diff --git a/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkFormListServlet.java b/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkFormListServlet.java index 546a129..5310542 100644 --- a/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkFormListServlet.java +++ b/org.argeo.app.servlet.odk/src/org/argeo/app/servlet/odk/OdkFormListServlet.java @@ -93,8 +93,8 @@ public class OdkFormListServlet extends HttpServlet { } String str = sb.toString(); if (!str.equals("")) { - if (log.isDebugEnabled()) - log.debug(str); + if (log.isTraceEnabled()) + log.trace(str); writer.append(str); } } diff --git a/sdk/branches/unstable.bnd b/sdk/branches/unstable.bnd index fab4587..acbede2 100644 --- a/sdk/branches/unstable.bnd +++ b/sdk/branches/unstable.bnd @@ -1,7 +1,7 @@ major=2 minor=3 micro=23 -qualifier= +qualifier=.next Bundle-Copyright= \ Copyright 2014-2023 Argeo GmbH, \ diff --git a/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java b/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java index 505c52d..9d3a192 100644 --- a/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java +++ b/swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java @@ -132,12 +132,15 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber Objects.requireNonNull(appUserState, "App user state must be provided"); long janitorPeriod = 60 * 60 * 1000;// 1h + // long janitorPeriod = 60 * 1000;// min janitorTimer.schedule(new TimerTask() { @Override public void run() { try { - Iterator>> uiRefs = managedUis.entrySet().iterator(); + // copy Map in order to avoid concurrent modification exception + Iterator>> uiRefs = new HashMap<>(managedUis).entrySet() + .iterator(); refs: while (uiRefs.hasNext()) { Map.Entry> entry = uiRefs.next(); String uiUuid = entry.getKey(); @@ -146,7 +149,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber if (ui == null) { if (log.isTraceEnabled()) log.warn("Unreferenced UI " + uiUuid + " in " + appPid + ", removing it"); - uiRefs.remove(); + managedUis.remove(uiUuid); continue refs; } if (!ui.isDisposed() && !ui.getDisplay().isDisposed()) { @@ -157,14 +160,14 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber } } else { if (log.isTraceEnabled()) - log.warn("Disposed UI " + uiUuid + " still in " + appPid + ", removing it"); - uiRefs.remove(); + log.warn("Disposed UI " + uiUuid + " still referenced in " + appPid + ", removing it"); + managedUis.remove(uiUuid); } } if (log.isTraceEnabled()) log.trace(managedUis.size() + " UIs being managed by app " + appPid); } catch (Exception e) { - e.printStackTrace(); + log.error("Could not clean up timed-out UIs", e); } } }, janitorPeriod, janitorPeriod); @@ -210,6 +213,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber SwtAppUi argeoSuiteUi = new SwtAppUi(uiParent, SWT.INHERIT_DEFAULT); // TODO make timeout configurable argeoSuiteUi.setUiTimeout(6 * 60 * 60 * 1000);// 6 hours + // argeoSuiteUi.setUiTimeout(60 * 1000);// 1 min String uid = cmsView.getUid(); argeoSuiteUi.addDisposeListener(new CleanUpUi(uid)); managedUis.put(uid, new WeakReference<>(argeoSuiteUi)); @@ -434,39 +438,12 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber // } } -// private static String listTypes(Node context) { -// try { -// StringBuilder sb = new StringBuilder(); -// sb.append(context.getPrimaryNodeType().getName()); -// for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) { -// sb.append(' '); -// sb.append(superType.getName()); -// } -// -// for (NodeType nodeType : context.getMixinNodeTypes()) { -// sb.append(' '); -// sb.append(nodeType.getName()); -// if (nodeType.getName().equals(EntityType.local.get())) -// sb.append('/').append(context.getProperty(EntityNames.ENTITY_TYPE).getString()); -// for (NodeType superType : nodeType.getDeclaredSupertypes()) { -// sb.append(' '); -// sb.append(superType.getName()); -// } -// } -// return sb.toString(); -// } catch (RepositoryException e) { -// throw new JcrException(e); -// } -// } - @Override public void setState(CmsUi cmsUi, String state) { AppUi ui = (AppUi) cmsUi; if (state == null) return; if (!state.startsWith("/")) { -// if (cmsUi instanceof SwtAppUi) { -// SwtAppUi ui = (SwtAppUi) cmsUi; if (LOGIN.equals(state)) { String appTitle = ""; if (ui.getTitle() != null) @@ -479,10 +456,8 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber properties.put(SuiteUxEvent.LAYER, layerId); properties.put(SuiteUxEvent.CONTENT_PATH, HOME_STATE); ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), properties); -// } return; } -// SwtAppUi suiteUi = (SwtAppUi) cmsUi; if (ui.isLoginScreen()) { return; } @@ -552,7 +527,7 @@ public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber ui.getCmsView().stateChanged(nodeToState(node), stateTitle(appTitle, CmsUxUtils.getTitle(node))); } else if (isTopic(topic, SuiteUxEvent.switchLayer)) { String layerId = get(event, SuiteUxEvent.LAYER); - if (layerId != null) { + if (layerId != null && !"".equals(layerId.trim())) { SwtAppLayer suiteLayer = findLayer(layerId); if (suiteLayer == null) throw new IllegalArgumentException("No layer '" + layerId + "' available."); diff --git a/swt/org.argeo.app.ui/src/org/argeo/app/ui/forms/MultiTermsPart.java b/swt/org.argeo.app.ui/src/org/argeo/app/ui/forms/MultiTermsPart.java index c936db3..57a6949 100644 --- a/swt/org.argeo.app.ui/src/org/argeo/app/ui/forms/MultiTermsPart.java +++ b/swt/org.argeo.app.ui/src/org/argeo/app/ui/forms/MultiTermsPart.java @@ -185,7 +185,8 @@ public class MultiTermsPart extends AbstractTermsPart { terms: for (String str : curr) { Term term = termsManager.getTerm(str); if (term == null) { - log.warn("Ignoring term " + str + " for " + getNode() + ", as it was not found."); + if (log.isTraceEnabled()) + log.warn("Ignoring term " + str + " for " + getNode() + ", as it was not found."); continue terms; } res.add(term);