mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUAC-587: Implement support for serving of arbitrary resources.
This commit is contained in:
		| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
|  | ||||
| /** | ||||
|  * Base abstract resource implementation which provides an associated mimetype, | ||||
|  * and modification time. Classes which extend AbstractResource must provide | ||||
|  * their own InputStream, however. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| public abstract class AbstractResource implements Resource { | ||||
|  | ||||
|     /** | ||||
|      * The mimetype of this resource. | ||||
|      */ | ||||
|     private final String mimetype; | ||||
|  | ||||
|     /** | ||||
|      * The time this resource was last modified, in milliseconds since midnight | ||||
|      * of January 1, 1970 UTC. | ||||
|      */ | ||||
|     private final long lastModified; | ||||
|  | ||||
|     /** | ||||
|      * Initializes this AbstractResource with the given mimetype and | ||||
|      * modification time. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of this resource. | ||||
|      * | ||||
|      * @param lastModified | ||||
|      *     The time this resource was last modified, in milliseconds since | ||||
|      *     midnight of January 1, 1970 UTC. | ||||
|      */ | ||||
|     public AbstractResource(String mimetype, long lastModified) { | ||||
|         this.mimetype = mimetype; | ||||
|         this.lastModified = lastModified; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Initializes this AbstractResource with the given mimetype. The | ||||
|      * modification time of the resource is set to the current system time. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of this resource. | ||||
|      */ | ||||
|     public AbstractResource(String mimetype) { | ||||
|         this(mimetype, System.currentTimeMillis()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public long getLastModified() { | ||||
|         return lastModified; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getMimeType() { | ||||
|         return mimetype; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,85 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
|  | ||||
| import java.io.InputStream; | ||||
|  | ||||
| /** | ||||
|  * A resource which is located within the classpath of an arbitrary | ||||
|  * ClassLoader. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| public class ClassPathResource extends AbstractResource { | ||||
|  | ||||
|     /** | ||||
|      * The classloader to use when reading this resource. | ||||
|      */ | ||||
|     private final ClassLoader classLoader; | ||||
|  | ||||
|     /** | ||||
|      * The path of this resource relative to the classloader. | ||||
|      */ | ||||
|     private final String path; | ||||
|  | ||||
|     /** | ||||
|      * Creates a new ClassPathResource which uses the given ClassLoader to | ||||
|      * read the resource having the given path. | ||||
|      * | ||||
|      * @param classLoader | ||||
|      *     The ClassLoader to use when reading the resource. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of the resource. | ||||
|      * | ||||
|      * @param path | ||||
|      *     The path of the resource relative to the given ClassLoader. | ||||
|      */ | ||||
|     public ClassPathResource(ClassLoader classLoader, String mimetype, String path) { | ||||
|         super(mimetype); | ||||
|         this.classLoader = classLoader; | ||||
|         this.path = path; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new ClassPathResource which uses the ClassLoader associated | ||||
|      * with the ClassPathResource class to read the resource having the given | ||||
|      * path. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of the resource. | ||||
|      * | ||||
|      * @param path | ||||
|      *     The path of the resource relative to the ClassLoader associated | ||||
|      *     with the ClassPathResource class. | ||||
|      */ | ||||
|     public ClassPathResource(String mimetype, String path) { | ||||
|         this(ClassPathResource.class.getClassLoader(), mimetype, path); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public InputStream asStream() { | ||||
|         return classLoader.getResourceAsStream(path); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,67 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
|  | ||||
| import java.io.InputStream; | ||||
|  | ||||
| /** | ||||
|  * An arbitrary resource that can be served to a user via HTTP. Resources are | ||||
|  * anonymous but have a defined mimetype and corresponding input stream. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| public interface Resource { | ||||
|  | ||||
|     /** | ||||
|      * Returns the mimetype of this resource. This function MUST always return | ||||
|      * a value. If the type is unknown, return "application/octet-stream". | ||||
|      * | ||||
|      * @return | ||||
|      *     The mimetype of this resource. | ||||
|      */ | ||||
|     String getMimeType(); | ||||
|  | ||||
|     /** | ||||
|      * Returns the time the resource was last modified in milliseconds since | ||||
|      * midnight of January 1, 1970 UTC. | ||||
|      * | ||||
|      * @return | ||||
|      *      The time the resource was last modified, in milliseconds. | ||||
|      */ | ||||
|     long getLastModified(); | ||||
|  | ||||
|     /** | ||||
|      * Returns an InputStream which reads the contents of this resource, | ||||
|      * starting with the first byte. Reading from the returned InputStream will | ||||
|      * not affect reads from other InputStreams returned by other calls to | ||||
|      * asStream(). The returned InputStream must be manually closed when no | ||||
|      * longer needed. If the resource is unexpectedly unavailable, this will | ||||
|      * return null. | ||||
|      * | ||||
|      * @return | ||||
|      *     An InputStream which reads the contents of this resource, starting | ||||
|      *     with the first byte, or null if the resource is unavailable. | ||||
|      */ | ||||
|     InputStream asStream(); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,126 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.OutputStream; | ||||
| import javax.servlet.ServletException; | ||||
| import javax.servlet.http.HttpServlet; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
|  | ||||
| /** | ||||
|  * Servlet which serves a given resource for all HTTP GET requests. The HEAD | ||||
|  * method is correctly supported, and HTTP 304 ("Not Modified") responses will | ||||
|  * be properly returned for GET requests depending on the last time the | ||||
|  * resource was modified. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| public class ResourceServlet extends HttpServlet { | ||||
|  | ||||
|     /** | ||||
|      * Logger for this class. | ||||
|      */ | ||||
|     private static final Logger logger = LoggerFactory.getLogger(ResourceServlet.class); | ||||
|  | ||||
|     /** | ||||
|      * The size of the buffer to use when transferring data from the input | ||||
|      * stream of a resource to the output stream of a request. | ||||
|      */ | ||||
|     private static final int BUFFER_SIZE = 10240; | ||||
|  | ||||
|     /** | ||||
|      * The resource to serve for every GET request. | ||||
|      */ | ||||
|     private final Resource resource; | ||||
|  | ||||
|     /** | ||||
|      * Creates a new ResourceServlet which serves the given Resource for all | ||||
|      * HTTP GET requests. | ||||
|      * | ||||
|      * @param resource | ||||
|      *     The Resource to serve. | ||||
|      */ | ||||
|     public ResourceServlet(Resource resource) { | ||||
|         this.resource = resource; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void doHead(HttpServletRequest request, HttpServletResponse response) | ||||
|             throws ServletException, IOException { | ||||
|  | ||||
|         // Set last modified and content type headers | ||||
|         response.addDateHeader("Last-Modified", resource.getLastModified()); | ||||
|         response.setContentType(resource.getMimeType()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void doGet(HttpServletRequest request, HttpServletResponse response) | ||||
|             throws ServletException, IOException { | ||||
|  | ||||
|         // Get input stream from resource | ||||
|         InputStream input = resource.asStream(); | ||||
|  | ||||
|         // If resource does not exist, return not found | ||||
|         if (input == null) { | ||||
|             logger.debug("Resource does not exist: \"{}\"", request.getServletPath()); | ||||
|             response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|  | ||||
|             // Write headers | ||||
|             doHead(request, response); | ||||
|  | ||||
|             // If not modified since "If-Modified-Since" header, return not modified | ||||
|             long ifModifiedSince = request.getDateHeader("If-Modified-Since"); | ||||
|             if (resource.getLastModified() - ifModifiedSince < 1000) { | ||||
|                 logger.debug("Resource not modified: \"{}\"", request.getServletPath()); | ||||
|                 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             int length; | ||||
|             byte[] buffer = new byte[BUFFER_SIZE]; | ||||
|  | ||||
|             // Write resource to response body | ||||
|             OutputStream output = response.getOutputStream(); | ||||
|             while ((length = input.read(buffer)) != -1) | ||||
|                 output.write(buffer, 0, length); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // Ensure input stream is always closed | ||||
|         finally { | ||||
|             input.close(); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,153 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.io.SequenceInputStream; | ||||
| import java.util.Arrays; | ||||
| import java.util.Enumeration; | ||||
| import java.util.Iterator; | ||||
|  | ||||
| /** | ||||
|  * A resource which is the logical concatenation of other resources. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| public class SequenceResource extends AbstractResource { | ||||
|  | ||||
|     /** | ||||
|      * The resources to be concatenated. | ||||
|      */ | ||||
|     private final Iterable<Resource> resources; | ||||
|  | ||||
|     /** | ||||
|      * Returns the mimetype of the first resource in the given Iterable, or | ||||
|      * "application/octet-stream" if no resources are provided. | ||||
|      * | ||||
|      * @param resources | ||||
|      *     The resources from which the mimetype should be retrieved. | ||||
|      * | ||||
|      * @return | ||||
|      *     The mimetype of the first resource, or "application/octet-stream" | ||||
|      *     if no resources were provided. | ||||
|      */ | ||||
|     private static String getMimeType(Iterable<Resource> resources) { | ||||
|  | ||||
|         // If no resources, just assume application/octet-stream | ||||
|         Iterator<Resource> resourceIterator = resources.iterator(); | ||||
|         if (!resourceIterator.hasNext()) | ||||
|             return "application/octet-stream"; | ||||
|  | ||||
|         // Return mimetype of first resource | ||||
|         return resourceIterator.next().getMimeType(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new SequenceResource as the logical concatenation of the | ||||
|      * given resources. Each resource is concatenated in iteration order as | ||||
|      * needed when reading from the input stream of the SequenceResource. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of the resource. | ||||
|      * | ||||
|      * @param resources | ||||
|      *     The resources to concatenate within the InputStream of this | ||||
|      *     SequenceResource. | ||||
|      */ | ||||
|     public SequenceResource(String mimetype, Iterable<Resource> resources) { | ||||
|         super(mimetype); | ||||
|         this.resources = resources; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new SequenceResource as the logical concatenation of the | ||||
|      * given resources. Each resource is concatenated in iteration order as | ||||
|      * needed when reading from the input stream of the SequenceResource. The | ||||
|      * mimetype of the resulting concatenation is derived from the first | ||||
|      * resource. | ||||
|      * | ||||
|      * @param resources | ||||
|      *     The resources to concatenate within the InputStream of this | ||||
|      *     SequenceResource. | ||||
|      */ | ||||
|     public SequenceResource(Iterable<Resource> resources) { | ||||
|         super(getMimeType(resources)); | ||||
|         this.resources = resources; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new SequenceResource as the logical concatenation of the | ||||
|      * given resources. Each resource is concatenated in iteration order as | ||||
|      * needed when reading from the input stream of the SequenceResource. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of the resource. | ||||
|      * | ||||
|      * @param resources | ||||
|      *     The resources to concatenate within the InputStream of this | ||||
|      *     SequenceResource. | ||||
|      */ | ||||
|     public SequenceResource(String mimetype, Resource... resources) { | ||||
|         this(mimetype, Arrays.asList(resources)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new SequenceResource as the logical concatenation of the | ||||
|      * given resources. Each resource is concatenated in iteration order as | ||||
|      * needed when reading from the input stream of the SequenceResource. The | ||||
|      * mimetype of the resulting concatenation is derived from the first | ||||
|      * resource. | ||||
|      * | ||||
|      * @param resources | ||||
|      *     The resources to concatenate within the InputStream of this | ||||
|      *     SequenceResource. | ||||
|      */ | ||||
|     public SequenceResource(Resource... resources) { | ||||
|         this(Arrays.asList(resources)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public InputStream asStream() { | ||||
|         return new SequenceInputStream(new Enumeration<InputStream>() { | ||||
|  | ||||
|             /** | ||||
|              * Iterator over all resources associated with this | ||||
|              * SequenceResource. | ||||
|              */ | ||||
|             private final Iterator<Resource> resourceIterator = resources.iterator(); | ||||
|  | ||||
|             @Override | ||||
|             public boolean hasMoreElements() { | ||||
|                 return resourceIterator.hasNext(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public InputStream nextElement() { | ||||
|                 return resourceIterator.next().asStream(); | ||||
|             } | ||||
|  | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,116 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import javax.servlet.ServletContext; | ||||
|  | ||||
| /** | ||||
|  * A resource which is located within the classpath associated with another | ||||
|  * class. | ||||
|  * | ||||
|  * @author Michael Jumper | ||||
|  */ | ||||
| public class WebApplicationResource extends AbstractResource { | ||||
|  | ||||
|     /** | ||||
|      * The servlet context to use when reading the resource and, if necessary, | ||||
|      * when determining the mimetype of the resource. | ||||
|      */ | ||||
|     private final ServletContext context; | ||||
|  | ||||
|     /** | ||||
|      * The path of this resource relative to the ServletContext. | ||||
|      */ | ||||
|     private final String path; | ||||
|  | ||||
|     /** | ||||
|      * Derives a mimetype from the filename within the given path using the | ||||
|      * given ServletContext, if possible. | ||||
|      * | ||||
|      * @param context | ||||
|      *     The ServletContext to use to derive the mimetype. | ||||
|      * | ||||
|      * @param path | ||||
|      *     The path to derive the mimetype from. | ||||
|      * | ||||
|      * @return | ||||
|      *     An appropriate mimetype based on the name of the file in the path, | ||||
|      *     or "application/octet-stream" if no mimetype could be determined. | ||||
|      */ | ||||
|     private static String getMimeType(ServletContext context, String path) { | ||||
|  | ||||
|         // If mimetype is known, use defined mimetype | ||||
|         String mimetype = context.getMimeType(path); | ||||
|         if (mimetype != null) | ||||
|             return mimetype; | ||||
|  | ||||
|         // Otherwise, default to application/octet-stream | ||||
|         return "application/octet-stream"; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new WebApplicationResource which serves the resource at the | ||||
|      * given path relative to the given ServletContext. Rather than deriving | ||||
|      * the mimetype of the resource from the filename within the path, the | ||||
|      * mimetype given is used. | ||||
|      * | ||||
|      * @param context | ||||
|      *     The ServletContext to use when reading the resource. | ||||
|      * | ||||
|      * @param mimetype | ||||
|      *     The mimetype of the resource. | ||||
|      * | ||||
|      * @param path | ||||
|      *     The path of the resource relative to the given ServletContext. | ||||
|      */ | ||||
|     public WebApplicationResource(ServletContext context, String mimetype, String path) { | ||||
|         super(mimetype); | ||||
|         this.context = context; | ||||
|         this.path = path; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new WebApplicationResource which serves the resource at the | ||||
|      * given path relative to the given ServletContext. The mimetype of the | ||||
|      * resource is automatically determined based on the filename within the | ||||
|      * path. | ||||
|      * | ||||
|      * @param context | ||||
|      *     The ServletContext to use when reading the resource and deriving the | ||||
|      *     mimetype. | ||||
|      * | ||||
|      * @param path | ||||
|      *     The path of the resource relative to the given ServletContext. | ||||
|      */ | ||||
|     public WebApplicationResource(ServletContext context, String path) { | ||||
|         this(context, getMimeType(context, path), path); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public InputStream asStream() { | ||||
|         return context.getResourceAsStream(path); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Classes which describe and provide access to arbitrary resources, such as | ||||
|  * the contents of the classpath of a classloader, or files within the web | ||||
|  * application itself. | ||||
|  */ | ||||
| package org.glyptodon.guacamole.net.basic.resource; | ||||
		Reference in New Issue
	
	Block a user