Skip to content

Commit a105baf

Browse files
committed
Add AssetStorage and deprecate the old way of managing marker-images
1 parent 3949ebc commit a105baf

File tree

4 files changed

+195
-23
lines changed

4 files changed

+195
-23
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package de.bluecolored.bluemap.api;
2+
3+
import de.bluecolored.bluemap.api.markers.POIMarker;
4+
import de.bluecolored.bluemap.api.markers.HtmlMarker;
5+
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
import java.io.OutputStream;
9+
import java.util.Optional;
10+
11+
/**
12+
* A storage that is able to hold any "asset"-data for a map. For example images, icons, scripts or json-files.
13+
*/
14+
public interface AssetStorage {
15+
16+
/**
17+
* Writes a new asset into this storage, overwriting any existent assets with the same name.<br>
18+
* Use the returned {@link OutputStream} to write the asset-data. The asset will be added to the storage as soon as that stream
19+
* gets closed!
20+
* <p>
21+
* Example:
22+
* <pre>
23+
* try (OutputStream out = assetStorage.writeAsset("image.png")) {
24+
* ImageIO.write(image, "png", out);
25+
* }
26+
* </pre>
27+
* </p>
28+
* @param name The (unique) name for this asset
29+
* @return An {@link OutputStream} that should be used to write the asset and closed once!
30+
* @throws IOException when the underlying storage rises an IOException
31+
*/
32+
OutputStream writeAsset(String name) throws IOException;
33+
34+
/**
35+
* Reads an asset from this storage.<br>
36+
* Use the returned {@link InputStream} to read the asset-data.
37+
* <p>
38+
* Example:
39+
* <pre>
40+
* Optional&lt;InputStream&gt; optIn = assetStorage.readAsset("image.png");
41+
* if (optIn.isPresent()) {
42+
* try (InputStream in = optIn.get()) {
43+
* BufferedImage image = ImageIO.read(in);
44+
* }
45+
* }
46+
* </pre>
47+
* </p>
48+
* @param name The name of the asset that should be read from the storage.
49+
* @return An {@link Optional} with an {@link InputStream} when the asset is found, from which the asset can be read.
50+
* Or an empty optional if there is no asset with this name.
51+
* @throws IOException when the underlying storage rises an IOException
52+
*/
53+
Optional<InputStream> readAsset(String name) throws IOException;
54+
55+
/**
56+
* Checks if an asset exists in this storage without reading it.<br>
57+
* This is useful if the asset has a lot of data and using {@link #readAsset(String)}
58+
* just to check if the asset is present would be wasteful.
59+
* @param name The name of the asset to check for
60+
* @return <code>true</code> if the asset is found, <code>false</code> if not
61+
* @throws IOException when the underlying storage rises an IOException
62+
*/
63+
boolean assetExists(String name) throws IOException;
64+
65+
/**
66+
* Returns the relative URL that can be used by the webapp to request this asset.<br>
67+
* This is the url that you can e.g. use in {@link POIMarker}s or {@link HtmlMarker}s to add an icon.<br>
68+
* If there is no asset with this name, then this method returns the URL that an asset with such a name <i>would</i>
69+
* have if it would be added later.
70+
* @param name The name of the asset
71+
* @return The relative URL for an asset with the given name
72+
*/
73+
String getAssetUrl(String name);
74+
75+
/**
76+
* Deletes the asset with the given name from this storage, if it exists.<br>
77+
* If there is no asset with this name, this method does nothing.
78+
* @param name The name of the asset that should be deleted
79+
* @throws IOException when the underlying storage rises an IOException
80+
*/
81+
void deleteAsset(String name) throws IOException;
82+
83+
}

