source: gs3-extensions/iiif-servlet/trunk/src/src/main/java/edu/illinois/library/cantaloupe/resource/iiif/v2/GSInformationResource.java@ 32707

Last change on this file since 32707 was 32707, checked in by davidb, 5 years ago

Files needed for GS3-Cantaloupe bridge result from second round of testing

File size: 8.0 KB
Line 
1package edu.illinois.library.cantaloupe.resource.iiif.v2;
2
3import java.io.IOException;
4import java.nio.file.Files;
5import java.nio.file.NoSuchFileException;
6import java.nio.file.Path;
7import java.util.List;
8
9import edu.illinois.library.cantaloupe.RestletApplication;
10import edu.illinois.library.cantaloupe.cache.CacheFacade;
11import edu.illinois.library.cantaloupe.config.Configuration;
12import edu.illinois.library.cantaloupe.config.Key;
13import edu.illinois.library.cantaloupe.image.Format;
14import edu.illinois.library.cantaloupe.image.Identifier;
15import edu.illinois.library.cantaloupe.image.Info;
16import edu.illinois.library.cantaloupe.processor.Processor;
17import edu.illinois.library.cantaloupe.processor.ProcessorFactory;
18import edu.illinois.library.cantaloupe.source.Source;
19import edu.illinois.library.cantaloupe.source.SourceFactory;
20import edu.illinois.library.cantaloupe.resource.JSONRepresentation;
21import edu.illinois.library.cantaloupe.processor.ProcessorConnector;
22import org.restlet.data.MediaType;
23import org.restlet.data.Preference;
24import org.restlet.data.Reference;
25import org.restlet.representation.EmptyRepresentation;
26import org.restlet.representation.Representation;
27import org.restlet.resource.Get;
28
29import org.greenstone.gsdl3.IIIFServerBridge;
30
31/**
32 * Handles IIIF Image API 2.x information requests.
33 *
34 * @see <a href="http://iiif.io/api/image/2.1/#information-request">Information
35 * Requests</a>
36 */
37public class GSInformationResource extends InformationResource {
38
39 /**
40 * Redirects {@literal /:identifier} to {@literal /:identifier/info.json},
41 * respecting the Servlet context root and
42 * {@link #PUBLIC_IDENTIFIER_HEADER} header.
43 */
44 public static class RedirectingResource extends IIIF2Resource {
45 @Get
46 public Representation doGet() {
47 final Reference newRef = new Reference(
48 getPublicRootReference() +
49 RestletApplication.IIIF_2_PATH + "/" +
50 getPublicIdentifier() +
51 "/info.json");
52 redirectSeeOther(newRef);
53 return new EmptyRepresentation();
54 }
55 }
56
57 /**
58 * Responds to information requests.
59 *
60 * @return {@link ImageInfo} instance serialized as JSON.
61 */
62 @Get
63 public Representation doGet() throws Exception {
64 final Configuration config = Configuration.getInstance();
65 final Identifier identifier = getIdentifier();
66 final CacheFacade cacheFacade = new CacheFacade();
67
68 // If we don't need to resolve first, and are using a cache, and the
69 // cache contains an info matching the request, skip all the setup and
70 // just return the cached info.
71 if (!isResolvingFirst()) {
72 try {
73 Info info = cacheFacade.getInfo(identifier);
74 if (info != null) {
75 // The source format will be null or UNKNOWN if the info was
76 // serialized in version < 3.4.
77 final Format format = info.getSourceFormat();
78 if (format != null && !Format.UNKNOWN.equals(format)) {
79 final Processor processor = new ProcessorFactory().
80 newProcessor(format);
81 commitCustomResponseHeaders();
82 return newRepresentation(info, processor);
83 }
84 }
85 } catch (IOException e) {
86 // Don't rethrow -- it's still possible to service the request.
87 getLogger().severe(e.getMessage());
88 }
89 }
90
91 IIIFServerBridge gs_iiif_bridge = new IIIFServerBridge();
92 gs_iiif_bridge.init("localsite");
93 String gs_message = gs_iiif_bridge.doGetDocumentMessage(identifier.toString());
94
95 final Source source = new SourceFactory().newSource(
96 identifier, getDelegateProxy());
97
98 System.err.println("***** identifier = " + identifier);
99 System.err.println("***** source path = " + ((edu.illinois.library.cantaloupe.source.FileSource)source).getPath());
100
101 // If we are resolving first, or if the source image is not present in
102 // the source cache (if enabled), check access to it in preparation for
103 // retrieval.
104 final Path sourceImage = cacheFacade.getSourceCacheFile(identifier);
105 if (sourceImage == null || isResolvingFirst()) {
106 try {
107 source.checkAccess();
108 } catch (NoSuchFileException e) { // this needs to be rethrown!
109 if (config.getBoolean(Key.CACHE_SERVER_PURGE_MISSING, false)) {
110 // If the image was not found, purge it from the cache.
111 cacheFacade.purgeAsync(identifier);
112 }
113 throw e;
114 }
115 }
116
117 // Get the format of the source image.
118 // If we are not resolving first, and there is a hit in the source
119 // cache, read the format from the source-cached-file, as we will
120 // expect source cache access to be more efficient.
121 // Otherwise, read it from the source.
122 Format format = Format.UNKNOWN;
123 if (!isResolvingFirst() && sourceImage != null) {
124 List<edu.illinois.library.cantaloupe.image.MediaType> mediaTypes =
125 edu.illinois.library.cantaloupe.image.MediaType.detectMediaTypes(sourceImage);
126 if (!mediaTypes.isEmpty()) {
127 format = mediaTypes.get(0).toFormat();
128 }
129 } else {
130 format = source.getFormat();
131 }
132
133 // Obtain an instance of the processor assigned to that format.
134 try (Processor processor = new ProcessorFactory().newProcessor(format)) {
135 // Connect it to the source.
136 tempFileFuture = new ProcessorConnector().connect(
137 source, processor, identifier, format);
138
139 final Info info = getOrReadInfo(identifier, processor);
140
141 commitCustomResponseHeaders();
142
143 return newRepresentation(info, processor);
144 }
145 }
146
147 /**
148 * @return Full image URI corresponding to the given identifier, respecting
149 * the {@literal X-Forwarded-*} and
150 * {@link #PUBLIC_IDENTIFIER_HEADER} reverse proxy headers.
151 */
152 private String getImageURI() {
153 return getPublicRootReference() + RestletApplication.IIIF_2_PATH + "/" +
154 getPublicIdentifier();
155 }
156
157 private MediaType getNegotiatedMediaType() {
158 MediaType mediaType;
159 // If the client has requested JSON-LD, set the content type to
160 // that; otherwise set it to JSON.
161 List<Preference<MediaType>> preferences = getRequest().getClientInfo().
162 getAcceptedMediaTypes();
163 if (preferences.get(0) != null && preferences.get(0).toString().
164 startsWith("application/ld+json")) {
165 mediaType = new MediaType("application/ld+json");
166 } else {
167 mediaType = new MediaType("application/json");
168 }
169 return mediaType;
170 }
171
172 private Representation newRepresentation(Info info,
173 Processor processor) {
174 final ImageInfoFactory factory = new ImageInfoFactory(
175 processor.getSupportedFeatures(),
176 processor.getSupportedIIIF2Qualities(),
177 processor.getAvailableOutputFormats());
178 factory.setDelegateProxy(getDelegateProxy());
179
180 final ImageInfo<String, Object> imageInfo = factory.newImageInfo(
181 getImageURI(), info, getPageIndex());
182 final MediaType mediaType = getNegotiatedMediaType();
183
184 return new JSONRepresentation(imageInfo, mediaType, () -> {
185 if (tempFileFuture != null) {
186 Path tempFile = tempFileFuture.get();
187 if (tempFile != null) {
188 Files.deleteIfExists(tempFile);
189 }
190 }
191 return null;
192 });
193 }
194
195 private boolean isResolvingFirst() {
196 return Configuration.getInstance().
197 getBoolean(Key.CACHE_SERVER_RESOLVE_FIRST, true);
198 }
199
200}
Note: See TracBrowser for help on using the repository browser.