/*
* ServiceProxyResource.java
*
* Created on October 25, 2007, 9:28 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.www.app.edit;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import org.atomojo.app.client.Link;
import org.atomojo.app.client.LinkSet;
import org.atomojo.app.client.XMLRepresentationParser;
import org.infoset.xml.Document;
import org.infoset.xml.Element;
import org.infoset.xml.Name;
import org.infoset.xml.util.XMLWriter;
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.ChallengeScheme;
import org.restlet.data.Cookie;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Parameter;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.representation.StringRepresentation;
/**
*
* @author alex
*/
public class APPProxy extends Restlet
{
static Map<String,Boolean> standardHeaders = new TreeMap<String,Boolean>();
static {
standardHeaders.put("Cookie",Boolean.TRUE);
standardHeaders.put("Content-Length",Boolean.TRUE);
standardHeaders.put("Content-Type",Boolean.TRUE);
standardHeaders.put("Referer",Boolean.TRUE);
standardHeaders.put("Connection",Boolean.TRUE);
standardHeaders.put("Accept-Charset",Boolean.TRUE);
standardHeaders.put("Accept-Encoding",Boolean.TRUE);
standardHeaders.put("Accept-Language",Boolean.TRUE);
standardHeaders.put("Accept",Boolean.TRUE);
standardHeaders.put("User-Agent",Boolean.TRUE);
standardHeaders.put("Host",Boolean.TRUE);
standardHeaders.put("If-None-Match", Boolean.TRUE);
}
static Name WORKSPACE = Name.create("{http://www.w3.org/2007/app}workspace");
static Name COLLECTION = Name.create("{http://www.w3.org/2007/app}collection");
String base;
String username;
String password;
public APPProxy(Context context)
{
super(context);
base = context.getParameters().getFirstValue("app.url");
username = null;
password = null;
String relation = context.getParameters().getFirstValue("app.link");
getLogger().info("app.link="+relation);
if (relation!=null) {
LinkSet linkSet = (LinkSet)context.getAttributes().get("org.atomojo.www.app.links");
List<Link> links = linkSet.get(relation);
if (links!=null && links.size()>0) {
Link link = links.get(0);
base = link.getLink().toString();
username = link.getUsername();
password = link.getPassword();
}
}
}
public void handle(Request request,Response response)
{
String baseURL = base;
if (baseURL==null) {
Object o = request.getAttributes().get("app.url");
if (o!=null) {
baseURL = o.toString();
} else {
getLogger().severe("app.url missing.");
response.setStatus(Status.SERVER_ERROR_INTERNAL);
return;
}
}
String remaining = request.getResourceRef().getRemainingPart();
if (remaining!=null && remaining.startsWith("R")) {
int q = remaining.indexOf("?");
if (q>0) {
remaining = remaining.substring(0,q);
}
}
Reference appRef = new Reference(remaining==null ? baseURL : baseURL+remaining);
getLogger().info("APP proxy to "+appRef);
Client client = new Client(getContext().createChildContext(),appRef.getSchemeProtocol());
client.getContext().getAttributes().put("hostnameVerifier", org.apache.commons.ssl.HostnameVerifier.DEFAULT);
Request appRequest = new Request(request.getMethod(),appRef);
if (username!=null) {
appRequest.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_BASIC,username,password));
} else if (request.getChallengeResponse()!=null) {
appRequest.setChallengeResponse(request.getChallengeResponse());
}
appRequest.setEntity(request.getEntity());
Cookie cookie = request.getCookies().getFirst("I");
if (cookie!=null) {
appRequest.getCookies().add(cookie);
}
Form headers = (Form)request.getAttributes().get("org.restlet.http.headers");
if (headers!=null) {
Form newHeaders = new Form();
for (Parameter param : headers) {
String name = param.getName();
if (standardHeaders.get(name)==null) {
newHeaders.add(param);;
}
}
appRequest.getAttributes().put("org.restlet.http.headers",newHeaders);
}
Response appResponse = client.handle(appRequest);
headers = (Form)appResponse.getAttributes().get("org.request.http.headers");
response.setStatus(appResponse.getStatus());
if (appResponse.getStatus().isSuccess() && (remaining==null || remaining.length()==0)) {
String path = request.getResourceRef().getPath();
path = path.substring(0,path.length()-1);
getLogger().info("Manipulating service document to adjust to path: "+path);
try {
XMLRepresentationParser parser = new XMLRepresentationParser();
Document introspection = parser.load(appResponse.getEntity());
Iterator<Element> workspaces = introspection.getDocumentElement().getElementsByName(WORKSPACE);
while (workspaces.hasNext()) {
Element workspace = workspaces.next();
Iterator<Element> collections = workspace.getElementsByName(COLLECTION);
while (collections.hasNext()) {
Element collection = collections.next();
String href = collection.getAttributeValue("href");
if (href!=null) {
int pos = href.indexOf("/R");
if (pos>=0) {
href = path+href.substring(pos);
collection.setAttributeValue("href", href);
}
}
}
}
StringWriter buffer = new StringWriter();
XMLWriter.writeDocument(introspection, buffer);
response.setEntity(new StringRepresentation(buffer.toString(),MediaType.APPLICATION_ATOM_SERVICE_XML));
} catch (Exception ex) {
response.setStatus(Status.SERVER_ERROR_INTERNAL);
getLogger().log(Level.SEVERE,"Cannot parse introspection.",ex);
}
} else {
response.setEntity(appResponse.getEntity());
}
response.setChallengeRequests(appResponse.getChallengeRequests());
response.getAttributes().put("org.request.http.headers", headers);
}
}