package org.toobsframework.pres.app;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.jfree.ui.FilesystemFilter;
import org.toobsframework.exception.ParameterException;
import org.toobsframework.pres.app.config.Applications;
import org.toobsframework.pres.app.config.ComponentConfig;
import org.toobsframework.pres.app.config.ConfigLocation;
import org.toobsframework.pres.app.config.LayoutConfig;
import org.toobsframework.pres.app.config.ToobsApp;
import org.toobsframework.pres.app.config.XSLConfig;
import org.toobsframework.pres.app.controller.IAppView;
import org.toobsframework.pres.component.Component;
import org.toobsframework.pres.component.ComponentException;
import org.toobsframework.pres.component.config.Components;
import org.toobsframework.pres.component.datasource.api.DataSourceInitializationException;
import org.toobsframework.pres.component.datasource.manager.DataSourceNotFoundException;
import org.toobsframework.pres.component.manager.ComponentManager;
import org.toobsframework.pres.layout.ComponentLayoutInitializationException;
import org.toobsframework.pres.layout.RuntimeLayout;
import org.toobsframework.pres.layout.config.Layout;
import org.toobsframework.pres.layout.config.Layouts;
import org.toobsframework.pres.layout.manager.ComponentLayoutManager;
import org.toobsframework.transformpipeline.domain.XSLUriResolverImpl;
import org.toobsframework.util.IRequest;
public class AppManager implements AppReader {
private static final Log log = LogFactory.getLog(AppManager.class);
private static String appsDirName = "apps";
private static File appsDir;
private static Hashtable<String,ToobsApplication> appRegistry;
private static boolean initDone = false;
public AppManager() {
log.info("Constructing new AppLoader");
appRegistry = new Hashtable<String,ToobsApplication>();
try {
init();
initDone = true;
} catch (ComponentLayoutInitializationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean containsApp(String appRoot) {
return appRegistry.containsKey(appRoot);
}
public ToobsApplication getApp(String appRoot) throws AppNotFoundException {
ToobsApplication toobsApp = null;
if (!appRegistry.containsKey(appRoot)) {
throw new AppNotFoundException();
}
toobsApp = appRegistry.get(appRoot);
//synchronized(toobsApp) {
return toobsApp;
//}
}
public void init() throws ComponentLayoutInitializationException {
if ( appsDir == null || !appsDir.exists() ) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL appsUrl = classLoader.getResource(appsDirName);
if (appsUrl == null) {
log.warn("The Toobs Apps directory was not found");
return;
}
appsDir = new File(appsUrl.getFile());
if (log.isDebugEnabled()) {
log.debug("Apps dir " + appsDirName + " found at " + appsDir);
}
}
if (appsDir != null && appsDir.exists()) {
File[] apps = appsDir.listFiles();
File[] appList;
FilesystemFilter filter = new FilesystemFilter(".tapp.xml", "Toobs Application filter", false);
if (log.isDebugEnabled())
log.debug("Apps Dir Listing");
for ( int i = 0; i < apps.length; i++ ) {
if (log.isDebugEnabled()) {
log.debug(" App " + apps[i] + " isDir " + apps[i].isDirectory());
}
if (apps[i].isDirectory() && (appList = apps[i].listFiles(filter) ).length > 0) {
ToobsApplication toobsApp = new ToobsApplication();
for ( int j = 0; j < appList.length; j++ ) {
if (log.isDebugEnabled()) {
log.debug(" App config " + appList[j]);
}
toobsApp.setName(apps[i].getName());
configureApplication(toobsApp, apps[i], appList[j]);
}
}
}
}
}
private void configureApplication(ToobsApplication toobsApp, File appDir, File appFile) throws ComponentLayoutInitializationException {
InputStreamReader reader = null;
try {
reader = new InputStreamReader(new FileInputStream(appFile));
Unmarshaller unmarshaller = new Unmarshaller(
Class.forName(Applications.class.getName()));
unmarshaller.setValidation(false);
Applications applications = (Applications) unmarshaller.unmarshal(reader);
ToobsApp toobsAppDef = applications.getToobsApp(0);
configureRoot(toobsApp,toobsAppDef.getRoot());
configureXSL(toobsApp,toobsAppDef.getXSLConfig());
configureLayouts(toobsApp,toobsAppDef.getLayoutConfig(), appDir);
configureComponents(toobsApp,toobsAppDef.getComponentConfig(), appDir);
appRegistry.put(toobsApp.getRoot(), toobsApp);
} catch (MarshalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ValidationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ignore) { }
}
}
}
private void configureComponents(ToobsApplication toobsApp, ComponentConfig componentConfig, File appDir) {
//ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStreamReader reader = null;
Map<String,Component> compMap = new HashMap<String,Component>();
//String appPrefix = appsDirName + "/" + toobsApp.getName() + "/";
for ( int i = 0; i < componentConfig.getConfigLocationCount(); i++ ) {
ConfigLocation cLoc = componentConfig.getConfigLocation(i);
File compDir = null;
if (cLoc.isInApplication()) {
compDir = findDirInDir(appDir, cLoc.getDir());
} else {
compDir = findDirInClasspath(cLoc.getDir());
}
if (compDir == null) {
log.warn("Could not locate Layout configuration location: " + cLoc.getDir() + " for app: " + toobsApp.getName());
continue;
}
String fileName = null;
for ( int j = 0; j < cLoc.getConfigFile().length; j++) {
//fileName = appPrefix + cLoc.getConfigFile(j).getName();
fileName = compDir.getAbsolutePath() + "/" + cLoc.getConfigFile(j).getName();
/*
URL configFileURL = classLoader.getResource(fileName);
if (configFileURL == null) {
log.warn("Layout Configuration file " + fileName + " not found");
continue;
}
*/
File configFile = new File(fileName);
if (!configFile.exists()) {
log.warn("Layout Configuration file " + fileName + " not found");
continue;
}
try {
reader = new InputStreamReader(new FileInputStream(configFile));
Unmarshaller unmarshaller = new Unmarshaller(
Class.forName(Components.class.getName()));
unmarshaller.setValidation(false);
Components components = (Components) unmarshaller.unmarshal(reader);
org.toobsframework.pres.component.config.Component[] comps = components.getComponent();
if ((comps != null) && (comps.length > 0)) {
org.toobsframework.pres.component.config.Component compDef = null;
Component comp = null;
for (int k = 0; k < comps.length; k ++) {
compDef = comps[k];
comp = new Component();
ComponentManager.configureComponent(compDef, comp, fileName, compMap);
if (compMap.containsKey(compDef.getId())) {
log.warn("Overriding layout with Id: " + compDef.getId());
}
compMap.put(compDef.getId(), comp);
}
}
} catch (MarshalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ValidationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DataSourceInitializationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DataSourceNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
toobsApp.setComponents(compMap);
}
private void configureLayouts(ToobsApplication toobsApp, LayoutConfig layoutConfig, File appDir) throws ComponentLayoutInitializationException {
//ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStreamReader reader = null;
Map<String,RuntimeLayout> layoutMap = new HashMap<String,RuntimeLayout>();
//String appPrefix = appsDirName + "/" + toobsApp.getName() + "/";
for ( int i = 0; i < layoutConfig.getConfigLocationCount(); i++ ) {
ConfigLocation cLoc = layoutConfig.getConfigLocation(i);
if (log.isDebugEnabled()) {
log.debug("Layout Config location: " + cLoc.getDir());
}
File layoutDir = null;
if (cLoc.isInApplication()) {
layoutDir = findDirInDir(appDir, cLoc.getDir());
if (log.isDebugEnabled()) {
log.debug("Layout dir from dir: " + layoutDir.getPath());
}
} else {
layoutDir = findDirInClasspath(cLoc.getDir());
if (log.isDebugEnabled()) {
log.debug("Layout dir from cp: " + layoutDir.getPath());
}
}
if (layoutDir == null) {
log.warn("Could not locate Layout configuration location: " + cLoc.getDir() + " for app: " + toobsApp.getName());
continue;
}
String fileName = null;
for ( int j = 0; j < cLoc.getConfigFile().length; j++) {
//fileName = appPrefix + cLoc.getConfigFile(j).getName();
fileName = layoutDir.getAbsolutePath() + "/" + cLoc.getConfigFile(j).getName();
/*
URL configFileURL = classLoader.getResource(fileName);
if (configFileURL == null) {
log.warn("Layout Configuration file " + fileName + " not found");
continue;
}
*/
File configFile = new File(fileName);
if (!configFile.exists()) {
log.warn("Layout Configuration file " + fileName + " not found");
continue;
}
try {
reader = new InputStreamReader(new FileInputStream(configFile));
Unmarshaller unmarshaller = new Unmarshaller(
Class.forName(Layouts.class.getName()));
unmarshaller.setValidation(false);
Layouts componentLayoutConfig = (Layouts) unmarshaller.unmarshal(reader);
Layout[] layouts = componentLayoutConfig.getLayout();
if ((layouts != null) && (layouts.length > 0)) {
Layout compLayout = null;
RuntimeLayout layout = null;
for (int k = 0; k < layouts.length; k ++) {
compLayout = layouts[k];
layout = new RuntimeLayout();
ComponentLayoutManager.configureLayout(compLayout, layout, layoutMap);
if (layoutMap.containsKey(compLayout.getId())) {
log.warn("Overriding layout with Id: " + compLayout.getId());
}
layoutMap.put(compLayout.getId(), layout);
}
}
} catch (MarshalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ValidationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
toobsApp.setLayouts(layoutMap);
}
private File findDirInDir(File dir, String name) {
File[] tmp;
FilesystemFilter filter = new FilesystemFilter(name, "Toobs Layout filter", false);
if ( (tmp = dir.listFiles(filter)).length > 0 && tmp[0].isDirectory()) {
return tmp[0];
}
return null;
}
private File findDirInClasspath(String name) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return new File( classLoader.getResource(name).getFile() );
}
private void configureXSL(ToobsApplication toobsApp, XSLConfig config) {
String[] locations = new String[ config.getXSLLocationCount() ];
String appPrefix = appsDirName + "/" + toobsApp.getName() + "/";
for (int i = 0; i < locations.length; i++) {
locations[i] = (config.getXSLLocation(i).isInApplication() ? appPrefix : "") + config.getXSLLocation(i).getDir();
if (log.isDebugEnabled()) {
log.debug("App [" + toobsApp.getName() + "] - adding xsl location: " + locations[i]);
}
}
toobsApp.setXslLocations(locations);
}
private void configureRoot(ToobsApplication toobsApp, String root) {
if (root == null) {
toobsApp.setRoot("/" + toobsApp.getName().toLowerCase());
} else {
toobsApp.setRoot(root);
}
}
public String getAppsDirName() {
return appsDirName;
}
public void setAppsDirName(String appsDirName) {
this.appsDirName = appsDirName;
}
public void showApps() {
log.debug("Installed Applications");
Enumeration<String> keys = appRegistry.keys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
log.debug(" Installed App: " + key);
}
}
public String renderView(IAppView appView, IRequest request) throws AppNotFoundException, ComponentException, ParameterException {
if (appView.isComponentView()) {
return null;
} else {
RuntimeLayout layout = getApp(appView.getAppName()).getLayouts().get(appView.getViewName());
return layout.render(request, new XSLUriResolverImpl(getApp(appView.getAppName()).getXslLocations()));
}
}
}