Author: gtrasuk Date: Fri Sep 2 21:31:08 2011 New Revision: 1164717 URL: http://svn.apache.org/viewvc?rev=1164717&view=rev Log: Continuing work on classloading for surrogate modules and overall configuration system for container. Added: river/jtsk/skunk/surrogate/docs/Bootstrap.txt river/jtsk/skunk/surrogate/src/org/apache/river/container/PropertiesFileReader.java river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/ river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/Strings.java river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/WorkingDirFileConfiguration.java river/jtsk/skunk/surrogate/test/org/apache/river/container/PropertiesFileReaderTest.java river/jtsk/skunk/surrogate/testfiles/property-file-reader-test.properties Modified: river/jtsk/skunk/surrogate/docs/ServiceStarterServices.txt river/jtsk/skunk/surrogate/nbproject/build-impl.xml river/jtsk/skunk/surrogate/nbproject/genfiles.properties river/jtsk/skunk/surrogate/nbproject/project.properties river/jtsk/skunk/surrogate/nbproject/project.xml river/jtsk/skunk/surrogate/src/org/apache/river/container/Context.java river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties river/jtsk/skunk/surrogate/src/org/apache/river/container/ProfileConfigReader.java river/jtsk/skunk/surrogate/src/org/apache/river/container/StarterServiceDeployer.java river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java river/jtsk/skunk/surrogate/src/org/apache/river/container/classloading/VirtualFileSystemClassLoader.java river/jtsk/skunk/surrogate/src/org/apache/river/container/core-config.xml river/jtsk/skunk/surrogate/test/org/apache/river/container/CommonsVFSTest.java river/jtsk/skunk/surrogate/test/org/apache/river/container/classloading/VFSClassLoaderTest.java river/jtsk/skunk/surrogate/test/org/apache/river/surrogate/SurrogateContextTest.java Added: river/jtsk/skunk/surrogate/docs/Bootstrap.txt URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/docs/Bootstrap.txt?rev=1164717&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/docs/Bootstrap.txt (added) +++ river/jtsk/skunk/surrogate/docs/Bootstrap.txt Fri Sep 2 21:31:08 2011 @@ -0,0 +1,26 @@ + +The bootstrap process looks like this: + +- The bootstrapper creates the overall container context object +- Core configuration is read from the classpath at "o.a.r.c.core-config.xml". +- Each component called out in the core configuration is instantiated and put +into the context. +- The core config includes component callouts for the following: + - AnnotatedClassDeployer, which sets up dependency injection for the container + components. + - CommandLineArgumentParser, which reads the command line and sets appropriate + values into the context (mainly the profile directory). + - MBeanRegistrar, which takes note of any manageable components placed in + the context, and registers them with the MBeanContainer. + - ShutdownListener, which acts as an MBean to allow shutdown of the + container from a JMX console. + - FileUtilityImpl, which provides file services to other components. + - PropertiesFileReader, which reads all the '.properties' files in the + profile directory, and puts them into the context under their file names. + - This facility allows components to simply declare a Properties object + and use the @Injected annotation to get their config files loaded. + - ProfileConfigReader, which reads the profile configuration and + sets up all the components in that config. + - The profile configuration is subject to more editing and customization + than the core config. + Modified: river/jtsk/skunk/surrogate/docs/ServiceStarterServices.txt URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/docs/ServiceStarterServices.txt?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/docs/ServiceStarterServices.txt (original) +++ river/jtsk/skunk/surrogate/docs/ServiceStarterServices.txt Fri Sep 2 21:31:08 2011 @@ -33,12 +33,11 @@ Packaging the Service Implementation ------------------------------------ Deployment jar file contains: -- Service jar files -- jar files for codebase +- Service jar files, in the "lib" directory. +- jar files for codebase, in the "lib-dl" directory. - Configuration file - - Indicates the service class and the name of the permissions file, as - well as which jars are part of the codebase and classpath. -- deployment descriptor. + - Indicates the service class and the name of the permissions file +- deployment descriptor (e.g. 'transient-reggie.config'). - Permissions file (defines maximum permissions required) The file should be named ending in a '.ssar' extension (service starter archive) @@ -48,13 +47,12 @@ default/deploy/reggie.ssar). Deployment ---------- When the starter service deployer finds the archive, it: -- unpacks the archive into a working directory - Creates a classloader that includes the jar files called out in the starter service deployer's configuration file (this will typically include 'jsk-platform.jar', 'jdk-lib.jar', and 'RiverContainerLiaison.jar', plus the -jar files referenced in the deployed service's 'service.properties' file. This +jar files contained in the deployed service's 'lib' directory. This classloader will be annotated with a codebase that allows all the jar files in -the deployer config file's codebase element, plus all the jar files called out -in the service configuration file. +the deployer config file's codebase element, plus all the jar files contained +in the service's 'lib-dl' directory. - Registers the appropriate codebase files with the codebase service. -- Instantiates the service and runs it. \ No newline at end of file +- Instantiates the service and runs it (on a separate thread from the deployer). Modified: river/jtsk/skunk/surrogate/nbproject/build-impl.xml URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/nbproject/build-impl.xml?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/nbproject/build-impl.xml (original) +++ river/jtsk/skunk/surrogate/nbproject/build-impl.xml Fri Sep 2 21:31:08 2011 @@ -54,8 +54,52 @@ is divided into following sections: + + + + + + + + + + + + + + + + + + + + + + + + + + Must set platform.home + Must set platform.bootcp + Must set platform.java + Must set platform.javac + + The J2SE Platform is not correctly set up. + Your active platform is: ${platform.active}, but the corresponding property "platforms.${platform.active}.home" is not found in the project's properties files. + Either open the project in the IDE and setup the Platform with the same name or add it manually. + For example like this: + ant -Duser.properties.file=<path_to_property_file> jar (where you put the property "platforms.${platform.active}.home" in a .properties file) + or ant -Dplatforms.${platform.active}.home=<path_to_JDK_home> jar (where no properties file is used) + - + + + + + + + + @@ -70,8 +114,14 @@ is divided into following sections: + + + + + + @@ -84,41 +134,42 @@ is divided into following sections: - - - - - - - - - - - - + - + - + - + - + - + + + + + + + + + + + + + @@ -173,8 +224,8 @@ is divided into following sections: - + @@ -219,7 +270,7 @@ is divided into following sections: - + @@ -258,7 +309,7 @@ is divided into following sections: - + @@ -302,7 +353,9 @@ is divided into following sections: - + + + @@ -312,7 +365,8 @@ is divided into following sections: - + + @@ -328,11 +382,56 @@ is divided into following sections: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + @@ -343,6 +442,9 @@ is divided into following sections: + + + @@ -358,7 +460,9 @@ is divided into following sections: - + + + @@ -383,7 +487,7 @@ is divided into following sections: - + @@ -408,7 +512,7 @@ is divided into following sections: - + @@ -427,6 +531,7 @@ is divided into following sections: + @@ -442,7 +547,7 @@ is divided into following sections: - + @@ -571,10 +676,10 @@ is divided into following sections: - + - + @@ -583,44 +688,53 @@ is divided into following sections: - To run this application from the command line without Ant, try: + To run this application from the command line without Ant, try: - java -cp "${run.classpath.with.dist.jar}" ${main.class} + ${platform.java} -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + - + - - - - - - - To run this application from the command line without Ant, try: + + + + + + + To run this application from the command line without Ant, try: - java -jar "${dist.jar.resolved}" + ${platform.java} -jar "${dist.jar.resolved}" - - - - - - - To run this application from the command line without Ant, try: - - java -jar "${dist.jar.resolved}" + + + + + - + + + + + + + + + + + Must select one file in the IDE or set profile.class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + @@ -731,7 +912,7 @@ is divided into following sections: - + @@ -746,7 +927,7 @@ is divided into following sections: - + Must select some files in the IDE or set javac.includes Modified: river/jtsk/skunk/surrogate/nbproject/genfiles.properties URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/nbproject/genfiles.properties?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/nbproject/genfiles.properties (original) +++ river/jtsk/skunk/surrogate/nbproject/genfiles.properties Fri Sep 2 21:31:08 2011 @@ -3,9 +3,9 @@ build.xml.script.CRC32=8dea2037 build.xml.stylesheet.CRC32=28e38971@1.38.2.45 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=092f50fa -nbproject/build-impl.xml.script.CRC32=b9aa5753 -nbproject/build-impl.xml.stylesheet.CRC32=229523de@1.38.3.45 +nbproject/build-impl.xml.data.CRC32=123acd6d +nbproject/build-impl.xml.script.CRC32=c953017f +nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45 nbproject/management-build-impl.xml.data.CRC32=318d2fde nbproject/management-build-impl.xml.script.CRC32=630dcf8f nbproject/management-build-impl.xml.stylesheet.CRC32=545273be@1.1 Modified: river/jtsk/skunk/surrogate/nbproject/project.properties URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/nbproject/project.properties?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/nbproject/project.properties (original) +++ river/jtsk/skunk/surrogate/nbproject/project.properties Fri Sep 2 21:31:08 2011 @@ -1,92 +1,97 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -application.title=surrogate -application.vendor=trasukg -build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=build -build.generated.dir=${build.dir}/generated -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=${dist.dir}/RiverSurrogate.jar -dist.javadoc.dir=${dist.dir}/javadoc -endorsed.classpath= -#endorsed.classpath=\ -# ${libs.JAXB-ENDORSED.classpath} -excludes= -includes=** -jar.archive.disabled=${jnlp.enabled} -jar.compress=false -jar.index=${jnlp.enabled} -javac.classpath=\ - ${libs.ApacheRiverPlatform.classpath}:\ - ${libs.ApacheRiverLib.classpath}:\ - ${libs.ApacheCommonsLogging-1_1_1.classpath}:\ - ${libs.ApacheCommonsVFS-1_0.classpath} -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=false -javac.processorpath=\ - ${javac.classpath}:\ - ${libs.JavaCC.classpath}:\ - ${libs.jaxb.classpath} -javac.source=1.5 -javac.target=1.5 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.junit_4.classpath} -javac.test.processorpath=\ - ${javac.test.classpath} -javadoc.additionalparam= -javadoc.author=false -javadoc.encoding=${source.encoding} -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=false -javadoc.windowtitle= -jaxbwiz.gensrc.classpath=${libs.jaxb.classpath} -jaxbwiz.xjcdef.classpath=${libs.jaxb.classpath} -jaxbwiz.xjcrun.classpath=${libs.jaxb.classpath} -jnlp.codebase.type=no.codebase -jnlp.descriptor=application -jnlp.enabled=false -jnlp.mixed.code=defaut -jnlp.offline-allowed=false -jnlp.signed=false -main.class=org.apache.river.container.Bootstrap -manifest.file=manifest.mf -meta.inf.dir=${src.dir}/META-INF -platform.active=default_platform -run.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.ApacheRiverServices.classpath} -# Space-separated list of JVM arguments used when running the project -# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value -# or test-sys-prop.name=value to set system properties for unit tests): -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=surrogate +application.vendor=trasukg +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/RiverSurrogate.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +#endorsed.classpath=\ +# ${libs.JAXB-ENDORSED.classpath} +excludes= +includes=** +jar.archive.disabled=${jnlp.enabled} +jar.compress=false +jar.index=${jnlp.enabled} +javac.classpath=\ + ${libs.ApacheCommonsLogging-1_1_1.classpath}:\ + ${libs.ApacheCommonsVFS-1_0.classpath}:\ + ${libs.ApacheRiverLib.classpath}:\ + ${libs.ApacheRiverPlatform.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath}:\ + ${libs.JavaCC.classpath}:\ + ${libs.jaxb.classpath} +javac.source=1.6 +javac.target=1.6 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit_4.classpath} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +jaxbwiz.gensrc.classpath=${libs.jaxb.classpath} +jaxbwiz.xjcdef.classpath=${libs.jaxb.classpath} +jaxbwiz.xjcrun.classpath=${libs.jaxb.classpath} +jnlp.codebase.type=web +jnlp.codebase.url=$$$$codebase +jnlp.descriptor=application +jnlp.enabled=false +jnlp.mixed.code=default +jnlp.offline-allowed=false +jnlp.signed=false +jnlp.signing= +jnlp.signing.alias= +jnlp.signing.keystore= +main.class=org.apache.river.container.Bootstrap +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=JDK_1.6 +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.ApacheRiverServices.classpath} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test Modified: river/jtsk/skunk/surrogate/nbproject/project.xml URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/nbproject/project.xml?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/nbproject/project.xml (original) +++ river/jtsk/skunk/surrogate/nbproject/project.xml Fri Sep 2 21:31:08 2011 @@ -4,6 +4,7 @@ RiverSurrogate + Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Context.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Context.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/Context.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Context.java Fri Sep 2 21:31:08 2011 @@ -28,7 +28,6 @@ import java.util.Map; * @author trasukg */ public class Context { - ClassLoader rootClassLoader=null; Map contents=new HashMap(); List listeners=new ArrayList(); @@ -57,6 +56,15 @@ public class Context { } } + /** + Retrieve an object from the context. + @param name Name of the object. + @return + */ + public Object get(String name) { + return contents.get(name); + } + /** Called by the bootstrapper to tell us that processing of the initialization file is now complete. Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/MessageNames.java Fri Sep 2 21:31:08 2011 @@ -50,6 +50,7 @@ public class MessageNames { CONTEXT_ITEM = "contextItem", EXCEPTION_THROWN="exceptionThrown", FAILED_DEPLOY_SERVICE="failedDeployService", + FAILED_READ_PROPERTIES="failedReadProperties", ILLEGAL_ARGUMENT_EXCEPTION="illegalArgumentException", ILLEGAL_ACCESS_EXCEPTION="illegalAccessException", INITIALIZATION_EXCEPTION="initializationException", Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties Fri Sep 2 21:31:08 2011 @@ -29,6 +29,7 @@ configuredClasspath=The configured class contextItem=Context key {0} refers to ''{1}''. exceptionThrown=Exception thrown: failedDeployService=Deployment of service archive at ''{0}'' failed. +failedReadProperties=Failed to read one or more properties files. illegalArgumentException=An operation threw an IllegalArgumentException. illegalAccessException=An operation threw an IllegalAccessException. invalidClasspathEntry=Invalid classpath entry: {0} Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/ProfileConfigReader.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/ProfileConfigReader.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/ProfileConfigReader.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/ProfileConfigReader.java Fri Sep 2 21:31:08 2011 @@ -14,7 +14,9 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */package org.apache.river.container; + */ + +package org.apache.river.container; import java.io.File; import java.io.FileInputStream; Added: river/jtsk/skunk/surrogate/src/org/apache/river/container/PropertiesFileReader.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/PropertiesFileReader.java?rev=1164717&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/PropertiesFileReader.java (added) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/PropertiesFileReader.java Fri Sep 2 21:31:08 2011 @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.river.container; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.apache.commons.vfs.FileObject; +import org.apache.commons.vfs.FileSystemException; +import org.apache.commons.vfs.FileType; + +/** + * + * @author trasukg + */ +public class PropertiesFileReader { + + @Injected + Context context = null; + @Injected + FileUtility fileUtility = null; + + @Init + public void initialize() { + try { + FileObject[] childFiles = fileUtility.getProfileDirectory().getChildren(); + for (FileObject fo: childFiles) { + if (fo.getName().getBaseName().endsWith(Strings.DOT_PROPERTIES) + && fo.getType()==FileType.FILE) { + readPropertiesFile(fo); + } + } + } catch (Exception ex) { + throw new LocalizedRuntimeException(ex, + MessageNames.BUNDLE_NAME, MessageNames.FAILED_READ_PROPERTIES); + } + } + + private void readPropertiesFile(FileObject fo) throws FileSystemException, IOException { + String name=fo.getName().getBaseName(); + InputStream is=fo.getContent().getInputStream(); + Properties props=new Properties(); + props.load(is); + context.put(name, props); + } +} Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/StarterServiceDeployer.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/StarterServiceDeployer.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/StarterServiceDeployer.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/StarterServiceDeployer.java Fri Sep 2 21:31:08 2011 @@ -23,9 +23,11 @@ package org.apache.river.container; import java.io.IOException; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.vfs.FileObject; +import org.apache.river.container.classloading.VirtualFileSystemClassLoader; /** * @@ -35,16 +37,17 @@ public class StarterServiceDeployer { private static final Logger log= Logger.getLogger(StarterServiceDeployer.class.getName(), MessageNames.BUNDLE_NAME); @Injected private FileUtility fileUtility=null; - + @Injected private ClassLoader systemClassLoader=null; @Name private String myName=null; @Injected() private String deploymentDirectory=null; + @Injected(Strings.STARTER_SERVICE_DEPLOYER_PROPERTIES) + Properties configProperties=null; + private FileObject deploymentDirectoryFile=null; - private FileObject workingDirectory=null; - @Init public void init() { try { tryInitialize(); @@ -56,8 +59,6 @@ public class StarterServiceDeployer { private void tryInitialize() throws IOException { log.log(Level.INFO, MessageNames.STARTER_SERVICE_DEPLOYER_STARTING, myName); - /* Setup the working directory. */ - workingDirectory = fileUtility.getWorkingDirectory(myName); /* Establish the deployment directory. */ deploymentDirectoryFile = fileUtility.getProfileDirectory() .resolveFile(deploymentDirectory); @@ -66,9 +67,6 @@ public class StarterServiceDeployer { new Object[] {deploymentDirectory,fileUtility.getProfileDirectory()}); } /* Read the maximal policy file if there is one. */ - /* Read the configuration file for minimal codebase and - discovery options. - */ /* Go through the deployment directory looking for services to deploy. */ FileObject[] serviceArchives= @@ -101,8 +99,10 @@ public class StarterServiceDeployer { } private void deployService(FileObject serviceJar) { - /* Unpack the jar into working dir. */ /* Create the service classloader. */ + VirtualFileSystemClassLoader cl= + new VirtualFileSystemClassLoader(null, systemClassLoader); + /* Include platform jars from the container's lib directory. */ /* Register the service's codebase jars with the codebase service. */ /* Setup the classloader's codebase annotation. */ /* Grant the appropriate permissions to the service's classloader and Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Strings.java Fri Sep 2 21:31:08 2011 @@ -35,8 +35,10 @@ public class Strings { DEFAULT_DISCOVERY_CONTEXT = "defaultDiscoveryContext", DOT=".", DOT_CLASS=".class", + DOT_PROPERTIES=".properties", DOT_SSAR=".ssar", EMPTY = "", + FILE_UTILITY="fileUtility", INIT_COMPLETE="initComplete", NAME="name", PROFILE = "profile", @@ -45,6 +47,7 @@ public class Strings { SSAR="ssar", SET = "set", SLASH="/", + STARTER_SERVICE_DEPLOYER_PROPERTIES="service-starter.properties", TYPE="type", WHITESPACE_SEPARATORS=" \t\n\r", WORK="work"; Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/classloading/VirtualFileSystemClassLoader.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/classloading/VirtualFileSystemClassLoader.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/classloading/VirtualFileSystemClassLoader.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/classloading/VirtualFileSystemClassLoader.java Fri Sep 2 21:31:08 2011 @@ -53,6 +53,12 @@ public class VirtualFileSystemClassLoade } void addClassPathEntry(String fileName) { + + addClassPathEntry(fileSystemRoot, fileName); + } + + void addClassPathEntry(FileObject fileRoot, String fileName) { + try { /* Classpath entry is a jar file with filter expressions that can be understood by ClasspathFilterBuilder. */ @@ -60,9 +66,9 @@ public class VirtualFileSystemClassLoade */ ClasspathFilter filter=new ClasspathFilterBuilder().parseToFilter(fileName); - FileObject entryObject = fileSystemRoot.resolveFile(filter.getJarName()); + FileObject entryObject = fileRoot.resolveFile(filter.getJarName()); FileObject entryFileSystem= - fileSystemRoot.getFileSystem().getFileSystemManager() + fileRoot.getFileSystem().getFileSystemManager() .createFileSystem(entryObject); classpathEntries.add(new ClasspathEntry(filter, entryFileSystem)); } catch (FileSystemException ex) { Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/core-config.xml URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/core-config.xml?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/core-config.xml (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/core-config.xml Fri Sep 2 21:31:08 2011 @@ -49,6 +49,7 @@ + Added: river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/Strings.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/Strings.java?rev=1164717&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/Strings.java (added) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/Strings.java Fri Sep 2 21:31:08 2011 @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.river.container.liaison; + +/** + * + Strings used in the liaison to the container. This is a separate class + from org.apache.container.Strings even though there are duplicates, so that + we can pull org.apache.river.container.liaison into its own jar and include + that standalone into the contained application's classpath. + * @author trasukg + */ +public class Strings { + public static final String + DASH="-", + ERROR_CLOSING_FILE="Error Closing File"; +} Added: river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/WorkingDirFileConfiguration.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/WorkingDirFileConfiguration.java?rev=1164717&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/WorkingDirFileConfiguration.java (added) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/liaison/WorkingDirFileConfiguration.java Fri Sep 2 21:31:08 2011 @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.river.container.liaison; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; +import net.jini.config.Configuration; +import net.jini.config.ConfigurationException; +import net.jini.config.ConfigurationFile; +import net.jini.config.ConfigurationNotFoundException; + +/** + * + * @author trasukg + */ +public class WorkingDirFileConfiguration + implements Configuration { + + private static File workingDirectory=null; + + private static Map specialEntries= + new HashMap(); + + private Configuration delegate=null; + + /** Inject the working directory for this application. This injection is + done using reflection by the ServiceStarterDeployer when the application + is setup. This way, the Configuration can be loaded without any hard-coded + directories, etc. + @param workingDirectory + */ + public static void setWorkingDirectory(File workingDirectory) { + WorkingDirFileConfiguration.workingDirectory = workingDirectory; + } + + public static File getWorkingDirectory() { + return workingDirectory; + } + /** + Set the value of a 'Special Entry' as defined in ConfigurationFile, that + can be accessed within the configuration by using the '$entryName' + construct. + @param name The name of the special entry, which must start with '$'. + @param o The object to store. + */ + public static void putSpecialEntry(String name, Object o) { + specialEntries.put(name, o); + } + + public WorkingDirFileConfiguration(String[] options, ClassLoader cl) throws ConfigurationException { + + /* no options; just delegate. */ + if (options == null || options.length==0) { + delegate=new MyConfigurationFile(options, cl); + return; + } + + /* No file called for; just delegate. */ + if (Strings.DASH.equals(options[0])) { + delegate = new MyConfigurationFile(options, cl); + return; + } + + /* Else, find the configuration file inside the working directory and + open it. + TODO: Should probably check to make sure that the supplied file + name does not include absolute path or '..' path, i.e. make sure + that the resolved file is actually a descendant of the working + directory. + */ + File configFile=new File(workingDirectory, options[0]); + Reader reader=null; + try { + reader=new FileReader(configFile); + delegate = new MyConfigurationFile(reader, options, cl); + } catch (FileNotFoundException ex) { + throw new ConfigurationNotFoundException(options[0], ex); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ex) { + throw new ConfigurationException(Strings.ERROR_CLOSING_FILE, ex); + } + } + } + + } + + public Object getEntry(String component, String name, Class type) throws ConfigurationException { + return delegate.getEntry(component, name, type); + } + + public Object getEntry(String component, String name, Class type, Object defaultValue) throws ConfigurationException { + return delegate.getEntry(component, name, type, defaultValue); + } + + public Object getEntry(String component, String name, Class type, Object defaultValue, Object data) throws ConfigurationException { + return delegate.getEntry(component, name, type, defaultValue, data); + } + + private static class MyConfigurationFile extends ConfigurationFile { + + public MyConfigurationFile(Reader reader, String[] overrides, ClassLoader cl) throws ConfigurationException { + super(reader, overrides, cl); + } + + public MyConfigurationFile(String[] options, ClassLoader cl) throws ConfigurationException { + super(options, cl); + } + + @Override + protected Object getSpecialEntry(String name) throws ConfigurationException { + if (specialEntries.containsKey(name)) { + return specialEntries.get(name); + } + return super.getSpecialEntry(name); + } + + @Override + protected Class getSpecialEntryType(String name) throws ConfigurationException { + if (specialEntries.containsKey(name)) { + return specialEntries.get(name).getClass(); + } + return super.getSpecialEntryType(name); + } + + + } +} Modified: river/jtsk/skunk/surrogate/test/org/apache/river/container/CommonsVFSTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/CommonsVFSTest.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/CommonsVFSTest.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/CommonsVFSTest.java Fri Sep 2 21:31:08 2011 @@ -17,6 +17,7 @@ */ package org.apache.river.container; +import org.junit.Ignore; import java.io.File; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; @@ -30,12 +31,13 @@ import org.junit.Test; import static org.junit.Assert.*; /** - * + * +Exploratory tests to understand and document the behavior of Commons-VFS * @author trasukg */ public class CommonsVFSTest { - FileSystemManager fileSystemManager=null; + FileSystemManager fileSystemManager = null; public CommonsVFSTest() { } @@ -50,7 +52,7 @@ public class CommonsVFSTest { @Before public void setUp() throws FileSystemException { - fileSystemManager=VFS.getManager(); + fileSystemManager = VFS.getManager(); } @@ -59,30 +61,66 @@ public class CommonsVFSTest { } /** - Should be able to get the current directory, and it should end with - 'testfiles/testroot'. - @throws Exception + Should be able to get the current directory, and it should end with + 'testfiles/testroot'. + @throws Exception */ @Test public void testBaseFile() throws Exception { - FileObject fo=fileSystemManager.resolveFile(new File("."),"."); + FileObject fo = fileSystemManager.resolveFile(new File("."), "."); System.out.println("fo=" + fo); assertTrue(fo.toString().endsWith("testfiles/testroot")); } /** - Make sure we can use the jar:syntax to get to the 'start.properties' file - inside the constructed reggie module jar. + Make sure we can use the jar:syntax to get to the 'start.properties' file + inside the constructed reggie module jar. */ @Test public void testFileInReggieModuleJar() throws Exception { - FileObject reggieJar= + FileObject reggieJar = fileSystemManager.resolveFile(new File("../../build/test/files"), "reggie-module.jar"); - assertTrue("Bad file:" + reggieJar.toString(),reggieJar.toString().endsWith("reggie-module.jar")); - FileObject reggieJarFS=fileSystemManager.createFileSystem(reggieJar); + assertTrue("Bad file:" + reggieJar.toString(), reggieJar.toString().endsWith("reggie-module.jar")); + FileObject reggieJarFS = fileSystemManager.createFileSystem(reggieJar); - FileObject startProperties=reggieJarFS.resolveFile("start.properties"); + FileObject startProperties = reggieJarFS.resolveFile("start.properties"); assertNotNull(startProperties); assertTrue("Properties file unreadable:" + startProperties.toString() + " type=" + startProperties.getType(), startProperties.isReadable()); } + + /** + If we create a virtual file system based on a jar file, we should be + able to add other jar files by adding junctions to the root, with the name + of the file we're adding. + + + Unfortunately, this theory doesn't pan out... + org.apache.commons.vfs.FileSystemException: Attempting to create a nested junction at "null/otherStart.properties". Nested junctions are not supported. + at org.apache.commons.vfs.impl.VirtualFileSystem.addJunction(VirtualFileSystem.java:111) + + */ + @Test @Ignore /*Didin't work, see above */ + public void testFileSystemJunctions() throws Exception { + FileObject reggieJar = + fileSystemManager.resolveFile(new File("../../build/test/files"), "reggie-module.jar"); + assertTrue("Bad file:" + reggieJar.toString(), reggieJar.toString().endsWith("reggie-module.jar")); + FileObject reggieJarFS = fileSystemManager.createFileSystem(reggieJar); + + FileObject virtRoot = fileSystemManager.createVirtualFileSystem((String) null); + virtRoot.getFileSystem().addJunction("/", reggieJarFS); + checkPresentAndReadable(virtRoot, "start.properties"); + FileObject startProperties = virtRoot.resolveFile("start.properties"); + assertNotNull(startProperties); + assertTrue("Properties file unreadable:" + startProperties.toString() + " type=" + startProperties.getType(), startProperties.isReadable()); + + /* Now try to add in a junction to a jar file */ + virtRoot.getFileSystem().addJunction("otherStart.properties", startProperties); + checkPresentAndReadable(virtRoot, "otherStart.properties"); + } + + void checkPresentAndReadable(FileObject root, String name) throws FileSystemException { + FileObject fo = root.resolveFile(name); + assertNotNull(fo); + assertTrue("File unreadable:" + fo.toString() + " type=" + fo.getType(), fo.isReadable()); + } } \ No newline at end of file Added: river/jtsk/skunk/surrogate/test/org/apache/river/container/PropertiesFileReaderTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/PropertiesFileReaderTest.java?rev=1164717&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/PropertiesFileReaderTest.java (added) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/PropertiesFileReaderTest.java Fri Sep 2 21:31:08 2011 @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.river.container; + +import java.util.Properties; +import java.io.File; +import org.apache.commons.vfs.FileSystemManager; +import java.io.IOException; +import org.apache.commons.vfs.FileObject; +import org.apache.commons.vfs.VFS; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author trasukg + */ +public class PropertiesFileReaderTest { + + public PropertiesFileReaderTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + PropertiesFileReader UUT = new PropertiesFileReader(); + Context context = new Context(); + FileUtility fileUtility = new MockFileUtility(); + + @Before + public void setUp() { + context.put(new AnnotatedClassDeployer()); + context.put(Strings.FILE_UTILITY, fileUtility); + context.put(UUT); + } + + @After + public void tearDown() { + } + + /** + Check that the MockFileUtility returns the profile directory as the + 'testfiles' dir. + @throws Exception + */ + @Test + public void testMockFileUtility() throws Exception { + FileObject fo=fileUtility.getProfileDirectory(); + + System.out.println("fo=" + fo); + assertTrue(fo.toString().endsWith("testfiles")); + } + + /** + When setup in the context, the config file reader should scan the profile + directory for files ending in ".properties", and create a Properties object + based on each file. As such, we should be able to just read the properties + from the context. + */ + @Test + public void testReader() { + Properties testProps=(Properties) + context.get("property-file-reader-test.properties"); + assertNotNull("property-file-reader-test.properties wasn't loaded.", + testProps); + + assertEquals("Expected message=Hello World", "Hello World", + testProps.getProperty("message")); + } + + @Test + public void testPropertiesInjection() throws Exception { + AnnotatedTestHarness harness=new AnnotatedTestHarness(); + context.put(harness); + + assertNotNull("property-file-reader-test.properties wasn't loaded.", + harness.props); + + assertEquals("Expected message=Hello World", "Hello World", + harness.props.getProperty("message")); + + } + + private class AnnotatedTestHarness { + + @Injected("property-file-reader-test.properties") + Properties props=null; + + } + + private class MockFileUtility implements FileUtility { + + @Override + public FileObject getWorkingDirectory(String name) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public FileObject getProfileDirectory() throws IOException { + FileSystemManager fileSystemManager=VFS.getManager(); + FileObject fo = fileSystemManager.resolveFile(new File("."), ".."); + + return fo; + } + } +} Modified: river/jtsk/skunk/surrogate/test/org/apache/river/container/classloading/VFSClassLoaderTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/classloading/VFSClassLoaderTest.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/classloading/VFSClassLoaderTest.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/classloading/VFSClassLoaderTest.java Fri Sep 2 21:31:08 2011 @@ -85,14 +85,15 @@ public class VFSClassLoaderTest { /** Create a VFSClassLoader and make sure it throws an exception if we try to add a non-existent jar file to it. + Also, test out the addClassPathEntry(root, fileName) method. @throws Exception */ @Test public void testNonExistentJarFile() throws Exception { VirtualFileSystemClassLoader UUT = - new VirtualFileSystemClassLoader(reggieModuleRoot, extensionLoader); + new VirtualFileSystemClassLoader(null, extensionLoader); try { - UUT.addClassPathEntry("nonexistent.jar"); + UUT.addClassPathEntry(reggieModuleRoot, "nonexistent.jar"); fail("Should have thrown an invalid classpath entry exception"); } catch (LocalizedRuntimeException ex) { assertEquals(MessageNames.INVALID_CLASSPATH_ENTRY, ex.getMessageKey()); Modified: river/jtsk/skunk/surrogate/test/org/apache/river/surrogate/SurrogateContextTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/surrogate/SurrogateContextTest.java?rev=1164717&r1=1164716&r2=1164717&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/surrogate/SurrogateContextTest.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/surrogate/SurrogateContextTest.java Fri Sep 2 21:31:08 2011 @@ -55,23 +55,14 @@ public class SurrogateContextTest { public void tearDown() { } - /** - * We should be able to point the context at a jar file - * and have it unpack the file in preparation for serving the - * surrogate out of that unpacked directory. - */ - @Test - public void testJarUnpack() { - fail("Implement me"); - } - @Test /** Make sure that the jar containing our test surrogate is actually there. It should be built by the "-post-compile-test" target in 'build.xml'. */ public void testThatTestJarIsPresent() { - File testJar=new File("build/test/files/sample-surrogate.jar"); + System.out.println("Working dir is " + new File(".").getAbsolutePath()); + File testJar=new File("../../build/test/files/sample-surrogate.jar"); assertTrue("No test jar present", testJar.exists()); } } \ No newline at end of file Added: river/jtsk/skunk/surrogate/testfiles/property-file-reader-test.properties URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/testfiles/property-file-reader-test.properties?rev=1164717&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/testfiles/property-file-reader-test.properties (added) +++ river/jtsk/skunk/surrogate/testfiles/property-file-reader-test.properties Fri Sep 2 21:31:08 2011 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one + # or more contributor license agreements. See the NOTICE file + # distributed with this work for additional information + # regarding copyright ownership. The ASF licenses this file + # to you under the Apache License, Version 2.0 (the + # "License"); you may not use this file except in compliance + # with the License. You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # + +message=Hello World +