/*
* Configuration.java
*
* Created on June 18, 2007, 3:01 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.www;
import org.atomojo.www.util.IdentityManager;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.atomojo.app.client.Link;
import org.atomojo.app.client.LinkSet;
import org.atomojo.www.util.ResourceManager;
import org.atomojo.www.util.script.ScriptManager;
import org.infoset.xml.Document;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.Element;
import org.infoset.xml.Name;
import org.infoset.xml.XMLException;
import org.infoset.xml.sax.SAXDocumentLoader;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.data.Parameter;
/**
*
* @author alex
*/
public class Configuration
{
public static final URI NAMESPACE = URI.create("http://www.atomojo.org/Vocabulary/WebServer/2008/1/0");
static final Name SERVER = Name.create(NAMESPACE,"server");
static final Name APPDEF = Name.create(NAMESPACE,"appdef");
static final Name LIBRARY = Name.create(NAMESPACE,"library");
static final Name INTERFACE = Name.create(NAMESPACE,"interface");
static final Name AUTOCONF = Name.create(NAMESPACE,"autoconf");
static final Name HOST = Name.create(NAMESPACE,"host");
static final Name LINK = Name.create(NAMESPACE,"link");
static final Name PARAMETER = Name.create(NAMESPACE,"parameter");
static final Name LOG = Name.create(NAMESPACE,"log");
static final Name APP = Name.create(NAMESPACE,"app");
static final Name CONTENT = Name.create(NAMESPACE,"content");
static final Name KEYSTORE = Name.create(NAMESPACE,"keystore");
public class AppDef {
String name;
Class<Application> appClass;
public AppDef(String name,Class<Application> appClass)
{
this.name = name;
this.appClass = appClass;
}
public String getName() {
return name;
}
public Application getInstance(Context context)
throws InstantiationException,IllegalAccessException,NoSuchMethodException,InvocationTargetException
{
Constructor<Application> makeit = appClass.getConstructor(Context.class);
return makeit.newInstance(context);
}
}
public class Interface {
String addr;
int port;
boolean secure;
Map<String,Host> hosts;
LinkSet links;
public Interface(String addr,int port,boolean secure)
{
this.addr = addr;
this.port = port;
this.secure = secure;
this.hosts = new HashMap<String,Host>();
this.links = new LinkSet();
}
public String getKey() {
return this.addr+":"+this.port;
}
public String getAddress() {
return addr;
}
public int getPort() {
return port;
}
public boolean isSecure() {
return secure;
}
public Map<String,Host> getHosts() {
return hosts;
}
public LinkSet getLinks() {
return links;
}
}
public class Host {
String name;
String internalName;
List<AppConf> apps;
LinkSet links;
List<Content> contents;
Map<String,String> parameters;
Map<String,String> logConf;
public Host(String name)
{
this(name,null);
}
public Host(String name,String internalName)
{
this.name = name;
this.internalName = internalName;
this.apps = new ArrayList<AppConf>();
this.links = new LinkSet();
this.contents = new ArrayList<Content>();
this.parameters = new TreeMap<String,String>();
this.logConf = new HashMap<String,String>();
}
public String getName() {
return name;
}
public String getInternalName() {
return internalName;
}
public Map<String,String> getParameters() {
return parameters;
}
public Map<String,String> getLogConfiguration() {
return logConf;
}
public LinkSet getLinks() {
return links;
}
public List<AppConf> getApplications() {
return apps;
}
public List<Content> getContentSources() {
return contents;
}
}
public class Content {
URI source;
String match;
Content(URI source,String match)
{
this.source = source;
this.match = match;
}
public URI getSource() {
return source;
}
public String getMatch() {
return match;
}
}
public class AppConf {
AppDef appDef;
String match;
Element confElement;
LinkSet links;
Map<String,String> parameters;
public AppConf(AppDef appDef,String match,Element confElement,LinkSet inheritedLinks)
{
this.appDef = appDef;
this.match = match;
this.confElement = confElement;
this.links = new LinkSet();
this.links.mergeLinkSet(inheritedLinks);
this.parameters = new TreeMap<String,String>();
}
public AppDef getApplicationDef() {
return appDef;
}
public LinkSet getLinks() {
return links;
}
public Map<String,String> getParameters() {
return parameters;
}
public Element getConfiguration() {
return confElement;
}
public Application getApplication(Context context,Map<String,List<Link>> links)
throws InstantiationException,IllegalAccessException,NoSuchMethodException,InvocationTargetException
{
Context appContext = context.createChildContext();
for (Parameter param : context.getParameters()) {
String name = param.getName();
if (name.equals("keystorePath") ||
name.equals("keystorePassword") ||
name.equals("keyPassword")) {
continue;
}
appContext.getParameters().add(param);
}
IdentityManager manager = (IdentityManager)context.getAttributes().get(IdentityManager.ATTR);
if (manager!=null) {
appContext.getAttributes().put(IdentityManager.ATTR,manager);
}
appContext.getAttributes().put(WebComponent.LINKS_ATTR,links);
Object scriptManager = context.getAttributes().get(ScriptManager.ATTR);
if (scriptManager!=null) {
appContext.getAttributes().put(ScriptManager.ATTR,scriptManager);
}
Object resourceManager = context.getAttributes().get(ResourceManager.ATTR);
if (resourceManager!=null) {
appContext.getAttributes().put(ResourceManager.ATTR,resourceManager);
}
for (String name : parameters.keySet()) {
appContext.getLogger().info("Setting parameter "+name+"="+parameters.get(name));
appContext.getParameters().add(name,parameters.get(name));
}
return appDef.getInstance(appContext);
}
public String getMatch()
{
return match;
}
}
long autoconfCheck;
Map<String,AppDef> appDefs;
List<Interface> interfaces;
File keyStorePath;
String keyStorePassword;
/** Creates a new instance of Configuration */
public Configuration()
{
this.autoconfCheck = 180*1000;
this.appDefs = new HashMap<String,AppDef>();
this.interfaces = new ArrayList<Interface>();
}
public Host createHost(Element hostE)
throws XMLException
{
String name = hostE.getAttributeValue("name");
String internalName = hostE.getAttributeValue("internal");
Host host = new Host(name,internalName);
Iterator<Element> hostParams = hostE.getElementsByName(PARAMETER);
while (hostParams.hasNext()) {
Element paramE = hostParams.next();
String pname = paramE.getAttributeValue("name");
if (pname!=null) {
String value = paramE.getAttributeValue("value");
String href = paramE.getAttributeValue("href");
if (href!=null) {
value = paramE.getBaseURI().resolve(href).toString();
}
if (value==null) {
value = "";
}
host.getParameters().put(pname,value);
}
}
Iterator<Element> links = hostE.getElementsByName(LINK);
while (links.hasNext()) {
Element linkE = links.next();
String href = linkE.getAttributeValue("href");
if (href!=null) {
URI tlocation = linkE.getBaseURI().resolve(href);
String mtype = linkE.getAttributeValue("type");
Link l = new Link(linkE.getAttributeValue("rel"),mtype==null ? null : MediaType.valueOf(mtype),tlocation);
l.setIdentity(linkE.getAttributeValue("username"),linkE.getAttributeValue("password"));
if (l.getRelation()!=null) {
host.getLinks().put(l.getRelation(),l);
}
}
}
Iterator<Element> appElements = hostE.getElementsByName(APP);
while (appElements.hasNext()) {
Element appE = appElements.next();
String appName = appE.getAttributeValue("name");
String match = appE.getAttributeValue("match");
AppDef def = appDefs.get(appName);
if (def==null) {
throw new XMLException("Cannot find defintion of application "+appName);
}
AppConf appconf = new AppConf(def,match,(Element)appE.copyOfItem(true),host.getLinks());
Iterator<Element> appLinks = appE.getElementsByName(LINK);
while (appLinks.hasNext()) {
Element linkE = appLinks.next();
String href = linkE.getAttributeValue("href");
if (href!=null) {
URI tlocation = linkE.getBaseURI().resolve(href);
String mtype = linkE.getAttributeValue("type");
Link l = new Link(linkE.getAttributeValue("rel"),mtype==null ? null : MediaType.valueOf(mtype),tlocation);
l.setIdentity(linkE.getAttributeValue("username"),linkE.getAttributeValue("password"));
if (l.getRelation()!=null) {
appconf.getLinks().put(l.getRelation(),l);
}
}
}
Iterator<Element> params = appE.getElementsByName(PARAMETER);
while (params.hasNext()) {
Element paramE = params.next();
String pname = paramE.getAttributeValue("name");
if (pname!=null) {
String value = paramE.getAttributeValue("value");
String href = paramE.getAttributeValue("href");
if (href!=null) {
value = paramE.getBaseURI().resolve(href).toString();
}
if (value==null) {
value = "";
}
appconf.getParameters().put(pname,value);
}
}
host.getApplications().add(appconf);
}
Iterator<Element> contentElements = hostE.getElementsByName(CONTENT);
while (contentElements.hasNext()) {
Element contentE = contentElements.next();
String match = contentE.getAttributeValue("match");
String href = contentE.getAttributeValue("href");
URI source = contentE.getBaseURI().resolve(href);
Content content = new Content(source,match);
host.getContentSources().add(content);
}
Iterator<Element> logs = hostE.getElementsByName(LOG);
if (logs.hasNext()) {
Element logE = logs.next();
for (Name attName : logE.getAttributes().keySet()) {
host.getLogConfiguration().put(attName.toString(),logE.getAttributeValue(attName));
}
}
return host;
}
public void load(URI location)
throws IOException,XMLException
{
DocumentLoader loader = new SAXDocumentLoader();
Document doc = loader.load(location);
Element top = doc.getDocumentElement();
if (!top.getName().equals(SERVER)) {
throw new XMLException("Expecting "+SERVER+" but found "+top.getName());
}
String value = top.getAttributeValue("autoconf-check");
if (value!=null) {
autoconfCheck = Long.parseLong(value) * 1000;
}
Element keyStoreE = top.getFirstElementNamed(KEYSTORE);
if (keyStoreE!=null) {
URI fileRef = keyStoreE.getBaseURI().resolve(keyStoreE.getAttributeValue("file"));
this.keyStorePath = new File(fileRef.getSchemeSpecificPart());
this.keyStorePassword = keyStoreE.getAttributeValue("password");
}
Iterator<Element> appdefElements = top.getElementsByName(APPDEF);
while (appdefElements.hasNext()) {
Element appdefE = appdefElements.next();
String name = appdefE.getAttributeValue("name");
String className = appdefE.getAttributeValue("class");
if (name!=null && className!=null) {
List<URL> libraries = new ArrayList<URL>();
Iterator<Element> libraryElements = appdefE.getElementsByName(LIBRARY);
while (libraryElements.hasNext()) {
Element libE = libraryElements.next();
String href = libE.getAttributeValue("href");
if (href!=null) {
URI u = libE.getBaseURI().resolve(href);
libraries.add(u.toURL());
}
}
try {
Class cdef = null;
if (libraries.size()==0) {
cdef = this.getClass().forName(className);
} else {
URL [] list = new URL[libraries.size()];
list = libraries.toArray(list);
ClassLoader urlLoader = new URLClassLoader(list,this.getClass().getClassLoader());
cdef = urlLoader.loadClass(className);
}
AppDef def = new AppDef(name,cdef);
appDefs.put(name,def);
} catch (ClassNotFoundException ex) {
throw new XMLException("Cannot find class: "+ex.getMessage(),ex);
}
}
}
Iterator<Element> interfaceElements = top.getElementsByName(INTERFACE);
while (interfaceElements.hasNext()) {
Element interfaceE = interfaceElements.next();
String addr = interfaceE.getAttributeValue("address");
String portS = interfaceE.getAttributeValue("port");
boolean secure = interfaceE.getAttributeValue("secure")==null || "true".equals(interfaceE.getAttributeValue("secure"));
int port = portS==null ? (secure ? 443 : 80) : Integer.parseInt(portS);
Interface iface = new Interface(addr,port,secure);
interfaces.add(iface);
Iterator<Element> links = interfaceE.getElementsByName(LINK);
while (links.hasNext()) {
Element linkE = links.next();
String href = linkE.getAttributeValue("href");
if (href!=null) {
URI tlocation = linkE.getBaseURI().resolve(href);
String mtype = linkE.getAttributeValue("type");
Link l = new Link(linkE.getAttributeValue("rel"),mtype==null ? null : MediaType.valueOf(mtype),tlocation);
l.setIdentity(linkE.getAttributeValue("username"),linkE.getAttributeValue("password"));
if (l.getRelation()!=null) {
iface.getLinks().put(l.getRelation(),l);
}
}
}
Iterator<Element> hostElements = interfaceE.getElementsByName(HOST);
while (hostElements.hasNext()) {
Element hostE = hostElements.next();
Host host = createHost(hostE);
iface.getHosts().put(host.getName(),host);
}
}
}
public long getAutoConfigurationCheckWait() {
return autoconfCheck;
}
public File getKeyStorePath()
{
return keyStorePath;
}
public String getKeyStorePassword()
{
return keyStorePassword;
}
public List<Interface> getInterfaces() {
return interfaces;
}
public void setKeyStorePath(File keyStorePath)
{
this.keyStorePath = keyStorePath;
}
public void setKeyStorePassword(String keyStorePassword)
{
this.keyStorePassword = keyStorePassword;
}
}