/*
* TemplateFinder.java
*
* Created on September 25, 2007, 10:41 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.www.util.script;
import org.atomojo.www.util.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Properties;
import java.util.logging.Level;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.MediaType;
import org.restlet.data.Metadata;
import org.restlet.resource.Finder;
import org.restlet.resource.ServerResource;
import org.restlet.routing.Template;
/**
*
* @author alex
*/
public class ScriptFinder extends Finder
{
public static String RESOURCE_CONFIG_ATTR = "org.atomojo.www.script.config";
public static String SCRIPT_CACHE_ATTR = "org.atomojo.www.script.cache";
public static String RESOURCE_ATTR = "org.atomojo.www.resource";
Class baseClass;
String packageName;
ResourceConfiguration resourceConfig;
ScriptCache scriptCache;
/** Creates a new instance of TemplateFinder */
public ScriptFinder(Context context,Class baseClass)
{
this(context,baseClass,null);
}
/** Creates a new instance of TemplateFinder */
public ScriptFinder(Context context,Class baseClass,String path)
{
super(context);
this.baseClass = baseClass;
this.packageName = path==null ? "/"+baseClass.getPackage().getName().replace('.','/')+"/" :
path.length()>0 && path.charAt(0)=='/' ? path :
"/"+baseClass.getPackage().getName().replace('.','/')+"/"+path;
if (!this.packageName.endsWith("/")) {
this.packageName += "/";
}
for (String name : getContext().getParameters().getNames()) {
getLogger().info("Script parameter: "+name+" -> "+getContext().getParameters().getFirstValue(name));
}
//getContext().getAttributes().putAll(context.getAttributes());
//getContext().setParameters(context.getParameters());
resourceConfig = (ResourceConfiguration)context.getAttributes().get(RESOURCE_CONFIG_ATTR);
if (resourceConfig==null) {
getLogger().warning("Defaulting resource configuration.");
resourceConfig = new ResourceConfiguration();
}
scriptCache = (ScriptCache)context.getAttributes().get(SCRIPT_CACHE_ATTR);
if (scriptCache==null) {
scriptCache = new ScriptCache();
}
}
public ResourceConfiguration getResourceConfiguraiton() {
return resourceConfig;
}
public ServerResource find(Request request,Response response)
{
//String path = packageName+request.getResourceRef().getRemainingPart();
String path = request.getResourceRef().getRemainingPart();
URL script = null;
URI resource = (URI)request.getAttributes().get(RESOURCE_ATTR);
int extPos = path.lastIndexOf('.');
Application app = this.getApplication();
Properties resourceProperties = resourceConfig.match(path);
String stype = resourceProperties.getProperty("content-type");
MediaType type = stype==null ? null : MediaType.valueOf(stype);
String defaultExtension = resourceProperties.getProperty("extension");
if (defaultExtension==null) {
defaultExtension = ".ats";
}
String agentsValue = resourceProperties.getProperty("agents");
String resourceTemplate = resourceProperties.getProperty("resource");
getLogger().info("resource template: "+resourceTemplate);
if (resource==null && resourceTemplate!=null) {
String href = null;
String uri = null;
try {
Template t = new Template(resourceTemplate);
href = t.format(request.getAttributes());
String baseURISpec = resourceProperties.getProperty("base-uri");
URI baseURI = null;
if (baseURISpec!=null) {
Template tbase = new Template(baseURISpec);
uri = tbase.format(request.getAttributes());
baseURI = new URI(uri);
}
resource = baseURI==null ? new URI(href) : baseURI.resolve(href);
} catch (URISyntaxException ex) {
getLogger().log(Level.SEVERE,"Cannot construct resource URI, href="+href+", base="+uri,ex);
return null;
}
}
String [] agents = null;
if (agentsValue!=null) {
agents = agentsValue.split(",");
}
MediaType forceType = null;
if (type==null && extPos>=0) {
String ext = path.substring(extPos+1);
Metadata mdata = this.getApplication().getMetadataService().getMetadata(ext);
if (mdata!=null) {
type = MediaType.valueOf(mdata.getName());
}
} else if (path.length()==0 || path.charAt(path.length()-1)=='/') {
// no extension and is a directory path, default to index.xml template
script = baseClass.getResource(packageName+path+"index.ats");
if (script==null) {
script = baseClass.getResource(packageName+path+"index.xsl");
}
if (resource==null) {
try {
URL url = baseClass.getResource(packageName+path + "index.xml");
/*
if (url==null) {
getLogger().warning("Canot find resource via class path: "+path+"index.xml");
return null;
}
resource = url.toURI();
*/
if (url!=null) {
resource = url.toURI();
}
} catch (URISyntaxException ex) {
getLogger().log(Level.SEVERE,"Cannot convert URL to URI: "+path,ex);
return null;
}
}
if (type==null && agents!=null) {
String agent = request.getClientInfo().getAgent();
for (int i=0; i<agents.length; i++) {
String exp = resourceProperties.getProperty(agents[i]+".match");
if (agent.matches(exp)) {
if (getLogger().isLoggable(Level.FINE)) {
getLogger().fine("Matched agent "+agent+" with "+agents[i]);
}
stype = resourceProperties.getProperty(agents[i]+".content-type");
forceType = stype==null ? null : MediaType.valueOf(stype);
break;
}
}
}
if (type==null) {
type = MediaType.APPLICATION_XHTML_XML;
}
} else {
// no extension, so lookup based on xml file
script = baseClass.getResource(packageName+path+defaultExtension);
if (script==null) {
script = baseClass.getResource(packageName+path+".xsl");
}
if (resource==null) {
try {
URL url = baseClass.getResource(packageName+path + ".xml");
/*
if (url==null) {
getLogger().warning("Canot find resource via class path: "+path+".xml");
return null;
}
resource = url.toURI();
*/
if (url!=null) {
resource = url.toURI();
}
} catch (URISyntaxException ex) {
getLogger().log(Level.SEVERE,"Cannot convert URL to URI: "+path);
return null;
}
}
if (type==null && agents!=null) {
String agent = request.getClientInfo().getAgent();
for (int i=0; i<agents.length; i++) {
String exp = resourceProperties.getProperty(agents[i]+".match");
if (agent.matches(exp)) {
stype = resourceProperties.getProperty(agents[i]+".content-type");
forceType = stype==null ? null : MediaType.valueOf(stype);
break;
}
}
}
if (type==null) {
type = MediaType.APPLICATION_XHTML_XML;
}
}
if (type==null) {
type = app.getMetadataService().getDefaultMediaType();
}
boolean isResource = (type.getMainType().equals("image") || (script==null && type.getMainType().equals("text")) || (type.getMainType().equals("application") && !type.getName().equals("application/xml") && !type.getName().endsWith("+xml")));
String sflag = resourceProperties.getProperty("force-resource");
if (sflag!=null && sflag.equals("true")) {
isResource = true;
}
sflag = resourceProperties.getProperty("force-script");
if (sflag!=null && sflag.equals("true")) {
isResource = false;
}
if (isResource) {
if (getLogger().isLoggable(Level.FINE)) {
getLogger().fine("Path is a resource: "+path+" "+type.getName());
}
path = packageName+path;
return new ClassResource(baseClass,path);
} else {
if (forceType!=null) {
type = forceType;
}
if (script==null) {
String uri = resourceProperties.getProperty("script");
if (uri!=null) {
Template t = new Template(uri);
String formatted = t.format(request.getAttributes());
try {
script = new URL(formatted);
} catch (MalformedURLException ex) {
getLogger().log(Level.SEVERE,"Cannot convert script to URL: "+uri,ex);
return null;
}
}
}
if (script==null) {
getLogger().warning("Cannot location script for path "+path);
return null;
}
try {
URI uri = script.toURI();
if (getLogger().isLoggable(Level.FINE)) {
getLogger().fine("Using script "+uri);
}
if (!scriptCache.hasScript(uri)) {
getLogger().info("adding "+uri);
scriptCache.add(uri);
}
ScriptResource scriptResource = new ScriptResource(scriptCache,uri,resource,type);
String username = resourceProperties.getProperty("resource.username");
if (username!=null) {
scriptResource.setResourceUser(username,resourceProperties.getProperty("resource.password"));
}
return scriptResource;
} catch (URISyntaxException ex) {
getLogger().log(Level.SEVERE,"Cannot convert URL to URI: "+path);
return null;
}
}
}
}