Skip to content

Commit

Permalink
[BP] Overview not shown in PDF export when the overview image is stor…
Browse files Browse the repository at this point in the history
…ed in GeoNetwork and requires authentication to access it. Fixes geonetwork#7540 (geonetwork#7556)
  • Loading branch information
josegar74 authored and ianwallen committed Dec 23, 2023
1 parent 3dad83b commit 91795de
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public ResourceHolder getResource(final ServiceContext context, final String met
int metadataId = canDownload(context, metadataUuid, visibility, approved);
checkResourceId(resourceId);

final Path resourceFile = Lib.resource.getDir(context, visibility.toString(), metadataId).
final Path resourceFile = Lib.resource.getDir(visibility.toString(), metadataId).
resolve(getFilename(metadataUuid, resourceId));

if (Files.exists(resourceFile)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ public Element updateFixedInfo(String schema, Optional<Integer> metadataId, Stri
env.addContent(new Element("parentUuid").setText(parentUuid));
}
if (metadataId.isPresent()) {
final Path resourceDir = Lib.resource.getDir(context, Params.Access.PRIVATE, metadataId.get());
final Path resourceDir = Lib.resource.getDir(Params.Access.PRIVATE, metadataId.get());
env.addContent(new Element("datadir").setText(resourceDir.toString()));
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/fao/geonet/lib/ResourceLib.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ public class ResourceLib {
* @param id The metadata identifier
* @return The data directory
*/
public Path getDir(ServiceContext context, String access, int id) {
Path mdDir = getMetadataDir(context.getBean(GeonetworkDataDirectory.class), id);
public Path getDir(String access, int id) {
Path mdDir = getMetadataDir(ApplicationContextHolder.get().getBean(GeonetworkDataDirectory.class), id);
String subDir = (access != null && access.equals(Params.Access.PUBLIC)) ? Params.Access.PUBLIC
: Params.Access.PRIVATE;
return mdDir.resolve(subDir);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2022 Food and Agriculture Organization of the
* Copyright (C) 2001-2023 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
Expand Down Expand Up @@ -28,11 +28,14 @@
import com.lowagie.text.Image;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.records.attachments.Store;
import org.fao.geonet.api.records.extent.MapRenderer;
import org.fao.geonet.api.records.extent.MetadataExtentApi;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.constants.Params;
import org.fao.geonet.domain.MetadataResourceVisibility;
import org.fao.geonet.utils.Log;
import org.xhtmlrenderer.extend.FSImage;
import org.xhtmlrenderer.extend.ReplacedElement;
Expand All @@ -59,6 +62,8 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jeeves.server.context.ServiceContext;

public class ImageReplacedElementFactory implements ReplacedElementFactory {
private static Set<String> imgFormatExts = null;
private final ReplacedElementFactory superFactory;
Expand All @@ -81,20 +86,23 @@ private static Set<String> getSupportedExts() {
if (imgFormatExts == null) {
synchronized (ImageReplacedElementFactory.class) {
if (imgFormatExts == null) {
imgFormatExts = Sets.newHashSet();
Set<String> tmpImgFormatExts = Sets.newHashSet();
for (String ext : ImageIO.getReaderFileSuffixes()) {
imgFormatExts.add(ext.toLowerCase());
tmpImgFormatExts.add(ext.toLowerCase());
}
imgFormatExts = tmpImgFormatExts;
}
}
}

return imgFormatExts;
}

static private Pattern ONE_EXTENT_API_REGEX = Pattern.compile(".*/(.*)/extents/([0-9]+)\\.png.*");
static private Pattern ALL_EXTENT_API_REGEX = Pattern.compile(".*/(.*)/extents\\.png.*");
static private final String EXTENT_XPATH = ".//*[local-name() ='extent']/*/*[local-name() = 'geographicElement']/*";
private static final Pattern ONE_EXTENT_API_REGEX = Pattern.compile(".*/(.*)/extents/(\\d+)\\.png.*");
private static final Pattern ALL_EXTENT_API_REGEX = Pattern.compile(".*/(.*)/extents\\.png.*");
private static final String EXTENT_XPATH = ".//*[local-name() ='extent']/*/*[local-name() = 'geographicElement']/*";

private static final String DEFAULT_SRS = "EPSG:4326";

@Override
public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockBox box,
Expand All @@ -108,15 +116,15 @@ public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockB
if (!"img".equals(nodeName)) {
try {
return superFactory.createReplacedElement(layoutContext, box, userAgentCallback, cssWidth, cssHeight);
} catch (Throwable e) {
} catch (Exception e) {
return new EmptyReplacedElement(cssWidth, cssHeight);
}
}


String src = element.getAttribute("src");
String baseUrlNoLang = baseURL.substring(0, baseURL.length() - 4);

boolean useExtentApi = src.startsWith(baseURL.substring(0, baseURL.length() - 4))
boolean useExtentApi = src.startsWith(baseUrlNoLang)
&& mapRenderer != null
&& (ALL_EXTENT_API_REGEX.matcher(src).matches()
|| ONE_EXTENT_API_REGEX.matcher(src).matches());
Expand All @@ -134,7 +142,7 @@ public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockB
regionId = String.format("metadata:@id%s:@xpath(%s)[%s]", ApiUtils.getInternalId(oneMatcher.group(1), true), EXTENT_XPATH, oneMatcher.group(2));
}
Map<String, String> parameters = getParams(src);
String srs = parameters.get(MetadataExtentApi.MAP_SRS_PARAM) != null ? parameters.get(MetadataExtentApi.MAP_SRS_PARAM) : "EPSG:4326";
String srs = parameters.get(MetadataExtentApi.MAP_SRS_PARAM) != null ? parameters.get(MetadataExtentApi.MAP_SRS_PARAM) : DEFAULT_SRS;
Integer width = parameters.get(MetadataExtentApi.WIDTH_PARAM) != null ? Integer.parseInt(parameters.get(MetadataExtentApi.WIDTH_PARAM)) : null;
Integer height = parameters.get(MetadataExtentApi.HEIGHT_PARAM) != null ? Integer.parseInt(parameters.get(MetadataExtentApi.HEIGHT_PARAM)) : null;
String background = parameters.get(MetadataExtentApi.BACKGROUND_PARAM);
Expand All @@ -144,20 +152,25 @@ public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockB
}
float factor = layoutContext.getDotsPerPixel();
return loadImage(layoutContext, box, userAgentCallback, cssWidth, cssHeight, new BufferedImageLoader(image), factor);
} else if (src.startsWith(baseURL + "region.getmap.png") | src.endsWith("/geom.png") && mapRenderer != null) {
} else if (src.startsWith(baseURL + "region.getmap.png") || src.endsWith("/geom.png") && mapRenderer != null) {
BufferedImage image = null;
try {
Map<String, String> parameters = getParams(src);

String id = parameters.get(Params.ID);
String srs = parameters.get(MetadataExtentApi.MAP_SRS_PARAM) != null ? parameters.get(MetadataExtentApi.MAP_SRS_PARAM) : "EPSG:4326";
String srs = parameters.get(MetadataExtentApi.MAP_SRS_PARAM) != null ? parameters.get(MetadataExtentApi.MAP_SRS_PARAM) : DEFAULT_SRS;
Integer width = parameters.get(MetadataExtentApi.WIDTH_PARAM) != null ? Integer.parseInt(parameters.get(MetadataExtentApi.WIDTH_PARAM)) : null;
Integer height = parameters.get(MetadataExtentApi.HEIGHT_PARAM) != null ? Integer.parseInt(parameters.get(MetadataExtentApi.HEIGHT_PARAM)) : null;
String background = parameters.get(MetadataExtentApi.BACKGROUND_PARAM);
String geomParam = parameters.get(MetadataExtentApi.GEOM_PARAM);
String geomType = parameters.get(MetadataExtentApi.GEOM_TYPE_PARAM) != null ? parameters.get(MetadataExtentApi.GEOM_TYPE_PARAM) : "WKT";
String geomSrs = parameters.get(MetadataExtentApi.GEOM_SRS_PARAM) != null ? parameters.get(MetadataExtentApi.GEOM_SRS_PARAM) : "EPSG:4326";
String geomSrs = parameters.get(MetadataExtentApi.GEOM_SRS_PARAM) != null ? parameters.get(MetadataExtentApi.GEOM_SRS_PARAM) : DEFAULT_SRS;

if ((width == null) && (height == null)) {
// Width or height are required. If not set the default width with the same value
// as defined in MetadataExtentApi.getOneRecordExtentAsImage
width = 300;
}
image = mapRenderer.render(
id, srs, width, height, background, geomParam, geomType, geomSrs, null, null);
} catch (Exception e) {
Expand Down Expand Up @@ -188,14 +201,29 @@ public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockB
}
float factor = layoutContext.getDotsPerPixel();
return loadImage(layoutContext, box, userAgentCallback, cssWidth, cssHeight, new UrlImageLoader(builder.toString()), factor);

} else if (src.startsWith(baseUrlNoLang) && src.contains("/attachments/")) {
// Process attachments urls to load the images from the data directory
Matcher m = Pattern.compile(baseUrlNoLang + "api/records/(.*)/attachments/(.*)$").matcher(src);
if (m.find()) {
String uuid = m.group(1);
String file = m.group(2);

float factor = layoutContext.getDotsPerPixel();
return loadImage(layoutContext, box, userAgentCallback, cssWidth, cssHeight, new DataDirectoryImageLoader(uuid, file), factor);
} else if (isSupportedImageFormat(src)) {
float factor = layoutContext.getDotsPerPixel();
return loadImage(layoutContext, box, userAgentCallback, cssWidth, cssHeight, new UrlImageLoader(src), factor);
}

} else if (isSupportedImageFormat(src)) {
float factor = layoutContext.getDotsPerPixel();
return loadImage(layoutContext, box, userAgentCallback, cssWidth, cssHeight, new UrlImageLoader(src), factor);
}

try {
return superFactory.createReplacedElement(layoutContext, box, userAgentCallback, cssWidth, cssHeight);
} catch (Throwable e) {
} catch (Exception e) {
return new EmptyReplacedElement(cssWidth, cssHeight);
}
}
Expand Down Expand Up @@ -243,7 +271,7 @@ private ReplacedElement loadImage(LayoutContext layoutContext, BlockBox box, Use

try {
return superFactory.createReplacedElement(layoutContext, box, userAgentCallback, cssWidth, cssHeight);
} catch (Throwable e2) {
} catch (Exception e2) {
return new EmptyReplacedElement(cssWidth, cssHeight);
}
}
Expand Down Expand Up @@ -292,6 +320,35 @@ public Image loadImage() throws Exception {
}
}


/**
* Class to load images from the metadata data directory.
*/
private class DataDirectoryImageLoader implements ImageLoader {
private final String uuid;
private final String file;
public DataDirectoryImageLoader(String uuid, String file) {
this.uuid = uuid;
this.file = file;
}

@Override
public Image loadImage() throws Exception {
Store store = ApplicationContextHolder.get().getBean("filesystemStore", Store.class);
BufferedImage bufferedImage;
try (Store.ResourceHolder imageFile = store.getResource(ServiceContext.get(),
this.uuid,

This comment has been minimized.

Copy link
@wangf1122

wangf1122 Jan 3, 2024

ServiceContext.get() is null here and will cause null pointer exception. I created a PR to avoid such issue, please review.

geonetwork#7593

MetadataResourceVisibility.PUBLIC,
this.file, true)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bufferedImage = ImageIO.read(imageFile.getPath().toFile());
ImageIO.write(bufferedImage, "png", baos);
return Image.getInstance(baos.toByteArray());
}
}
}


/* Define an AWT BufferedImage image loader */

private class BufferedImageLoader implements ImageLoader {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,8 +658,8 @@ public void getRelated() throws Exception {
}

private void addThumbnails(ServiceContext context) throws Exception {
Path mdPublicDataDir = Lib.resource.getDir(context, Params.Access.PUBLIC, id);
Path mdPrivateDataDir = Lib.resource.getDir(context, Params.Access.PRIVATE, id);
Path mdPublicDataDir = Lib.resource.getDir(Params.Access.PUBLIC, id);
Path mdPrivateDataDir = Lib.resource.getDir(Params.Access.PRIVATE, id);
final Path smallImage = mdPublicDataDir.resolve("small.gif");
final Path largeImage = mdPublicDataDir.resolve("large.gif");
createImage("gif", smallImage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ public void testCreateMetadataAndCopyExistingPictures() throws Exception {

final String id = importMetadata(context);

Path mdPublicDataDir = Lib.resource.getDir(context, Params.Access.PUBLIC, Integer.parseInt(id));
Path mdPrivateDataDir = Lib.resource.getDir(context, Params.Access.PRIVATE, Integer.parseInt(id));
Path mdPublicDataDir = Lib.resource.getDir(Params.Access.PUBLIC, Integer.parseInt(id));
Path mdPrivateDataDir = Lib.resource.getDir(Params.Access.PRIVATE, Integer.parseInt(id));
final Path smallImage = mdPublicDataDir.resolve("small.gif");
final Path largeImage = mdPublicDataDir.resolve("large.gif");
createImage(GIF, smallImage);
Expand All @@ -119,14 +119,14 @@ public void testCreateMetadataAndCopyExistingPictures() throws Exception {
final String newId = element.getChildText(Geonet.Elem.ID);
assertNotNull(_metadataRepo.findOne(newId));

Path newPublicMdDataDir = Lib.resource.getDir(context, Params.Access.PUBLIC, Integer.parseInt(newId));
Path newPublicMdDataDir = Lib.resource.getDir(Params.Access.PUBLIC, Integer.parseInt(newId));
assertTrue(Files.exists(newPublicMdDataDir.resolve(smallImage.getFileName())));
assertTrue(Files.exists(newPublicMdDataDir.resolve(largeImage.getFileName())));

final int expected = 2;
assertFilesInDirectory(newPublicMdDataDir, expected);

Path newPrivateMdDataDir = Lib.resource.getDir(context, Params.Access.PRIVATE, Integer.parseInt(newId));
Path newPrivateMdDataDir = Lib.resource.getDir(Params.Access.PRIVATE, Integer.parseInt(newId));
assertTrue(Files.exists(newPrivateMdDataDir));
assertFilesInDirectory(newPrivateMdDataDir, 1);
assertTrue(Files.exists(newPrivateMdDataDir.resolve(privateImage.getFileName())));
Expand Down

0 comments on commit 91795de

Please sign in to comment.