src/main/java/de/bluecolored/bluemap/api/BlueMapMap.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ public interface BlueMapMap {
6060
@DebugDump
6161
BlueMapWorld getWorld();
6262

63+
/**
64+
* Getter for this map's {@link AssetStorage}. <br>
65+
* Each map has its own storage for assets. Assets that are stored here will be available to every webapp that
66+
* is displaying this map. E.g. these assets are also available in server-networks.
67+
* @return the {@link AssetStorage} of this map
68+
*/
69+
@DebugDump
70+
AssetStorage getAssetStorage();
71+
6372
/**
6473
* Getter for a (modifiable) {@link Map} of {@link MarkerSet}s with the key being the {@link MarkerSet}'s id.
6574
* Changing this map will change the {@link MarkerSet}s and markers displayed on the web-app for this map.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package de.bluecolored.bluemap.api;
2+
3+
import java.nio.file.Path;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
/**
8+
* This Content-Type registry is used by the internal webserver to get the content-type of an asset.<br>
9+
* The most commonly used file-suffixes and their content-types are registered by default, but you can use the static
10+
* methods of this class to add more, if you need them.<br>
11+
* <b>Note:</b> that any additionally added types won't work if the user uses an external webserver to serve their map-files.
12+
*/
13+
public class ContentTypeRegistry {
14+
15+
private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
16+
private static final Map<String, String> SUFFIX_MAP = new HashMap<>();
17+
18+
static {
19+
register("txt", "text/plain");
20+
register("css", "text/css");
21+
register("csv", "text/csv");
22+
register("htm", "text/html");
23+
register("html", "text/html");
24+
register("js", "text/javascript");
25+
register("xml", "text/xml");
26+
27+
register("png", "image/png");
28+
register("jpg", "image/jpeg");
29+
register("jpeg", "image/jpeg");
30+
register("gif", "image/gif");
31+
register("webp", "image/webp");
32+
register("tif", "image/tiff");
33+
register("tiff", "image/tiff");
34+
register("svg", "image/svg+xml");
35+
36+
register("json", "application/json");
37+
38+
register("mp3", "audio/mpeg");
39+
register("oga", "audio/ogg");
40+
register("wav", "audio/wav");
41+
register("weba", "audio/webm");
42+
43+
register("mp4", "video/mp4");
44+
register("mpeg", "video/mpeg");
45+
register("webm", "video/webm");
46+
47+
register("ttf", "font/ttf");
48+
register("woff", "font/woff");
49+
register("woff2", "font/woff2");
50+
}
51+
52+
/**
53+
* Derives the content-type (mime) string using a path denoting a file
54+
* @param path The path pointing at the file
55+
* @return The derived content-type string
56+
*/
57+
public static String fromPath(Path path) {
58+
return fromFileName(path.getFileName().toString());
59+
}
60+
61+
/**
62+
* Derives the content-type (mime) string from the name of a file
63+
* @param fileName The name of the file
64+
* @return The derived content-type string
65+
*/
66+
public static String fromFileName(String fileName) {
67+
int i = fileName.lastIndexOf('.');
68+
if (i < 0) return DEFAULT_CONTENT_TYPE;
69+
70+
int s = fileName.lastIndexOf('/');
71+
if (i < s) return DEFAULT_CONTENT_TYPE;
72+
73+
String suffix = fileName.substring(i + 1);
74+
return fromFileSuffix(suffix);
75+
}
76+
77+
/**
78+
* Searches and returns the content-type for the provided file-suffix.
79+
* @param suffix The type-suffix of a file-name
80+
* @return The content-type string
81+
*/
82+
public static String fromFileSuffix(String suffix) {
83+
String contentType = SUFFIX_MAP.get(suffix);
84+
if (contentType != null) return contentType;
85+
return DEFAULT_CONTENT_TYPE;
86+
}
87+
88+
/**
89+
* Registers a new file-suffix => content-type mapping to this registry.
90+
* @param fileSuffix The type-suffix of a file-name
91+
* @param contentType The content-type string
92+
*/
93+
public static void register(String fileSuffix, String contentType) {
94+
SUFFIX_MAP.put(fileSuffix, contentType);
95+
}
96+
97+
}

src/main/java/de/bluecolored/bluemap/api/WebApp.java

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525
package de.bluecolored.bluemap.api;
2626

2727
import de.bluecolored.bluemap.api.debug.DebugDump;
28-
import de.bluecolored.bluemap.api.markers.Marker;
29-
import de.bluecolored.bluemap.api.markers.POIMarker;
30-
import com.flowpowered.math.vector.Vector2i;
3128

3229
import java.awt.image.BufferedImage;
3330
import java.io.IOException;
@@ -59,31 +56,17 @@ public interface WebApp {
5956
boolean getPlayerVisibility(UUID player);
6057

6158
/**
62-
* Creates an image-file with the given {@link BufferedImage} somewhere in the web-root, so it can be used in the web-app (e.g. for {@link Marker}-icons).
63-
*
64-
* <p>The given <code>path</code> is used as file-name and (separated with '/') optional folders to organize the image-files.
65-
* Do NOT include the file-ending! (e.g. <code>"someFolder/somePOIIcon"</code> will result in a file "somePOIIcon.png" in a folder "someFolder").</p>
66-
* <p>If the image file with the given path already exists, it will be replaced.</p>
67-
*
68-
* @param image the image to create
69-
* @param path the path/name of this image, the separator-char is '/'
70-
* @return the relative address of the image in the web-app,
71-
* which can be used as it is e.g. in the {@link POIMarker#setIcon(String, Vector2i)} method
72-
* @throws IOException If an {@link IOException} is thrown while writing the image
59+
* @deprecated You should use the {@link #getWebRoot()} method to create the image-files you need, or store map/marker
60+
* specific images in the map's storage (See: {@link BlueMapMap#getAssetStorage()})!
7361
*/
62+
@Deprecated
7463
String createImage(BufferedImage image, String path) throws IOException;
7564

7665
/**
77-
* Lists all images that are available. This includes all images previously created with the {@link #createImage(BufferedImage, String)}
78-
* function, but might include more.
79-
* @return A map of available images where:
80-
* <ul>
81-
* <li>the <b>key</b> is the image path how it would be used in the "path" parameter of the {@link #createImage(BufferedImage, String)} method</li>
82-
* <li>and the <b>value</b> is the relative address of the image. The same ones that are returned from the {@link #createImage(BufferedImage, String)} method</li>
83-
* </ul>
84-
* @throws IOException If an {@link IOException} is thrown while reading the images
66+
* @deprecated You should use the {@link #getWebRoot()} method to find the image-files you need, or read map/marker
67+
* specific images from the map's storage (See: {@link BlueMapMap#getAssetStorage()})!
8568
*/
86-
@DebugDump
69+
@Deprecated
8770
Map<String, String> availableImages() throws IOException;
8871

8972
}

0 commit comments

Comments
 (0)