From: <fxp...@us...> - 2011-05-26 06:52:42
|
Revision: 7765 http://geonetwork.svn.sourceforge.net/geonetwork/?rev=7765&view=rev Author: fxprunayre Date: 2011-05-26 06:52:33 +0000 (Thu, 26 May 2011) Log Message: ----------- Add Jeevlet engine to run GeoNetwork as a RESTLET application. In that environment, you could run many catalogues with only one GeoNetwork installation. Each catalogue are defined using a WEB-INF-NodeId directory and started as a GeoNetworkRestletApplication according to that configuration. All catalogues are sharing the Managers (eg. ThesaurusManager, SchemaManager) but not the configuration (eg. DB, DataDir, LuceneDir). Made by Jean-Pascal Boignard and Mathieu Coudert. Added Paths: ----------- sandbox/GeoSource/branches/jeevlet/ sandbox/GeoSource/branches/jeevlet/bin/ sandbox/GeoSource/branches/jeevlet/bin/add2lib.bat sandbox/GeoSource/branches/jeevlet/bin/jeevlet.properties sandbox/GeoSource/branches/jeevlet/bin/log4j.cfg sandbox/GeoSource/branches/jeevlet/bin/logs/ sandbox/GeoSource/branches/jeevlet/bin/shutdown.bat sandbox/GeoSource/branches/jeevlet/bin/shutdown.sh sandbox/GeoSource/branches/jeevlet/bin/startup.bat sandbox/GeoSource/branches/jeevlet/bin/startup.sh sandbox/GeoSource/branches/jeevlet/pom.xml sandbox/GeoSource/branches/jeevlet/src/ sandbox/GeoSource/branches/jeevlet/src/main/ sandbox/GeoSource/branches/jeevlet/src/main/java/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/JeevletEngine.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/JeevletSession.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/dispatchers/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/dispatchers/JeevletServiceManager.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/sources/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/sources/JeevletServiceRequest.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/sources/JeevletServiceRequestFactory.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/sources/http/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/sources/http/Jeevlet.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/GeoNetworkRestletApplication.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/GeoNetworkStopperApplication.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/StarterAuto.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/StopperAuto.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/constants/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/constants/Config.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/exception/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/exception/JeevletException.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/representation/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/representation/BlobRepresentation.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/representation/JDomRepresentation.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/representation/JeevletRepresentation.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/representation/OutputStreamRepresentation.java sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/utils/ sandbox/GeoSource/branches/jeevlet/src/main/java/jeevlet/utils/ConfigUtils.java Added: sandbox/GeoSource/branches/jeevlet/bin/add2lib.bat =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/add2lib.bat (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/add2lib.bat 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1 @@ +SET PROJECT_LIB=%PROJECT_LIB%;%1 \ No newline at end of file Added: sandbox/GeoSource/branches/jeevlet/bin/jeevlet.properties =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/jeevlet.properties (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/jeevlet.properties 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,27 @@ +# Properties for Jeevlet engine offering capability to start +# many instances. + +# Application port (default: 8080) +app_port = 8082 + +# Listening port to stop the application (default: 8079) +listen_port = 8079 + +# GeoNetwork webapp directory +# WEB-INF-* folders will be use to start and configure all instances +#app_path = D:\\project\\GeoSource_multiAd\\geosource_2.3.0\\web\\geonetwork +# app_path = /home/mcoudert/applications/geosource_multi/web/geonetwork +#app_path = /home/francois/Neogeo3/Workspace/Catalogue/GS-MN/web/target/geonetwork +app_path = /path/to/your/geonetwork/webapp + +# Host name +host_domain = localhost + +# Garbage collection frequency in seconds (ie. 300s = 5 mn) +interval = 300 + +# Session timeout before deletion in seconds (1800s = .5 hour) +duration = 1800 + +# Node prefix (eg. WEB-INF-SAVOIE will be startup with catalogue-SAVOIE as base url) +node_prefix = catalogue Property changes on: sandbox/GeoSource/branches/jeevlet/bin/jeevlet.properties ___________________________________________________________________ Added: svn:executable + * Added: sandbox/GeoSource/branches/jeevlet/bin/log4j.cfg =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/log4j.cfg (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/log4j.cfg 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,13 @@ +.level=WARNING + +log4j.logger.jeevlet.starter = DEBUG, console, jeevlet + +log4j.appender.jeevlet =org.apache.log4j.DailyRollingFileAppender +log4j.appender.jeevlet.DatePattern='.'yyyy-MM-dd +log4j.appender.jeevlet.file = logs/jeevlet.log +log4j.appender.jeevlet.layout = org.apache.log4j.PatternLayout +log4j.appender.jeevlet.layout.ConversionPattern=%d{ISO8601} %-5p [%c] - %m%n + +log4j.appender.console = org.apache.log4j.ConsoleAppender +log4j.appender.console.layout = org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%c] - %m%n Added: sandbox/GeoSource/branches/jeevlet/bin/shutdown.bat =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/shutdown.bat (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/shutdown.bat 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,11 @@ +set JEEVLET_LIB=..\target +set GEONETWORK_LIB=..\..\web\target + +FOR %%f IN (%JEEVLET_LIB%\*.jar) DO CALL add2lib %%f +FOR %%f IN (%GEONETWORK_LIB%\WEB-INF\lib\*.jar) DO CALL add2lib %%f + +SET CLASSPATH=%PROJECT_LIB% + +java -classpath %CLASSPATH% jeevlet.StopperAuto + +exit Added: sandbox/GeoSource/branches/jeevlet/bin/shutdown.sh =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/shutdown.sh (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/shutdown.sh 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,7 @@ +JEEVLET_LIB=../target +GEONETWORK_LIB=../../web/target + +for jarFile in $JEEVLET_LIB/*.jar; do CLASSPATH="$CLASSPATH:$jarFile"; done +for jarFile in $GEONETWORK_LIB/geonetwork/WEB-INF/lib/*.jar; do CLASSPATH="$CLASSPATH:$jarFile"; done + +java -classpath $CLASSPATH jeevlet.StopperAuto Property changes on: sandbox/GeoSource/branches/jeevlet/bin/shutdown.sh ___________________________________________________________________ Added: svn:executable + * Added: sandbox/GeoSource/branches/jeevlet/bin/startup.bat =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/startup.bat (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/startup.bat 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,17 @@ +# Add all libs to classpath +set JEEVLET_LIB=..\target +set JEEVLET_DEP_LIB=%JEEVLET_LIB%\lib +set GEONETWORK_LIB=..\..\web\target + +FOR %%f IN (%JEEVLET_LIB%\*.jar) DO CALL add2lib %%f +FOR %%f IN (%JEEVLET_DEP_LIB%\*.jar) DO CALL add2lib %%f +FOR %%f IN (%GEONETWORK_LIB%\*.jar) DO CALL add2lib %%f +FOR %%f IN (%GEONETWORK_LIB%\geonetwork\WEB-INF\lib*.jar) DO CALL add2lib %%f + +SET CLASSPATH=%PROJECT_LIB% + +# FIXME : Remove Xalan from classpath because it may be used by Jeeves.TransformerFactoryFactory and cause XSL issues +del $JEEVLET_DEP_LIB\xalan-*.jar + +# Start the app +java -Xms128m -Xmx1024m -XX:MaxPermSize=128m -classpath %CLASSPATH% jeevlet.StarterAuto %1% Added: sandbox/GeoSource/branches/jeevlet/bin/startup.sh =================================================================== --- sandbox/GeoSource/branches/jeevlet/bin/startup.sh (rev 0) +++ sandbox/GeoSource/branches/jeevlet/bin/startup.sh 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,18 @@ + +# Add all libs to classpath +JEEVLET_LIB=../target +JEEVLET_DEP_LIB=$JEEVLET_LIB/lib +GEONETWORK_LIB=../../web/target +#GEONETWORK_LIB=/home/francois/Neogeo3/Workspace/Catalogue/GS-MN/web/target +for f in $JEEVLET_LIB/*.jar; do CLASSPATH=$CLASSPATH:$f; done +for f in $JEEVLET_DEP_LIB/*.jar; do CLASSPATH=$CLASSPATH:$f; done +for f in ../lib/*.jar; do CLASSPATH=$CLASSPATH:$f; done +for f in $GEONETWORK_LIB/*.jar; do CLASSPATH=$CLASSPATH:$f; done +for f in $GEONETWORK_LIB/geonetwork/WEB-INF/lib/*.jar; do CLASSPATH=$CLASSPATH:$f; done +echo $CLASSPATH + +# FIXME : Remove Xalan from classpath because it may be used by Jeeves.TransformerFactoryFactory and cause XSL issues +rm $JEEVLET_DEP_LIB/xalan-*.jar + +# Start the app +java -Xms128m -Xmx1024m -XX:MaxPermSize=128m -classpath $CLASSPATH jeevlet.StarterAuto `pwd` $* Property changes on: sandbox/GeoSource/branches/jeevlet/bin/startup.sh ___________________________________________________________________ Added: svn:executable + * Added: sandbox/GeoSource/branches/jeevlet/pom.xml =================================================================== --- sandbox/GeoSource/branches/jeevlet/pom.xml (rev 0) +++ sandbox/GeoSource/branches/jeevlet/pom.xml 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,149 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.geonetwork-opensource</groupId> + <artifactId>geonetwork</artifactId> + <version>2.7.0-SNAPSHOT</version> + </parent> + + + <groupId>org.geonetwork-opensource</groupId> + <artifactId>jeevlet</artifactId> + <packaging>jar</packaging> + <name>Jeevlet modules</name> + <description>Jeevlet project is based on Jeeves and RESTLET in order to start many GeoNetwork + nodes in one application.</description> + <developers> + <developer> + <name>Jean-Pascal Boignard</name> + <roles> + <role>Initial development</role> + <role>Main contributor</role> + </roles> + </developer> + <developer> + <name>Mathieu Coudert</name> + <roles> + <role>Initial development</role> + <role>Main contributor</role> + </roles> + </developer> + <developer> + <name>François Prunayre</name> + <roles> + <role>Maven module</role> + </roles> + </developer> + </developers> + <licenses> + <license> + <name>Lesser General Public License (LGPL)</name> + <url>http://www.gnu.org/copyleft/lesser.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + + <dependencies> + <dependency> + <groupId>org.restlet.jse</groupId> + <artifactId>org.restlet</artifactId> + <version>${restlet.version}</version> + </dependency> + <dependency> + <groupId>org.restlet.jse</groupId> + <artifactId>org.restlet.ext.fileupload</artifactId> + <version>${restlet.version}</version> + </dependency> + + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + </dependency> + <dependency> + <groupId>commons-fileupload</groupId> + <artifactId>commons-fileupload</artifactId> + </dependency> + <dependency> + <groupId>commons-dbcp</groupId> + <artifactId>commons-dbcp</artifactId> + </dependency> + <dependency> + <groupId>commons-pool</groupId> + <artifactId>commons-pool</artifactId> + </dependency> + <dependency> + <groupId>org.mortbay.jetty</groupId> + <artifactId>jetty</artifactId> + </dependency> + <dependency> + <groupId>jsch</groupId> + <artifactId>jsch</artifactId> + </dependency> + <dependency> + <groupId>org.apache.xmlgraphics</groupId> + <artifactId>fop</artifactId> + </dependency> + <dependency> + <groupId>org.apache.jcs</groupId> + <artifactId>jcs</artifactId> + </dependency> + <dependency> + <groupId>net.sf.saxon</groupId> + <artifactId>saxon</artifactId> + </dependency> + <dependency> + <groupId>globus</groupId> + <artifactId>cog-jglobus</artifactId> + </dependency> + <dependency> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </dependency> + <dependency> + <groupId>xml-resolver</groupId> + <artifactId>xml-resolver</artifactId> + </dependency> + <dependency> + <groupId>org.geonetwork-opensource</groupId> + <artifactId>jeeves</artifactId> + <version>${pom.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.2</version> + <executions> + <execution> + <id>copy-dependencies</id> + <phase>install</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <outputDirectory>${project.build.directory}/lib</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + <!-- TODO add assembly task to pack the release. --> + </plugins> + </build> + + <properties> + <restlet.version>2.0.0</restlet.version> + </properties> + +</project> Added: sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/JeevletEngine.java =================================================================== --- sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/JeevletEngine.java (rev 0) +++ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/JeevletEngine.java 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,658 @@ +//============================================================================== +//=== +//=== JeevletEngine +//=== +//============================================================================= +//=== Copyright (C) 2010-2011 BRGM +//=== +//=== This library is free software; you can redistribute it and/or +//=== modify it under the terms of the GNU Lesser General Public +//=== License as published by the Free Software Foundation; either +//=== version 2.1 of the License, or (at your option) any later version. +//=== +//=== This library is distributed in the hope that it will be useful, +//=== but WITHOUT ANY WARRANTY; without even the implied warranty of +//=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +//=== Lesser General Public License for more details. +//=== +//=== You should have received a copy of the GNU Lesser General Public +//=== License along with this library; if not, write to the Free Software +//=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +//=== +//=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, +//=== Rome - Italy. email: Geo...@fa... +//============================================================================== + +package jeeves; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; +import javax.xml.transform.TransformerFactory; +import jeeves.constants.ConfigFile; +import jeeves.constants.Jeeves; +import jeeves.exceptions.BadInputEx; +import jeeves.interfaces.Activator; +import jeeves.interfaces.ApplicationHandler; +import jeeves.interfaces.Logger; +import jeeves.server.JeevesEngine; +import jeeves.server.ScheduleManager; +import jeeves.server.UserSession; +import jeeves.server.context.ServiceContext; +import jeeves.server.dispatchers.JeevletServiceManager; +import jeeves.server.resources.ProviderManager; +import jeeves.server.sources.JeevletServiceRequest; +import jeeves.utils.Log; +import jeeves.utils.SerialFactory; +import jeeves.utils.Util; +import jeeves.utils.Xml; +import jeevlet.exception.JeevletException; + +import org.apache.log4j.PropertyConfigurator; +import org.jdom.Element; + +//============================================================================= + +/** + * This is the main class. It handles http connections and inits the system. + * + * Most of the code is similar to {@link JeevesEngine}. (TODO : could be improved probably) + * + * @author Jean-Pascal Boignard + * @author Mathieu Coudert + */ + +public class JeevletEngine { + private String defaultSrv; + private String profilesFile; + private String defaultLang; + private String defaultContType; + private String uploadDir; + private int maxUploadSize; + private String appPath; + private boolean defaultLocal; + private boolean debugFlag; + + /** true if the 'general' part has been loaded */ + private boolean generalLoaded; + + private JeevletServiceManager serviceMan = new JeevletServiceManager(); + private ProviderManager providerMan = new ProviderManager(); + private ScheduleManager scheduleMan = new ScheduleManager(); + private SerialFactory serialFact = new SerialFactory(); + + private Logger appHandLogger = Log.createLogger(Log.APPHAND); + private List appHandList = new ArrayList(); + private Vector vAppHandlers = new Vector(); + private Vector vActivators = new Vector(); + + private String nodeId = ""; + + // --------------------------------------------------------------------------- + // --- + // --- Init + // --- + // --------------------------------------------------------------------------- + + /** + * Inits the engine, loading all needed data + * + * FIXME use nodeId on object creation + */ + public void init(String appPath, String configPath, String baseUrl, + String nodeId) throws JeevletException { + try { + this.appPath = appPath; + + long start = System.currentTimeMillis(); + + long maxMem = Runtime.getRuntime().maxMemory() / 1024; + long totMem = Runtime.getRuntime().totalMemory() / 1024; + long freeMem = Runtime.getRuntime().freeMemory() / 1024; + + long usedMem = totMem - freeMem; + long startFreeMem = maxMem - usedMem; + + // Config file per adherent because configPath <> + PropertyConfigurator.configure(configPath + "log4j.cfg"); + + info("=== Starting system ========================================"); + + // --------------------------------------------------------------------- + // --- init system + + info("Engine : " + this.getClass().getName()); + info("Java version : " + System.getProperty("java.vm.version")); + info("Java vendor : " + System.getProperty("java.vm.vendor")); + info("XSLT factory : " + + TransformerFactory.newInstance().newTransformer() + .getClass().getName()); + + info("Path : " + appPath); + info("BaseURL : " + baseUrl); + + serviceMan.setAppPath(appPath); + serviceMan.setProviderMan(providerMan); + serviceMan.setSerialFactory(serialFact); + serviceMan.setBaseUrl(baseUrl); + + scheduleMan.setAppPath(appPath); + scheduleMan.setProviderMan(providerMan); + scheduleMan.setSerialFactory(serialFact); + scheduleMan.setBaseUrl(baseUrl); + + loadConfigFile(configPath, Jeeves.CONFIG_FILE, serviceMan); + + info("Initializing profiles..."); + serviceMan.loadProfiles(profilesFile, nodeId); + + // --- handlers must be started here because they may need the + // context + // --- with the ProfileManager already loaded + + for (int i = 0; i < appHandList.size(); i++) + initAppHandler((Element) appHandList.get(i)); + + info("Starting schedule manager..."); + scheduleMan.start(); + + // --------------------------------------------------------------------- + + long end = System.currentTimeMillis(); + long duration = (end - start) / 1000; + + freeMem = Runtime.getRuntime().freeMemory() / 1024; + totMem = Runtime.getRuntime().totalMemory() / 1024; + usedMem = totMem - freeMem; + + long endFreeMem = maxMem - usedMem; + long dataMem = startFreeMem - endFreeMem; + + info("Memory used is : " + dataMem + " Kb"); + info("Total memory is : " + maxMem + " Kb"); + info("Startup time is : " + duration + " (secs)"); + + info("=== System working ========================================="); + } catch (Exception e) { + fatal("Raised exception during init"); + fatal(" Exception : " + e); + fatal(" Message : " + e.getMessage()); + fatal(" Stack : " + Util.getStackTrace(e)); + + throw new JeevletException("Exception raised", e); + } + } + + // --------------------------------------------------------------------------- + + private void loadConfigFile(String path, String file, + JeevletServiceManager serviceMan) throws Exception { + file = path + file; + + info("Loading : " + file); + + Element configRoot = Xml.loadFile(file); + + Element elGeneral = configRoot.getChild(ConfigFile.Child.GENERAL); + Element elDefault = configRoot.getChild(ConfigFile.Child.DEFAULT); + + if (!generalLoaded) { + if (elGeneral == null) + throw new NullPointerException( + "Missing 'general' element in config file :" + file); + + if (elDefault == null) + throw new NullPointerException( + "Missing 'default' element in config file :" + file); + + generalLoaded = true; + + initGeneral(elGeneral, serviceMan); + initDefault(elDefault, serviceMan); + } else { + if (elGeneral != null) + throw new IllegalArgumentException( + "Illegal 'general' element in secondary include"); + + if (elDefault != null) + throw new IllegalArgumentException( + "Illegal 'default' element in secondary include"); + } + + // --- init resources + + List resList = configRoot.getChildren(ConfigFile.Child.RESOURCES); + + for (int i = 0; i < resList.size(); i++) + initResources((Element) resList.get(i)); + + // --- init app-handlers + + appHandList + .addAll(configRoot.getChildren(ConfigFile.Child.APP_HANDLER)); + + // --- init services + + List srvList = configRoot.getChildren(ConfigFile.Child.SERVICES); + + for (int i = 0; i < srvList.size(); i++) + initServices((Element) srvList.get(i)); + + // --- init schedules + + List schedList = configRoot.getChildren(ConfigFile.Child.SCHEDULES); + + for (int i = 0; i < schedList.size(); i++) + initSchedules((Element) schedList.get(i)); + + // --- recurse on includes + + List includes = configRoot.getChildren(ConfigFile.Child.INCLUDE); + + for (int i = 0; i < includes.size(); i++) { + Element include = (Element) includes.get(i); + + loadConfigFile(path, include.getText(), serviceMan); + } + } + + // --------------------------------------------------------------------------- + // --- + // --- 'general' element + // --- + // --------------------------------------------------------------------------- + + /** + * Setup parameters from config tag (config.xml) + */ + + private void initGeneral(Element general, JeevletServiceManager serviceMan) + throws BadInputEx { + info("Initializing general configuration..."); + + profilesFile = Util + .getParam(general, ConfigFile.General.Child.PROFILES); + uploadDir = Util.getParam(general, ConfigFile.General.Child.UPLOAD_DIR); + try { + maxUploadSize = Integer.parseInt(Util.getParam(general, + ConfigFile.General.Child.MAX_UPLOAD_SIZE)); + } catch (Exception e) { + maxUploadSize = 50; + error("Maximum upload size not properly configured in config.xml. Using default size of 50MB"); + error(" Exception : " + e); + error(" Message : " + e.getMessage()); + error(" Stack : " + Util.getStackTrace(e)); + } + + if (!new File(uploadDir).isAbsolute()) + uploadDir = appPath + uploadDir; + + if (!uploadDir.endsWith("/")) + uploadDir += "/"; + + new File(uploadDir).mkdirs(); + + debugFlag = "true".equals(general + .getChildText(ConfigFile.General.Child.DEBUG)); + + serviceMan.setUploadDir(uploadDir); + serviceMan.setMaxUploadSize(maxUploadSize); + } + + // --------------------------------------------------------------------------- + // --- + // --- 'general' element + // --- + // --------------------------------------------------------------------------- + + /** + * Setup parameters from config tag (config.xml) + */ + + private void initDefault(Element defaults, JeevletServiceManager serviceMan) + throws Exception { + info("Initializing defaults..."); + + defaultSrv = Util.getParam(defaults, ConfigFile.Default.Child.SERVICE); + defaultLang = Util + .getParam(defaults, ConfigFile.Default.Child.LANGUAGE); + defaultContType = Util.getParam(defaults, + ConfigFile.Default.Child.CONTENT_TYPE); + + defaultLocal = "true".equals(defaults + .getChildText(ConfigFile.Default.Child.LOCALIZED)); + + info(" Default local is :" + defaultLocal); + + serviceMan.setDefaultLang(defaultLang); + serviceMan.setDefaultLocal(defaultLocal); + serviceMan.setDefaultContType(defaultContType); + + List errorPages = defaults.getChildren(ConfigFile.Default.Child.ERROR); + + for (int i = 0; i < errorPages.size(); i++) + serviceMan.addErrorPage((Element) errorPages.get(i)); + + Element gui = defaults.getChild(ConfigFile.Default.Child.GUI); + + if (gui != null) { + List guiElems = gui.getChildren(); + + for (int i = 0; i < guiElems.size(); i++) + serviceMan.addDefaultGui((Element) guiElems.get(i)); + } + } + + // --------------------------------------------------------------------------- + // --- + // --- 'resources' element + // --- + // --------------------------------------------------------------------------- + + /** + * Setup resources from the resource element (config.xml) + */ + + private void initResources(Element resources) { + info("Initializing resources..."); + + List resList = resources + .getChildren(ConfigFile.Resources.Child.RESOURCE); + + for (int i = 0; i < resList.size(); i++) { + Element res = (Element) resList.get(i); + + String name = res.getChildText(ConfigFile.Resource.Child.NAME); + String provider = res + .getChildText(ConfigFile.Resource.Child.PROVIDER); + Element config = res.getChild(ConfigFile.Resource.Child.CONFIG); + Element activator = res + .getChild(ConfigFile.Resource.Child.ACTIVATOR); + + String enabled = res + .getAttributeValue(ConfigFile.Resource.Attr.ENABLED); + + if ((enabled == null) || enabled.equals("true")) { + info(" Adding resource : " + name); + + try { + if (activator != null) { + String clas = activator + .getAttributeValue(ConfigFile.Activator.Attr.CLASS); + + info(" Loading activator : " + clas); + Activator activ = (Activator) Class.forName(clas) + .newInstance(); + + info(" Starting activator : " + clas); + activ.startup(appPath, activator); + + vActivators.add(activ); + } + + providerMan.register(provider, name, config); + } catch (Exception e) { + error("Raised exception while initializing resource. Skipped."); + error(" Resource : " + name); + error(" Provider : " + provider); + error(" Exception : " + e); + error(" Message : " + e.getMessage()); + error(" Stack : " + Util.getStackTrace(e)); + } + } + } + } + + // --------------------------------------------------------------------------- + // --- + // --- 'appHandler' element + // --- + // --------------------------------------------------------------------------- + + private void initAppHandler(Element handler) throws Exception { + if (handler == null) + info("Handler not found"); + else { + String className = handler + .getAttributeValue(ConfigFile.AppHandler.Attr.CLASS); + + if (className == null) + throw new IllegalArgumentException("Missing '" + + ConfigFile.AppHandler.Attr.CLASS + "' attribute in '" + + ConfigFile.Child.APP_HANDLER + "' element"); + + info("Found handler : " + className); + + Class c = Class.forName(className); + + ApplicationHandler h = (ApplicationHandler) c.newInstance(); + + ServiceContext srvContext = serviceMan + .createServiceContext("AppHandler"); + srvContext.setLanguage(defaultLang); + srvContext.setLogger(appHandLogger); + + try { + info("--- Starting handler --------------------------------------"); + + Object context = h.start(handler, srvContext); + + srvContext.getResourceManager().close(); + vAppHandlers.add(h); + serviceMan.registerContext(h.getContextName(), context); + scheduleMan.registerContext(h.getContextName(), context); + + info("--- Handler started ---------------------------------------"); + } catch (Exception e) { + error("Raised exception while starting appl handler. Skipped."); + error(" Handler : " + className); + error(" Exception : " + e); + error(" Message : " + e.getMessage()); + error(" Stack : " + Util.getStackTrace(e)); + + srvContext.getResourceManager().abort(); + } + } + } + + // --------------------------------------------------------------------------- + // --- + // --- 'services' element + // --- + // --------------------------------------------------------------------------- + + /** + * Setup services found in the services tag (config.xml) + */ + + private void initServices(Element services) throws Exception { + info("Initializing services..."); + + // --- get services root package + String pack = services + .getAttributeValue(ConfigFile.Services.Attr.PACKAGE); + + // --- scan services elements + List srvList = services.getChildren(ConfigFile.Services.Child.SERVICE); + + for (int i = 0; i < srvList.size(); i++) { + Element service = (Element) srvList.get(i); + String name = service + .getAttributeValue(ConfigFile.Service.Attr.NAME); + + info(" Adding service : " + name); + + try { + serviceMan.addService(pack, service); + } catch (Exception e) { + warning("Raised exception while registering service. Skipped."); + warning(" Service : " + name); + warning(" Package : " + pack); + warning(" Exception : " + e); + warning(" Message : " + e.getMessage()); + warning(" Stack : " + Util.getStackTrace(e)); + } + } + } + + // --------------------------------------------------------------------------- + // --- + // --- 'schedules' element + // --- + // --------------------------------------------------------------------------- + + /** + * Setup schedules found in the 'schedules' element (config.xml) + */ + + private void initSchedules(Element schedules) throws Exception { + info("Initializing schedules..."); + + // --- get schedules root package + String pack = schedules + .getAttributeValue(ConfigFile.Schedules.Attr.PACKAGE); + + // --- scan schedules elements + List schedList = schedules + .getChildren(ConfigFile.Schedules.Child.SCHEDULE); + + for (int i = 0; i < schedList.size(); i++) { + Element schedule = (Element) schedList.get(i); + String name = schedule + .getAttributeValue(ConfigFile.Schedule.Attr.NAME); + + info(" Adding schedule : " + name); + + try { + scheduleMan.addSchedule(pack, schedule); + } catch (Exception e) { + error("Raised exception while registering schedule. Skipped."); + error(" Schedule : " + name); + error(" Package : " + pack); + error(" Exception : " + e); + error(" Message : " + e.getMessage()); + error(" Stack : " + Util.getStackTrace(e)); + } + } + } + + // --------------------------------------------------------------------------- + // --- + // --- Destroy + // --- + // --------------------------------------------------------------------------- + + public void destroy() { + try { + info("=== Stopping system ========================================"); + + info("Stopping schedule manager..."); + scheduleMan.exit(); + + info("Stopping handlers..."); + stopHandlers(); + + info("Stopping resources..."); + stopResources(); + + info("=== System stopped ========================================"); + } catch (Exception e) { + error("Raised exception during destroy"); + error(" Exception : " + e); + error(" Message : " + e.getMessage()); + error(" Stack : " + Util.getStackTrace(e)); + } + } + + // --------------------------------------------------------------------------- + /** + * Stop handlers + */ + + private void stopHandlers() throws Exception { + for (int i = 0; i < vAppHandlers.size(); i++) { + ApplicationHandler h = (ApplicationHandler) vAppHandlers.get(i); + + h.stop(); + } + } + + // --------------------------------------------------------------------------- + /** + * Stop resources + */ + + private void stopResources() { + providerMan.end(); + + for (Iterator i = vActivators.iterator(); i.hasNext();) { + Activator a = (Activator) i.next(); + + info(" Stopping activator : " + a.getClass().getName()); + a.shutdown(); + } + } + + // --------------------------------------------------------------------------- + // --- + // --- API methods + // --- + // --------------------------------------------------------------------------- + + public String getUploadDir() { + return uploadDir; + } + + // --------------------------------------------------------------------------- + + public int getMaxUploadSize() { + return maxUploadSize; + } + + // --------------------------------------------------------------------------- + + public void dispatch(JeevletServiceRequest srvReq, UserSession session) { + if (srvReq.getService() == null || srvReq.getService().length() == 0) + srvReq.setService(defaultSrv); + + if (srvReq.getLanguage() == null || srvReq.getLanguage().length() == 0) + srvReq.setLanguage(defaultLang); + + srvReq.setDebug(srvReq.hasDebug() && debugFlag); + + // --- normal dispatch pipeline + + serviceMan.dispatch(srvReq, session); + } + + // --------------------------------------------------------------------------- + // --- + // --- Other private methods + // --- + // --------------------------------------------------------------------------- + + private void debug(String message) { + Log.debug(Log.ENGINE, message); + } + + private void info(String message) { + Log.info(Log.ENGINE, message); + } + + private void warning(String message) { + Log.warning(Log.ENGINE, message); + } + + private void error(String message) { + Log.error(Log.ENGINE, message); + } + + private void fatal(String message) { + Log.fatal(Log.ENGINE, message); + } +} + +// ============================================================================= + Added: sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/JeevletSession.java =================================================================== --- sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/JeevletSession.java (rev 0) +++ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/JeevletSession.java 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,43 @@ +//============================================================================= +//=== Copyright (C) 2010-2011 BRGM +//=== +//=== This library is free software; you can redistribute it and/or +//=== modify it under the terms of the GNU Lesser General Public +//=== License as published by the Free Software Foundation; either +//=== version 2.1 of the License, or (at your option) any later version. +//=== +//=== This library is distributed in the hope that it will be useful, +//=== but WITHOUT ANY WARRANTY; without even the implied warranty of +//=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +//=== Lesser General Public License for more details. +//=== +//=== You should have received a copy of the GNU Lesser General Public +//=== License along with this library; if not, write to the Free Software +//=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +//=== +//=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, +//=== Rome - Italy. email: Geo...@fa... +//============================================================================== + +package jeeves.server; + +import java.util.Date; + +public class JeevletSession extends UserSession { + + Date lastUsed = new Date(); + + public JeevletSession() { + super(); + // TODO Auto-generated constructor stub + } + + public Date getLastUsed() { + return lastUsed; + } + + public void setLastUsed(Date lastUsed) { + this.lastUsed = lastUsed; + } + +} Added: sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/dispatchers/JeevletServiceManager.java =================================================================== --- sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/dispatchers/JeevletServiceManager.java (rev 0) +++ sandbox/GeoSource/branches/jeevlet/src/main/java/jeeves/server/dispatchers/JeevletServiceManager.java 2011-05-26 06:52:33 UTC (rev 7765) @@ -0,0 +1,946 @@ +//============================================================================= +//=== Copyright (C) 2010-2011 BRGM +//=== +//=== This library is free software; you can redistribute it and/or +//=== modify it under the terms of the GNU Lesser General Public +//=== License as published by the Free Software Foundation; either +//=== version 2.1 of the License, or (at your option) any later version. +//=== +//=== This library is distributed in the hope that it will be useful, +//=== but WITHOUT ANY WARRANTY; without even the implied warranty of +//=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +//=== Lesser General Public License for more details. +//=== +//=== You should have received a copy of the GNU Lesser General Public +//=== License along with this library; if not, write to the Free Software +//=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +//=== +//=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, +//=== Rome - Italy. email: Geo...@fa... +//============================================================================== + +package jeeves.server.dispatchers; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; +import jeeves.constants.ConfigFile; +import jeeves.constants.Jeeves; +import jeeves.exceptions.JeevesException; +import jeeves.exceptions.ServiceNotAllowedEx; +import jeeves.exceptions.ServiceNotFoundEx; +import jeeves.exceptions.ServiceNotMatchedEx; +import jeeves.interfaces.Service; +import jeeves.server.ProfileManager; +import jeeves.server.ServiceConfig; +import jeeves.server.UserSession; +import jeeves.server.context.ServiceContext; +import jeeves.server.dispatchers.ErrorPage; +import jeeves.server.dispatchers.guiservices.Call; +import jeeves.server.dispatchers.guiservices.GuiService; +import jeeves.server.dispatchers.guiservices.XmlFile; +import jeeves.server.resources.ProviderManager; +import jeeves.server.sources.JeevletServiceRequest; +import jeeves.server.sources.ServiceRequest.InputMethod; +import jeeves.server.sources.ServiceRequest.OutputMethod; +import jeeves.utils.BLOB; +import jeeves.utils.BinaryFile; +import jeeves.utils.Log; +import jeeves.utils.SOAPUtil; +import jeeves.utils.SerialFactory; +import jeeves.utils.Util; +import jeeves.utils.Xml; +import jeevlet.representation.BlobRepresentation; +import jeevlet.representation.JDomRepresentation; +import jeevlet.representation.OutputStreamRepresentation; + +import org.jdom.Element; +import org.restlet.data.MediaType; +import org.restlet.representation.FileRepresentation; + +//============================================================================= + +public class JeevletServiceManager { + private Hashtable htServices = new Hashtable(100); + private Hashtable htContexts = new Hashtable(); + private Vector vErrorPipe = new Vector(); + private Vector vDefaultGui = new Vector(); + + private ProviderManager providMan; + private ProfileManager profilMan; + private SerialFactory serialFact; + + private String appPath; + private String baseUrl; + private String uploadDir; + private int maxUploadSize; + private String defaultLang; + private String defaultContType; + private boolean defaultLocal; + + // --------------------------------------------------------------------------- + // --- + // --- API methods + // --- + // --------------------------------------------------------------------------- + + public void setAppPath(String path) { + appPath = path; + } + + public void setDefaultLang(String lang) { + defaultLang = lang; + } + + public void setDefaultContType(String type) { + defaultContType = type; + } + + public void setUploadDir(String dir) { + uploadDir = dir; + } + + public void setMaxUploadSize(int size) { + maxUploadSize = size; + } + + public void setDefaultLocal(boolean yesno) { + defaultLocal = yesno; + } + + public void setProviderMan(ProviderManager p) { + providMan = p; + } + + public void setSerialFactory(SerialFactory s) { + serialFact = s; + } + + // --------------------------------------------------------------------------- + + public void setBaseUrl(String name) { + baseUrl = name; + + if (!baseUrl.startsWith("/") && baseUrl.length() != 0) + baseUrl = "/" + baseUrl; + } + + // --------------------------------------------------------------------------- + + public void loadProfiles(String file, String nodeId) throws Exception { + String webInfPath = Jeeves.Path.WEBINF; + if (nodeId != null && !nodeId.equals("")) + webInfPath = "WEB-INF-" + nodeId + "/"; + + profilMan = new ProfileManager(appPath + webInfPath + file); + } + + // --------------------------------------------------------------------------- + + public void registerContext(String name, Object context) { + htContexts.put(name, context); + } + + // --------------------------------------------------------------------------- + + public void addDefaultGui(Element gui) throws Exception { + vDefaultGui.add(getGuiService("", gui)); + } + + // --------------------------------------------------------------------------- + // --- + // --- Registering methods (service) + // --- + // --------------------------------------------------------------------------- + + public void addService(String pack, Element srv) throws Exception { + String name = srv.getAttributeValue(ConfigFile.Service.Attr.NAME); + String match = srv.getAttributeValue(ConfigFile.Service.Attr.MATCH); + String sheet = srv.getAttributeValue(ConfigFile.Service.Attr.SHEET); + String cache = srv.getAttributeValue(ConfigFile.Service.Attr.CACHE); + + ServiceInfo si = new ServiceInfo(appPath); + + si.setMatch(match); + si.setSheet(sheet); + si.setCache(cache); + + ArrayList al = (ArrayList) htServices.get(name); + + if (al == null) { + al = new ArrayList(); + htServices.put(name, al); + } + + al.add(si); + + // --- parse classes elements + + List classes = srv.getChildren(ConfigFile.Service.Child.CLASS); + + for (int i = 0; i < classes.size(); i++) + si.addService(buildService(pack, (Element) classes.get(i))); + + // --- parse output pages + + List outputs = srv.getChildren(ConfigFile.Service.Child.OUTPUT); + + for (int i = 0; i < outputs.size(); i++) + si.addOutputPage(buildOutputPage(pack, (Element) outputs.get(i))); + + // --- parse error pages + + List errors = srv.getChildren(ConfigFile.Service.Child.ERROR); + + for (int j = 0; j < errors.size(); j++) + si.addErrorPage(buildErrorPage((Element) errors.get(j))); + } + + // --------------------------------------------------------------------------- + + private Service buildService(String pack, Element clas) throws Exception { + // --- get class name + + String name = clas.getAttributeValue(ConfigFile.Class.Attr.NAME); + + if (name == null) + throw new IllegalArgumentException( + "Missing 'name' attrib in 'class' element"); + + if (name.startsWith(".")) + name = pack + name; + + // --- create instance + + Service service = (Service) Class.forName(name).newInstance(); + + service.init( + appPath, + new ServiceConfig(clas + .getChildren(ConfigFile.Class.Child.PARAM))); + + return service; + } + + // --------------------------------------------------------------------------- + + private OutputPage buildOutputPage(String pack, Element output) + throws Exception { + OutputPage outPage = new OutputPage(); + + outPage.setStyleSheet(output + .getAttributeValue(ConfigFile.Output.Attr.SHEET)); + outPage.setForward(output + .getAttributeValue(ConfigFile.Output.Attr.FORWARD)); + outPage.setTestCondition(output + .getAttributeValue(ConfigFile.Output.Attr.TEST)); + outPage.setFile(output.getAttributeValue(ConfigFile.Output.Attr.FILE) != null); + outPage.setBLOB(output.getAttributeValue(ConfigFile.Output.Attr.BLOB) != null); + + // --- set content type + + String contType = output + .getAttributeValue(ConfigFile.Output.Attr.CONTENT_TYPE); + + if (contType == null) + contType = defaultContType; + + outPage.setContentType(contType); + + // --- handle children + + List guiList = output.getChildren(); + + for (int i = 0; i < guiList.size(); i++) + outPage.addGuiService(getGuiService(pack, (Element) guiList.get(i))); + + return outPage; + } + + // --------------------------------------------------------------------------- + + private GuiService getGuiService(String pack, Element elem) + throws Exception { + if (ConfigFile.Output.Child.XML.equals(elem.getName())) + return new XmlFile(elem, defaultLang, defaultLocal); + + if (ConfigFile.Output.Child.CALL.equals(elem.getName())) + return new Call(elem, pack, appPath); + + throw new IllegalArgumentException("Unknown GUI element : " + + Xml.getString(elem)); + } + + // --------------------------------------------------------------------------- + + private ErrorPage buildErrorPage(Element err) throws Exception { + ErrorPage errPage = new ErrorPage(); + + errPage.setStyleSheet(err + .getAttributeValue(ConfigFile.Error.Attr.SHEET)); + errPage.setTestCondition(err + .getAttributeValue(ConfigFile.Error.Attr.ID)); + + // --- set content type + + String contType = err + .getAttributeValue(ConfigFile.Error.Attr.CONTENT_TYPE); + + if (contType == null) + contType = defaultContType; + + errPage.setContentType(contType); + + // -- set status code + int statusCode; + String strStatusCode = err + .getAttributeValue(ConfigFile.Error.Attr.STATUS_CODE); + + try { + statusCode = Integer.parseInt(strStatusCode); + } catch (Exception e) { + // Default value for an error page where status code is not defined. + statusCode = 500; + } + + errPage.setStatusCode(statusCode); + + // --- handle children + + List guiList = err.getChildren(); + + for (int i = 0; i < guiList.size(); i++) + errPage.addGuiService(getGuiService("?", (Element) guiList.get(i))); + + return errPage; + } + + // --------------------------------------------------------------------------- + // --- + // --- Registering methods (error) + // --- + // --------------------------------------------------------------------------- + + public void addErrorPage(Element err) throws Exception { + vErrorPipe.add(buildErrorPage(err)); + } + + // --------------------------------------------------------------------------- + + public ServiceContext createServiceContext(String name) { + ServiceContext context = new ServiceContext(name, providMan, + serialFact, profilMan, htContexts); + + context.setBaseUrl(baseUrl); + context.setLanguage("?"); + context.setUserSession(null); + context.setIpAddress("?"); + context.setAppPath(appPath); + context.setUploadDir(uploadDir); + context.setMaxUploadSize(maxUploadSize); + + return context; + } + + // --------------------------------------------------------------------------- + // --- + // --- Dispatching methods + // --- + // --------------------------------------------------------------------------- + + public void dispatch(JeevletServiceRequest req, UserSession session) { + // --- create the corresponding service request + + ServiceContext context = new ServiceContext(req.getService(), + providMan, serialFact, profilMan, htContexts); + + context.setBaseUrl(baseUrl); + context.setLanguage(req.getLanguage()); + context.setUserSession(session); + context.setIpAddress(req.getAddress()); + context.setAppPath(appPath); + context.setUploadDir(uploadDir); + context.setMaxUploadSize(maxUploadSize); + context.setInputMethod(req.getInputMethod()); + context.setOutputMethod(req.getOutputMethod()); + context.setHeaders(req.getHeaders()); + + // --- invoke service and build result + + Element response = null; + ServiceInfo srvInfo = null; + + try { + while (true) { + String srvName = req.getService(); + + info("Dispatching : " + srvName); + logParameters(req.getParams()); + + ArrayList al = (ArrayList) htServices.get(srvName); + + if (al == null) { + error("Service not found : " + srvName); + throw new ServiceNotFoundEx(srvName); + } + + for (int i = 0; i < al.size(); i++) { + ServiceInfo si = (ServiceInfo) al.get(i); + + if (si.matches(req.getParams())) { + srvInfo = si; + break; + } + } + + if (srvInfo == null) { + error("Service not matched in list : " + srvName); + throw new ServiceNotMatchedEx(srvName); + } + + // --------------------------------------------------------------------- + // --- check access + + String profile = ProfileManager.GUEST; + + if (session.isAuthenticated()) + profile = session.getProfile(); + + if (!profilMan.hasAccessTo(profile, srvName)) { + error("Service not allowed : " + srvName); + throw new ServiceNotAllowedEx(srvName); + } + + response = srvInfo.execServices(req.getParams(), context); + + // --------------------------------------------------------------------- + // --- handle forward + + OutputPage outPage = srvInfo.findOutputPage(response); + String forward = dispatchOutput(req, context, response, + outPage, srvInfo.isCacheSet()); + + if (forward == null) { + info(" -> dispatch ended for : " + srvName); + return; + } else { + info(" -> forwarding to : " + forward); + + Element elForward = new Element(Jeeves.Elem.FORWARD); + elForward.setAttribute(Jeeves.Attr.SERVICE, srvName); + + // --- send response to forwarded service request + + response.setName(Jeeves.Elem.REQUEST); + response.addContent(elForward); + + context.setService(forward); + req.setService(forward); + req.setParams(response); + } + } + } catch (Throwable e) { + handleError(req, response, context, srvInfo, e); + } + } + + // --------------------------------------------------------------------------- + // --- Handle error + // --------------------------------------------------------------------------- + + private void handleError(JeevletServiceRequest req, Element response, + ServiceContext context, ServiceInfo srvInfo, Throwable e) { + Element error = getError(req, e, response); + String id = error.getAttributeValue("id"); + int code = getErrorCode(e); + boolean cache = (srvInfo == null) ? false : srvInfo.isCacheSet(); + + debug("Raised exception while executing service\n" + + Xml.getString(error)); + + try { + InputMethod input = req.getInputMethod(); + OutputMethod output = req.getOutputMethod(); + + if (input == InputMethod.SOAP || output == OutputMethod.SOAP) { + req.setStatusCode(code); + req.beginStream("application/soap+xml; charset=UTF-8", cache); + + error.setAttribute("encodingStyle", + "http://www.geonetwork.org/encoding/error", + SOAPUtil.NAMESPACE_ENV); + + boolean sender = (code < 500); + String message = error.getChildText("class") + " : " + + error.getChildText("message"); + + // req.write(SOAPUtil.embedExc(error, sender, id, message)); + + // FIXME JDomRepresentation avec MediaType pour + // application/soap+xml, encodage utf8 et cache http + MediaType mt = new MediaType("application/soap+xml"); + JDomRepresentation rep = new JDomRepresentation( + SOAPUtil.embedExc(error, sender, id, message), mt, + cache); + req.setRepresentation(rep); + } + + else if (input == InputMethod.XML || output == OutputMethod.XML + || srvInfo == null) { + req.setStatusCode(code); + // req.beginStream("application/soap+xml; charset=UTF-8", + // cache); + // req.write(error); + + // JDomRepresentation MediaType application/soap+xml - encodage + // utf8 + JDomRepresentation rep = new JDomRepresentation(error, + new MediaType("application/xml"), cache); + req.setRepresentation(rep); + } + + else { + // --- try to dispatch to the error output + + ErrorPage errPage = (srvInfo != null) ? srvInfo + .findErrorPage(id) : null; + + if (errPage == null) + errPage = findErrorPage(id); + + try { + dispatchError(req, context, error, errPage, cache); + } catch (Exception ex) { + // --- ok, if we are here there is no error page + // --- so we display plain xml data + + req.setStatusCode(code); + // req.beginStream("application/xml; charset=UTF-8", cache); + // req.write(error); + + // JDomRepresentation avec encodage utf8 et cache http + JDomRepresentation rep = new JDomRepresentation(error, + cache); + req.setRepresentation(rep); + } + } + } catch (Exception ex) { + error("Raised exception while writing response to exception"); + error(" Exception : " + ex); + error(" Message : " + ex.getMessage()); + error(" Stack : " + Util.getStackTrace(ex)); + } + } + + // --------------------------------------------------------------------------- + // --- Dispatch output + // --------------------------------------------------------------------------- + + /** + * Takes a service's response and builds the output + */ + + private String dispatchOutput(JeevletServiceRequest req, + ServiceContext context, Element response, OutputPage outPage, + boolean cache) throws Exception { + info(" -> dispatching to output for : " + req.getService()); + + // ------------------------------------------------------------------------ + // --- check if the output page is a foward + + if (outPage != null) { + String sForward = outPage.getForward(); + + if (sForward != null) + return sForward; + } + + // ------------------------------------------------------------------------ + // --- write result to output page + + if (outPage == null) { + // --- if there is no output page we output the xml result (if any) + + if (response == null) + warning("Response is null and there is no output page for : " + + req.getService()); + else { + info(" -> writing xml for : " + req.getService()); + + // --- this logging is usefull for xml services that are called + // by javascript code + debug("Service xml is :\n" + Xml.getString(response)); + + InputMethod in = req.getInputMethod(); + OutputMethod out = req.getOutputMethod(); + + if (in == InputMethod.SOAP || out == OutputMethod.SOAP) { + // req.beginStream("application/soap+xml; charset=UTF-8", + // cache); + + if (!SOAPUtil.isEnvelope(response)) + response = SOAPUtil.embed(response); + + // FIXME JDomRepresentation avec MediaType pour + // application/soap+xml, encodage utf8 et cache http + MediaType mt = new MediaType("application/soap+xml"); + JDomRepresentation rep = new JDomRepresentation(response, + mt, cache); + req.setRepresentation(rep); + + } else { + // req.beginStream("application/xml; charset=UTF-8", cache); + JDomRepresentation rep = new JDomRepresentation(response, + cache); + req.setRepresentation(rep); + } + // req.write(response); + } + } + + // --- FILE output + + else if (outPage.isFile()) { + boolean autoDeleting = false; + // PDF Output + if (outPage.getContentType().equals("application/pdf") + && !outPage.getStyleSheet().equals("")) { + + // --- build the xml data for the XSL/FO translation + String styleSheet = outPage.getStyleSheet(); + Element guiElem = outPage.invokeGuiServices(context, response, + vDefaultGui); + + addPrefixes(guiElem, context.getLanguage(), req.getService()); + + Element rootElem = new Element(Jeeves.Elem.ROOT).addContent( + guiElem).addContent(response); + + Element reqElem = (Element) req.getParams().clone(); + reqElem.setName(Jeeves.Elem.REQUEST); + + rootElem.addContent(reqElem); + + // --- do an XSL transformation + + styleSheet = appPath + Jeeves.Path.XSL + styleSheet; + + if (!new File(styleSheet).exists()) + error(" -> stylesheet not found on disk, aborting : " + + styleSheet); + else { + info(" -> transforming with stylesheet : " + styleSheet); + + try { + // --- first we do the transformation + // ByteArrayOutputStream baos = new + // ByteArrayOutputStream(); + + String file = Xml.transformFOP(uploadDir, rootElem, + styleSheet); + response = BinaryFile.encode(200, file, "document.pdf", + true); + autoDeleting = true; + } catch (Exception e) { + error(" -> exception during XSL/FO transformation for : " + + req.getService()); + error(" -> (C) stylesheet : " + styleSheet); + error(" -> (C) message : " + e.getMessage()); + error(" -> (C) exception : " + + e.getClass().getSimpleName()); + + throw e; + } + + info(" -> end transformation for : " + req.getService()); + } + + } + String contentType = BinaryFile.getContentType(response); + + if (contentType == null) + contentType = "application/octet-stream"; + + // String contentDisposition = + // BinaryFile.getContentDisposition(response); + // String contentLength = BinaryFile.getContentLength(response); + // + // int cl = (contentLength == null) ? -1 : + // Integer.parseInt(contentLength); + // + // req.beginStream(contentType, cl, contentDisposition, cache); + // BinaryFile.write(response, req.getOutputStream()); + // req.endStream(); + // BinaryFile.removeIfTheCase(response); + + // FIXME FileRepresentation encodage utf8, contentDisposition, + // contentLength et cache http + String path = response.getAttributeValue("path"); + File f = new File(path); + FileRepresentation rep = new FileRepresentation(f, new MediaType( + contentType)); + rep.setAutoDeleting(autoDeleting); + req.setRepresentation(rep); + } + + // --- BLOB output + + else if (outPage.isBLOB()) { + String contentType = BLOB.getContentType(response); + + if (contentType == null) + contentType = "application/octet-stream"; + + // String contentDisposition = BLOB.getContentDisposition(response); + // String contentLength = BLOB.getContentLength(response); + // + // int cl = (contentLength == null) ? -1 : + // Integer.parseInt(contentLength); + // + // req.beginStream(contentType, cl, contentDisposition, cache); + // BLOB.write(response, req.getOutputStream()); + // req.endStream(); + + // FIXME Representation contentLength, contentDisposition, cache + // http + BlobRepresentation rep = new BlobRepresentation(response, + new MediaType(contentType), cache); + req.setRepresentation(rep); + + } + + // --- HTML/XML output + + else { + // --- build the xml data for the XSL translation + + String styleSheet = outPage.getStyleSheet(); + El... [truncated message content] |