/**
* Copyright 2005-2014 Restlet
*
* The contents of this file are subject to the terms of one of the following
* open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the Apache 2.0 license at
* http://www.opensource.org/licenses/apache-2.0
*
* You can obtain a copy of the EPL 1.0 license at
* http://www.opensource.org/licenses/eclipse-1.0
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royalty free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://restlet.com/products/restlet-framework
*
* Restlet is a registered trademark of Restlet S.A.S.
*/
package org.restlet.ext.servlet.internal;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.servlet.ServletContext;
import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.engine.local.Entity;
import org.restlet.representation.InputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.service.MetadataService;
/**
* Local entity based on a Servlet context's resource file.
*
* @author Thierry Boileau
*/
public class ServletWarEntity extends Entity {
/**
* List of children files if it is a directory. We suppose that in a WAR
* entity, this list does not change, and thus can be cached during the
* request processing.
*/
private List<Entity> children = null;
/** Is this file a directory? */
private final boolean directory;
/** The full name of the file (without trailing "/"). */
private final String fullName;
/** The relative path of the file inside the context. */
private final String path;
/** The Servlet context to use. */
private final ServletContext servletContext;
/**
* Constructor.
*
* @param servletContext
* The parent Servlet context.
* @param path
* The entity path.
* @param metadataService
* The metadata service to use.
*/
public ServletWarEntity(ServletContext servletContext, String path,
MetadataService metadataService) {
super(metadataService);
this.children = null;
this.servletContext = servletContext;
this.path = path;
if (path.endsWith("/")) {
this.directory = true;
this.fullName = path.substring(0, path.length() - 1);
Set<?> childPaths = getServletContext().getResourcePaths(path);
if (childPaths != null && !childPaths.isEmpty()) {
this.children = new ArrayList<Entity>();
for (Object childPath : childPaths) {
if (!childPath.equals(this.path)) {
this.children.add(new ServletWarEntity(
this.servletContext, (String) childPath,
metadataService));
}
}
}
} else {
this.fullName = path;
Set<?> childPaths = getServletContext().getResourcePaths(path);
if (childPaths != null && !childPaths.isEmpty()) {
this.directory = true;
this.children = new ArrayList<Entity>();
for (Object childPath : childPaths) {
if (!childPath.equals(this.path)) {
this.children.add(new ServletWarEntity(
this.servletContext, (String) childPath,
metadataService));
}
}
} else {
this.directory = false;
}
}
}
@Override
public boolean exists() {
boolean result = false;
try {
result = (isDirectory() && getChildren() != null)
|| (isNormal() && getServletContext()
.getResource(this.path) != null);
} catch (MalformedURLException e) {
Context.getCurrentLogger().log(Level.WARNING,
"Unable to test the existence of the WAR resource", e);
}
return result;
}
@Override
public List<Entity> getChildren() {
return this.children;
}
@Override
public String getName() {
int index = this.fullName.lastIndexOf("/");
if (index != -1) {
return this.fullName.substring(index + 1);
}
return this.fullName;
}
@Override
public Entity getParent() {
Entity result = null;
int index = this.fullName.lastIndexOf("/");
if (index != -1) {
result = new ServletWarEntity(getServletContext(),
this.fullName.substring(0, index + 1), getMetadataService());
}
return result;
}
@Override
public Representation getRepresentation(MediaType defaultMediaType,
int timeToLive) {
Representation result = null;
try {
URL resource = getServletContext().getResource(path);
if (resource != null) {
URLConnection connection = resource.openConnection();
result = new InputRepresentation(connection.getInputStream(),
defaultMediaType);
// Sets the modification date
result.setModificationDate(new Date(connection
.getLastModified()));
// Sets the expiration date
if (timeToLive == 0) {
result.setExpirationDate(null);
} else if (timeToLive > 0) {
result.setExpirationDate(new Date(System
.currentTimeMillis() + (1000L * timeToLive)));
}
}
} catch (IOException e) {
Context.getCurrentLogger().log(Level.WARNING,
"Error getting the WAR resource.", e);
}
return result;
}
/**
* Returns the Servlet context to use.
*
* @return The Servlet context to use.
*/
public ServletContext getServletContext() {
return this.servletContext;
}
@Override
public boolean isDirectory() {
return this.directory;
}
@Override
public boolean isNormal() {
return !isDirectory();
}
}