/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package juzu.impl.asset;
import juzu.asset.AssetLocation;
import juzu.impl.common.Timestamped;
import juzu.impl.plugin.application.Application;
import juzu.impl.common.Tools;
import juzu.impl.request.Request;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class AssetServer {
/** Application -> Dynamic. */
HashMap<Application, Boolean> runtimes = new HashMap<Application, Boolean>();
/** . */
private static final ThreadLocal<AssetServer> current = new ThreadLocal<AssetServer>();
public AssetServer() {
}
public void register(Application assetManager, boolean cacheAssets) {
runtimes.put(assetManager, cacheAssets);
}
public void unregister(Application assetManager) {
runtimes.remove(assetManager);
}
public boolean doGet(String path, ServletContext ctx, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (path != null && path.length() > 0) {
for (Map.Entry<Application, Boolean> runtime : runtimes.entrySet()) {
Iterable<AssetManager> resolvers = runtime.getKey().resolveBeans(AssetManager.class);
for (AssetManager resolver : resolvers) {
// For now we only have resource of URL type ...
AssetResource content = resolver.resolveApplicationAssetResource(path);
if (content == null) {
// It could be a server resource like an image
URL resource = ctx.getResource(path);
if (resource != null) {
content = new AssetResource(resource, null);
}
}
if (content != null) {
InputStream in;
long lastModified;
URLConnection conn = content.url.openConnection();
lastModified = conn.getLastModified();
String etag = Tools.etag(path, lastModified);
Enumeration<String> matches = req.getHeaders("If-None-Match");
if (matches.hasMoreElements() && matches.nextElement().equals(etag)) {
resp.setStatus(304);
} else {
in = conn.getInputStream();
int pos = path.lastIndexOf('/');
String name = pos == -1 ? path : path.substring(pos + 1);
resp.setHeader("ETag", etag);
boolean cacheAssets = runtime.getValue();
if (cacheAssets) {
int maxAge = content.maxAge != null ? content.maxAge : 3600;
if (maxAge > 0) {
resp.setHeader("Cache-Control", "max-age=" + maxAge);
}
} else {
resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
}
String contentType = ctx.getMimeType(name);
if (contentType != null) {
resp.setContentType(contentType);
}
Tools.copy(in, resp.getOutputStream());
}
return true;
}
}
}
}
return false;
}
public static String renderAssetURLById(String id) throws NullPointerException {
Request request = Request.getCurrent();
if (request != null) {
AssetManager assetManager = request.getApplication().resolveBean(AssetManager.class);
if (assetManager != null) {
Asset asset = assetManager.getAsset(id);
if (asset != null) {
String uri = asset.resolveURI(request.getRunMode().getMinifyAssets());
return renderAssetURL(request, asset.getLocation(), uri);
}
}
}
return null;
}
public static String renderAssetURLByPath(String path) throws NullPointerException {
Request request = Request.getCurrent();
if (request != null) {
return renderAssetURL(request, AssetLocation.APPLICATION, path);
} else {
return null;
}
}
public static String renderAssetURLByPath(AssetLocation location, String path) throws NullPointerException {
Request request = Request.getCurrent();
if (request != null) {
return renderAssetURL(request, location, path);
} else {
return null;
}
}
private static String renderAssetURL(Request request, AssetLocation location, String uri) throws NullPointerException {
StringBuilder buffer = new StringBuilder();
switch (location) {
case APPLICATION:
request.renderAssetURL(location, uri, buffer);
break;
default:
request.renderAssetURL(location, uri, buffer);
break;
}
return buffer.toString();
}
}