/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.atomojo.www.util.script;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.atomojo.app.client.Link;
import org.atomojo.app.client.LinkSet;
import org.atomojo.www.util.Identity;
import org.atomojo.www.util.ResourceManager;
import org.restlet.Application;
import org.restlet.Client;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.CharacterSet;
import org.restlet.data.Cookie;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Method;
import org.restlet.data.Parameter;
import org.restlet.data.Status;
import org.restlet.representation.OutputRepresentation;
import org.restlet.representation.Representation;
/**
*
* @author alex
*/
public class IndexApplication extends Application {
public static final String LINKS_ATTR = "org.atomojo.www.app.links";
final static String T_APP_RESOURCE = "http://www.atomojo.org/O/www/configuration/application/resource";
final static String T_APP_PREFIX = "http://www.atmoo.org/O/www/configuration/application/prefix";
ScriptManager manager;
Link base;
String resourceName;
String prefix;
public IndexApplication(Context context)
{
super(context);
getTunnelService().setEnabled(false);
manager = (ScriptManager)context.getAttributes().get(ScriptManager.ATTR);
LinkSet linkset = (LinkSet)context.getAttributes().get(LINKS_ATTR);
String relation = context.getParameters().getFirstValue("http://www.atomojo.org/O/www/configuration/application/link-relation");
if (relation==null) {
relation = "resources";
}
List<Link> links = linkset.get(relation);
if (links!=null && links.size()>0) {
base = links.get(0);
}
if (base==null) {
getLogger().severe("The link relation "+relation+" cannot be found in the context.");
}
resourceName = context.getParameters().getFirstValue(T_APP_RESOURCE);
prefix = context.getParameters().getFirstValue(T_APP_PREFIX);
getLogger().info("Prefix: "+prefix);
getConnectorService().getClientProtocols().add(Protocol.HTTPS);
getConnectorService().getClientProtocols().add(Protocol.HTTP);
getConnectorService().getClientProtocols().add(Protocol.FILE);
getConnectorService().getClientProtocols().add(Protocol.CLAP);
getConnectorService().getClientProtocols().add(Protocol.RIAP);
}
public void setResource(String name) {
this.resourceName = null;
}
public Restlet createRoot() {
return new Restlet(getContext()) {
boolean isFineLog = getLogger().isLoggable(Level.FINE);
public void handle(final Request request,Response response) {
if (!request.getMethod().equals(Method.GET)) {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
return;
}
if (base==null) {
response.setStatus(Status.CLIENT_ERROR_PRECONDITION_FAILED);
return;
}
Object o = request.getAttributes().get("path");
String path = prefix==null ? "" : prefix;
if (o!=null) {
path = path+o.toString();
}
String remaining = request.getResourceRef().getRemainingPart();
if (remaining!=null && remaining.length()>0) {
if (path.length()>0) {
path += "/"+remaining;
} else {
path = remaining;
}
}
if (path.length()>0 && path.charAt(0)=='/') {
path = path.substring(1);
}
final Reference resource = new Reference(base.getLink().toString()+path);
if (path.length()>0 && path.charAt(path.length()-1)!='/') {
// resource
if (isFineLog) {
getLogger().fine("Proxy to "+resource);
}
Client client = getContext().getClientDispatcher();
//Client client = new Client(getContext().createChildContext(),Protocol.valueOf(resource.getScheme()));
client.getContext().getAttributes().put("hostnameVerifier", org.apache.commons.ssl.HostnameVerifier.DEFAULT);
Request remoteRequest = new Request(request.getMethod(),resource);
if (request.isEntityAvailable()) {
remoteRequest.setEntity(request.getEntity());
}
if (base.getUsername()!=null) {
remoteRequest.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_BASIC,base.getUsername(),base.getPassword()));
}
Response remoteResponse = client.handle(remoteRequest);
response.setStatus(remoteResponse.getStatus());
response.setEntity(remoteResponse.getEntity());
} else {
ScriptManager.ScriptContext releaseScript = null;
try {
final ScriptManager.ScriptContext script = manager.findScript(request,path);
if (script==null) {
response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
return;
}
releaseScript = script;
Response remoteResponse = null;
if (resourceName!=null) {
if (isFineLog) {
getLogger().fine("Using resource "+resourceName);
}
ResourceManager manager = (ResourceManager)getContext().getAttributes().get(ResourceManager.ATTR);
ResourceManager.Retriever retriever = manager.findResource(resourceName);
if (retriever!=null) {
remoteResponse = retriever.get();
} else {
getLogger().warning("No resource named "+resourceName);
}
} else {
Client client = getContext().getClientDispatcher();
//Client client = new Client(getContext().createChildContext(),resource.getSchemeProtocol());
client.getContext().getAttributes().put("hostnameVerifier", org.apache.commons.ssl.HostnameVerifier.DEFAULT);
Request remoteRequest = new Request(Method.GET,new Reference(resource.toString()));
if (base.getUsername()!=null) {
remoteRequest.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_BASIC,base.getUsername(),base.getPassword()));
}
Cookie cookie = request.getCookies().getFirst("I");
if (cookie!=null) {
remoteRequest.getCookies().add(cookie);
}
remoteResponse = client.handle(remoteRequest);
}
if (remoteResponse!=null && remoteResponse.getStatus().isSuccess()) {
final Representation feedResource = remoteResponse.getEntity();
response.setStatus(Status.SUCCESS_OK);
final Identity identity = (Identity)request.getAttributes().get(Identity.IDENTITY_ATTR);
final Map<String,Object> attrs = request.getAttributes();
releaseScript = null;
Representation rep = new OutputRepresentation(script.getMediaType()) {
public void write(OutputStream os)
throws IOException
{
try {
Transformer xform = script.getTransformer();
xform.clearParameters();
if (identity!=null) {
xform.setParameter("user.session",identity.getSession());
xform.setParameter("user.id",identity.getId());
xform.setParameter("user.alias",identity.getAlias());
if (identity.getName()!=null) {
xform.setParameter("user.name",identity.getName());
}
if (identity.getEmail()!=null) {
xform.setParameter("user.email",identity.getEmail());
}
}
xform.setParameter("request.resource.path",request.getResourceRef().getPath());
xform.setParameter("request.resource.authority",request.getResourceRef().getAuthority());
xform.setParameter("request.resource.scheme",request.getResourceRef().getScheme());
xform.setParameter("request.resource.query",request.getResourceRef().getQuery());
xform.setParameter("request.resource.fragment",request.getResourceRef().getFragment());
for (String name : attrs.keySet()) {
Object value = attrs.get(name);
if (value instanceof String) {
xform.setParameter(name,value);
}
}
for (Parameter param : getContext().getParameters()) {
xform.setParameter(param.getName(),param.getValue());
}
xform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
Reader input = null;
try {
input = feedResource.getReader();
try {
xform.transform(new StreamSource(input,resource.toString()),new StreamResult(new OutputStreamWriter(os,"UTF-8")));
} catch (TransformerException ex) {
getLogger().log(Level.SEVERE,"Cannot transform feed due to script error.",ex);
}
} finally {
if (input!=null) {
input.close();
}
}
} finally {
feedResource.release();
}
}
public void release() {
script.release();
}
};
rep.setCharacterSet(CharacterSet.UTF_8);
response.setEntity(rep);
response.setStatus(Status.SUCCESS_OK);
} else if (remoteResponse!=null) {
if (remoteResponse.isEntityAvailable()) {
remoteResponse.getEntity().release();
}
response.setStatus(remoteResponse.getStatus());
} else {
response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
}
} catch (Exception ex) {
getLogger().log(Level.SEVERE,"Cannot process script for "+path+" due to exception.",ex);
response.setStatus(Status.SERVER_ERROR_INTERNAL);
} finally {
if (releaseScript!=null) {
releaseScript.release();
}
}
}
}
};
}}