knut 2004/11/11 06:13:45
Modified: . .classpath status.xml
src/documentation/content/xdocs site.xml dependencies.xml
links.ent
library build.xml
framework/src/java/org/apache/hivemind/impl
XmlModuleDescriptorProvider.java
framework/src/java/org/apache/hivemind/parse
XmlResourceProcessor.java
Added: library/src/test/org/apache/hivemind/lib/groovy
TestGroovyModuleDescriptorProvider.java
calculator.groovy TestHiveMindBuilder.java
missingModuleId.groovy basic.groovy
library/src/java/org/apache/hivemind/lib/groovy
GroovyScriptProcessor.java HiveMindBuilder.java
GroovyModuleDescriptorProvider.java
src/documentation/content/xdocs groovy.xml
Log:
added support for defining module descriptors using Groovy scripts
Revision Changes Path
1.42 +1 -1 jakarta-hivemind/.classpath
Index: .classpath
===================================================================
RCS file: /home/cvs/jakarta-hivemind/.classpath,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -r1.41 -r1.42
--- .classpath 7 Nov 2004 12:35:00 -0000 1.41
+++ .classpath 11 Nov 2004 14:13:44 -0000 1.42
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="var" path="CLOVER_RUNTIME"/>
<classpathentry output="framework/target/eclipse-test-classes"
kind="src" path="framework/src/conf"/>
<classpathentry output="framework/target/eclipse-classes" kind="src"
path="framework/src/java"/>
<classpathentry output="framework/target/eclipse-test-classes"
kind="src" path="framework/src/test"/>
@@ -24,5 +23,6 @@
<classpathentry kind="lib"
path="ext-package/lib/spring-full-1.0.1.jar"/>
<classpathentry kind="lib" path="ext-package/lib/junit-3.8.1.jar"/>
<classpathentry kind="lib" path="ext-package/lib/jboss-j2ee-3.2.1.jar"/>
+ <classpathentry kind="lib"
path="ext-package/lib/groovy-all-1.0-beta-7.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
1.82 +4 -0 jakarta-hivemind/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/status.xml,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -r1.81 -r1.82
--- status.xml 10 Nov 2004 20:51:23 -0000 1.81
+++ status.xml 11 Nov 2004 14:13:44 -0000 1.82
@@ -104,6 +104,10 @@
Change BuilderFactoryLogic to report the actual exception, not the
InvocationTargetException,
when an exception is thrown by a constructor or by a initializer
method invocation.
</action>
+ <action type="add" dev="KW">
+ Added Groovy support. Module descriptors can now be defined using
Groovy scripts. Although
+ it requires some additional work in building the Registry.
+ </action>
</release>
<release version="1.0" date="Sep 22 2004">
1.1
jakarta-hivemind/library/src/test/org/apache/hivemind/lib/groovy/TestGroovyModuleDescriptorProvider.java
Index: TestGroovyModuleDescriptorProvider.java
===================================================================
//Copyright 2004 The Apache Software Foundation
//
// Licensed 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.hivemind.lib.groovy;
import java.util.ArrayList;
import java.util.List;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.impl.DefaultClassResolver;
import org.apache.hivemind.impl.DefaultErrorHandler;
import org.apache.hivemind.impl.RegistryAssemblyImpl;
import org.apache.hivemind.parse.ModuleDescriptor;
import org.apache.hivemind.test.HiveMindTestCase;
public class TestGroovyModuleDescriptorProvider extends HiveMindTestCase
{
public void testBasicScript() throws Exception
{
GroovyModuleDescriptorProvider provider = new
GroovyModuleDescriptorProvider(
new DefaultClassResolver(), getResource("basic.groovy"));
ErrorHandler errorHandler = new DefaultErrorHandler();
List descriptors = provider.getModuleDescriptors(errorHandler, new
RegistryAssemblyImpl(
errorHandler));
assertEquals(1, descriptors.size());
ModuleDescriptor descriptor = (ModuleDescriptor) descriptors.get(0);
assertEquals("basic", descriptor.getModuleId());
}
public void testMultipleResources() throws Exception
{
List resources = new ArrayList();
resources.add(getResource("basic.groovy"));
resources.add(getResource("calculator.groovy"));
GroovyModuleDescriptorProvider provider = new
GroovyModuleDescriptorProvider(
new DefaultClassResolver(), resources);
ErrorHandler errorHandler = new DefaultErrorHandler();
List descriptors = provider.getModuleDescriptors(errorHandler, new
RegistryAssemblyImpl(
errorHandler));
assertEquals(2, descriptors.size());
}
}
1.1
jakarta-hivemind/library/src/test/org/apache/hivemind/lib/groovy/calculator.groovy
Index: calculator.groovy
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed 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.
processor.module(id:'examples', version:'1.0.0') {
examplesPkg = 'org.apache.hivemind.examples'
examplesImplPkg = 'org.apache.hivemind.examples.impl'
[
'Adder':[examplesPkg + '.Adder', examplesImplPkg +
'.AdderImpl'],
'Subtracter':[examplesPkg + '.Subtracter', examplesImplPkg +
'.SubtracterImpl'],
'Multiplier':[examplesPkg + '.Multiplier', examplesImplPkg +
'.MultiplerImpl'],
'Divider':[examplesPkg + '.Divider', examplesImplPkg +
'.DividerImpl']
].entrySet().each { e |
processor.servicePoint(id:e.key, interface:e.value[0]) {
createInstance(class:e.value[1])
interceptor(serviceId:'hivemind.LoggingInterceptor')
}
}
servicePoint(id:'Calculator', interface:examplesPkg +
'.Calculator.class') {
invokeFactory {
construct(class:examplesImplPkg + '.CalculatorImpl')
}
interceptor(serviceId:'hivemind.LoggingInterceptor')
}
}
1.1
jakarta-hivemind/library/src/test/org/apache/hivemind/lib/groovy/TestHiveMindBuilder.java
Index: TestHiveMindBuilder.java
===================================================================
//Copyright 2004 The Apache Software Foundation
//
// Licensed 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.hivemind.lib.groovy;
import groovy.lang.Binding;
import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.Resource;
import org.apache.hivemind.impl.DefaultClassResolver;
import org.apache.hivemind.impl.DefaultErrorHandler;
import org.apache.hivemind.impl.RegistryAssembly;
import org.apache.hivemind.impl.RegistryAssemblyImpl;
import org.apache.hivemind.lib.groovy.HiveMindBuilder;
import org.apache.hivemind.parse.DescriptorParser;
import org.apache.hivemind.test.HiveMindTestCase;
import org.easymock.MockControl;
import org.easymock.internal.EqualsMatcher;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.helpers.AttributesImpl;
public class TestHiveMindBuilder extends HiveMindTestCase
{
public void testBasicScript() throws Exception
{
MockControl control = newControl(ContentHandler.class);
control.setDefaultMatcher(new SAXEqualsMatcher());
ContentHandler mock = (ContentHandler) control.getMock();
mock.setDocumentLocator(HiveMindBuilder.GROOVY_LOCATOR);
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute("", "id", "id", "", "basic");
attrs.addAttribute("", "version", "version", "", "1.0.0");
mock.startElement("", "module", "module", attrs);
mock.endElement("", "module", "module");
replayControls();
Script script = new GroovyShell().parse("processor.module(id:'basic',
version:'1.0.0')");
runScript(script, mock);
}
public void testLinePreciseErrorReporting() throws Exception
{
Resource resource = getResource("missingModuleId.groovy");
ErrorHandler handler = new DefaultErrorHandler();
RegistryAssembly assembly = new RegistryAssemblyImpl(handler);
DescriptorParser parser = new DescriptorParser(handler, assembly);
parser.initialize(resource, new DefaultClassResolver());
GroovyCodeSource source = new
GroovyCodeSource(resource.getResourceURL());
Script script = new GroovyShell().parse(source);
try
{
runScript(script, parser);
unreachable();
}
catch (ApplicationRuntimeException e)
{
assertExceptionRegexp(e, "Missing required attribute
.+missingModuleId\\.groovy, line 15\\)\\.");
}
}
private void runScript(Script script, ContentHandler handler)
{
HiveMindBuilder builder = new HiveMindBuilder(handler);
Binding processorBinding = new Binding();
processorBinding.setVariable("processor", builder);
script.setBinding(processorBinding);
script.run();
}
private static class SAXEqualsMatcher extends EqualsMatcher
{
protected boolean argumentMatches(Object expected, Object actual)
{
if ((expected instanceof Attributes) && (actual instanceof
Attributes))
{
Attributes expectedAttributes = (Attributes) expected;
Attributes actualAttributes = (Attributes) actual;
if (expectedAttributes.getLength() !=
actualAttributes.getLength())
return false;
for (int i = 0; i < expectedAttributes.getLength(); i++)
{
if (!expectedAttributes.getLocalName(i)
.equals(actualAttributes.getLocalName(i))
||
!expectedAttributes.getValue(i).equals(actualAttributes.getValue(i)))
return false;
}
return true;
}
return super.argumentMatches(expected, actual);
}
}
}
1.1
jakarta-hivemind/library/src/test/org/apache/hivemind/lib/groovy/missingModuleId.groovy
Index: missingModuleId.groovy
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed 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.
processor.module()
1.1
jakarta-hivemind/library/src/test/org/apache/hivemind/lib/groovy/basic.groovy
Index: basic.groovy
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed 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.
processor.module(id:'basic', version:'1.0.0')
1.1
jakarta-hivemind/library/src/java/org/apache/hivemind/lib/groovy/GroovyScriptProcessor.java
Index: GroovyScriptProcessor.java
===================================================================
//Copyright 2004 The Apache Software Foundation
//
// Licensed 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.hivemind.lib.groovy;
import groovy.lang.Binding;
import groovy.lang.GroovyCodeSource;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import java.io.IOException;
import javax.xml.parsers.SAXParser;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.Resource;
import org.apache.hivemind.impl.RegistryAssembly;
import org.apache.hivemind.parse.DescriptorParser;
import org.apache.hivemind.parse.ModuleDescriptor;
import org.apache.hivemind.parse.XmlResourceProcessor;
import org.xml.sax.SAXException;
/**
* This extension of the [EMAIL PROTECTED]
org.apache.hivemind.parse.XmlResourceProcessor}is suitable for
* processing Groovy scripts and is used internally by [EMAIL PROTECTED]
GroovyModuleDescriptorProvider}.
*
* @see org.apache.hivemind.lib.groovy.GroovyModuleDescriptorProvider
* @author Knut Wannheden
* @since 1.1
*/
class GroovyScriptProcessor extends XmlResourceProcessor
{
private GroovyShell _groovyShell;
public GroovyScriptProcessor(ClassResolver resolver, ErrorHandler
errorHandler,
RegistryAssembly assembly)
{
super(resolver, errorHandler, assembly);
}
protected ModuleDescriptor parseResource(Resource resource, SAXParser
parser,
DescriptorParser contentHandler) throws SAXException, IOException
{
HiveMindBuilder builder = new HiveMindBuilder(contentHandler);
GroovyCodeSource source = new
GroovyCodeSource(resource.getResourceURL());
Script script;
try
{
script = getGroovyShell().parse(source);
}
catch (Exception e)
{
throw new ApplicationRuntimeException(e);
}
Binding processorBinding = new Binding();
processorBinding.setVariable("processor", builder);
script.setBinding(processorBinding);
script.run();
return contentHandler.getModuleDescriptor();
}
private GroovyShell getGroovyShell()
{
if (_groovyShell == null)
_groovyShell = new GroovyShell(_resolver.getClassLoader());
return _groovyShell;
}
}
1.1
jakarta-hivemind/library/src/java/org/apache/hivemind/lib/groovy/HiveMindBuilder.java
Index: HiveMindBuilder.java
===================================================================
//Copyright 2004 The Apache Software Foundation
//
// Licensed 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.hivemind.lib.groovy;
import java.util.HashMap;
import java.util.Map;
import groovy.xml.SAXBuilder;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.helpers.AttributesImpl;
/**
* The HiveMindBuilder is a <a
href="http://groovy.codehaus.org/GroovyMarkup">groovy markup builder
* </a> which can be used to define HiveMind [EMAIL PROTECTED]
ModuleDescriptor module descriptors}using a
* Groovy script. A single Groovy script must only define one module
descriptor.
* <p>
* The markup in the Groovy script is equivalent to the XML markup for module
descriptors. The only
* difference being that any dashes in element names and attribute names
(which would confuse the
* Groovy parser) are replaced by a camelCase notation. So for example
* <code>configuration-point</code> becomes <code>configurationPoint</code>
in a Groovy script.
*
* @since 1.1
* @author Knut Wannheden
*/
public class HiveMindBuilder extends SAXBuilder
{
public static final Locator GROOVY_LOCATOR = new GroovyLocator();
private static final Map CAMEL_TO_HYPHEN_MAP = new HashMap();
public HiveMindBuilder(ContentHandler parser)
{
super(parser);
parser.setDocumentLocator(GROOVY_LOCATOR);
}
protected void nodeCompleted(Object parent, Object node)
{
super.nodeCompleted(parent, getHyphenatedName(node.toString()));
}
protected void doStartElement(Object name, Attributes attributes)
{
super.doStartElement(
getHyphenatedName(name.toString()),
getHyphenatedAttributes(attributes));
}
private String getHyphenatedName(String name)
{
String hyphenatedName = (String) CAMEL_TO_HYPHEN_MAP.get(name);
if (hyphenatedName == null)
{
char[] chars = name.toCharArray();
StringBuffer hyphenated = new StringBuffer();
for (int i = 0; i < name.length(); i++)
{
if (Character.isUpperCase(chars[i]))
hyphenated.append('-').append(Character.toLowerCase(chars[i]));
else
hyphenated.append(chars[i]);
}
hyphenatedName = hyphenated.toString();
CAMEL_TO_HYPHEN_MAP.put(name, hyphenatedName);
}
return hyphenatedName;
}
private Attributes getHyphenatedAttributes(Attributes attributes)
{
AttributesImpl result = (AttributesImpl) attributes;
for (int i = 0; i < result.getLength(); i++)
{
result.setLocalName(i, getHyphenatedName(result.getLocalName(i)));
}
return result;
}
private static class GroovyLocator implements Locator
{
public String getPublicId()
{
return null;
}
public String getSystemId()
{
return null;
}
public int getLineNumber()
{
try
{
throw new Throwable();
}
catch (Throwable t)
{
StackTraceElement[] trace = t.getStackTrace();
for (int i = 0; i < trace.length; i++)
if (trace[i].getFileName().endsWith(".groovy"))
return trace[i].getLineNumber();
}
return -1;
}
public int getColumnNumber()
{
return -1;
}
}
}
1.1
jakarta-hivemind/library/src/java/org/apache/hivemind/lib/groovy/GroovyModuleDescriptorProvider.java
Index: GroovyModuleDescriptorProvider.java
===================================================================
// Copyright 2004 The Apache Software Foundation
//
// Licensed 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.hivemind.lib.groovy;
import java.util.List;
import org.apache.hivemind.ClassResolver;
import org.apache.hivemind.ErrorHandler;
import org.apache.hivemind.ModuleDescriptorProvider;
import org.apache.hivemind.Resource;
import org.apache.hivemind.impl.RegistryAssembly;
import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
import org.apache.hivemind.parse.XmlResourceProcessor;
/**
* This [EMAIL PROTECTED]
org.apache.hivemind.ModuleDescriptorProvider}processes Groovy scripts defining
* module descriptors. To all Groovy scripts executed by the provider a
variable
* <code>processor</code> will be bound. This variable references the
* [EMAIL PROTECTED] HiveMindBuilder HiveMind GroovyMarkup builder}.
*
* @see org.apache.hivemind.lib.groovy.HiveMindBuilder
* @author Knut Wannheden
* @since 1.1
*/
public class GroovyModuleDescriptorProvider extends
XmlModuleDescriptorProvider implements
ModuleDescriptorProvider
{
/**
* Constructs an GroovyModuleDescriptorProvider only loading the
ModuleDescriptor identified by
* the given [EMAIL PROTECTED] org.apache.hivemind.Resource}.
*/
public GroovyModuleDescriptorProvider(ClassResolver resolver, Resource
resource)
{
super(resolver, resource);
}
/**
* Constructs an GroovyModuleDescriptorProvider loading all
ModuleDescriptors identified by the
* given List of [EMAIL PROTECTED] org.apache.hivemind.Resource}objects.
*/
public GroovyModuleDescriptorProvider(ClassResolver resolver, List
resources)
{
super(resolver, resources);
}
protected XmlResourceProcessor getResourceProcessor(ClassResolver
resolver,
ErrorHandler handler, RegistryAssembly assembly)
{
return new GroovyScriptProcessor(resolver, handler, assembly);
}
}
1.33 +1 -0 jakarta-hivemind/src/documentation/content/xdocs/site.xml
Index: site.xml
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/site.xml,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- site.xml 7 Nov 2004 12:35:01 -0000 1.32
+++ site.xml 11 Nov 2004 14:13:45 -0000 1.33
@@ -55,6 +55,7 @@
<multithreading label="Multi-Threading"
href="multithreading.html"/>
<filter label="Servlets" href="filter.html"/>
<override label="Overriding Services"
href="override.html"/>
+ <groovy label="Groovy Support" href="groovy.html"/>
<!-- quickref label="Quick Reference Sheet"
href="HiveMind-QuickReference.doc"/ -->
</tutorials>
1.8 +5 -0
jakarta-hivemind/src/documentation/content/xdocs/dependencies.xml
Index: dependencies.xml
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/dependencies.xml,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- dependencies.xml 2 Nov 2004 22:32:16 -0000 1.7
+++ dependencies.xml 11 Nov 2004 14:13:45 -0000 1.8
@@ -57,6 +57,11 @@
<td>Only needed by &api.HiveMindTestCase;, which exists as the basis
for your own tests.</td>
</tr>
<tr>
+ <td>groovy-all-1.0-beta-7.jar</td>
+ <td>&Groovy;</td>
+ <td>Used by the &api.GroovyModuleDescriptorProvider; to support Groovy
module descriptors.</td>
+ </tr>
+ <tr>
<td>jboss-j2ee-3.2.1.jar</td>
<td>
<link href="http://jboss.org/">JBoss J2EE Server</link>
1.20 +3 -1
jakarta-hivemind/src/documentation/content/xdocs/links.ent
Index: links.ent
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/src/documentation/content/xdocs/links.ent,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- links.ent 8 Nov 2004 14:55:40 -0000 1.19
+++ links.ent 11 Nov 2004 14:13:45 -0000 1.20
@@ -30,6 +30,7 @@
<!ENTITY api.InterceptorStack '<link
href="&apiroot;/InterceptorStack.html">InterceptorStack</link>'>
<!ENTITY api.Messages '<link href="&apiroot;/Messages.html">Messages</link>'>
<!ENTITY api.Module '<link href="&apiroot;/Module.html">Module</link>'>
+<!ENTITY api.ModuleDescriptorProvider '<link
href="&apiroot;/ModuleDescriptorProvider.html">ModuleDescriptorProvider</link>'>
<!ENTITY api.Registry '<link href="&apiroot;/Registry.html">Registry</link>'>
<!ENTITY api.RegistryBuilder '<link
href="&apiroot;/impl/RegistryBuilder.html">RegistryBuilder</link>'>
<!ENTITY api.RegistryShutdownListener '<link
href="&apiroot;/events/RegistryShutdownListener.html">RegistryShutdownListener</link>'>
@@ -46,10 +47,11 @@
<!ENTITY api.BeanFactory '<link
href="&apiroot-lib;/BeanFactory.html">BeanFactory</link>'>
+<!ENTITY api.GroovyModuleDescriptorProvider '<link
href="&apiroot-lib;/groovy/GroovyModuleDescriptorProvider.html">GroovyModuleDescriptorProvider</link>'>
<!ENTITY Spring '<link href="site:spring">Spring</link>'>
<!ENTITY Ant '<link href="http://ant.apache.org/">Ant</link>'>
-
+<!ENTITY Groovy '<link href="http://groovy.codehaus.org/">Groovy</link>'>
<!-- Note, these links CAN NOT currently be converted to site:descriptor#foo
because Forrest 0.5.1 doesn't
understand the use of the '#' as an anchor. -->
1.1
jakarta-hivemind/src/documentation/content/xdocs/groovy.xml
Index: groovy.xml
===================================================================
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed 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.
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.3//EN"
"http://forrest.apache.org/dtd/document-v13.dtd" [
<!ENTITY % common-links SYSTEM "links.ent">
%common-links;
]>
<document>
<header>
<title>Using Groovy to Define Modules</title>
</header>
<body>
<p>
HiveMind's XML format is intentionally designed as a static
(with the exception of the Ant style
properties called <em>substitution symbols</em>) descriptive
format. Yet, in some situations it
would be nice to be able to specify the HiveMind module
descriptors in more dynamic and expressive
ways. <link href="http://groovy.codehaus.org/">Groovy</link>
to the rescue.
</p>
<p>
In the following we will take a look at how the calculator
example module can be expressed using a
Groovy script. We will also go through the steps required to
get module descriptors defined in
Groovy loaded into the Registry.
</p>
<section>
<title>Module Descriptor in Groovy</title>
<source><![CDATA[
import hivemind.examples.*
import hivemind.examples.impl.*
def addSimpleServiceWithLogging(processor, id, interfaceClass) {
interfaceName = interfaceClass.name
processor.servicePoint(id:id, interface:interfaceName) {
lastDotIdx = interfaceName.lastIndexOf('.')
createInstance(class:interfaceName.substring(0, lastDotIdx) +
'.impl' +
interfaceName.substring(lastDotIdx) + 'Impl')
interceptor(serviceId:'hivemind.LoggingInterceptor')
}
}
processor.module(id:'hivemind.examples', version:'1.0.0') {
addSimpleServiceWithLogging(processor, 'Adder', Adder.class)
addSimpleServiceWithLogging(processor, 'Subtracter', Subtracter.class)
addSimpleServiceWithLogging(processor, 'Multiplier', Multiplier.class)
addSimpleServiceWithLogging(processor, 'Divider', Divider.class)
servicePoint(id:'Calculator', interface:Calculator.class.name) {
invokeFactory {
construct(class:CalculatorImpl.class.name)
}
interceptor(serviceId:'hivemind.LoggingInterceptor')
}
}]]></source>
<p>
At first glance this looks very different from a standard XML
module descriptor. But if you take a
closer look you will notice that the main differences stem from
the dynamic aspects which have been
introduced. Without these the module descriptor would actually
look very much alike its XML
equivalent.
</p>
<p>
There are a few important things you should know when writing
Groovy module descriptors:
</p>
<ul>
<li>HiveMind binds the variable <code>processor</code> to the
script, which is the
<link
href="http://groovy.codehaus.org/GroovyMarkup">GroovyMarkup</link> builder.
You can only
use it to define one module descriptor per script.</li>
<li>The XML descriptor elements correspond to methods and the
element attributes correspond to
method parameters. Instead of the hyphened element and
attribute names we have corresponding
camelCased identifiers (e.g. <code>servicePoint</code>
instead of &_service-point;).</li>
</ul>
</section>
<section>
<title>Setting up the Registry</title>
<source><![CDATA[
package hivemind.examples;
import java.util.Locale;
import org.apache.hivemind.*;
import org.apache.hivemind.impl.*;
import org.apache.hivemind.lib.groovy.GroovyModuleDescriptorProvider;
import org.apache.hivemind.util.ClasspathResource;
public class Main
{
public static void main(String[] args)
{
double arg0 = Double.parseDouble(args[0]);
double arg1 = Double.parseDouble(args[1]);
RegistryBuilder builder = new RegistryBuilder();
ClassResolver resolver = new DefaultClassResolver();
// we have to add the default provider to load HiveMind's own modules
builder.addModuleDescriptorProvider(new
XmlModuleDescriptorProvider(resolver));
Resource groovyScript = new ClasspathResource(resolver,
"/META-INF/hivemind.examples.groovy");
// now we add a Groovy provider to load our Groovy script
builder.addModuleDescriptorProvider(new
GroovyModuleDescriptorProvider(resolver,
groovyScript));
Registry registry = builder.constructRegistry(Locale.getDefault());
Calculator calculator = (Calculator)
registry.getService(Calculator.class);
System.out.println("Inputs: " + arg0 + " and " + arg1);
System.out.println("Add: " + calculator.add(arg0, arg1));
System.out.println("Subtract: " + calculator.subtract(arg0, arg1));
System.out.println("Multiply: " + calculator.multiply(arg0, arg1));
System.out.println("Divide: " + calculator.divide(arg0, arg1));
registry.shutdown();
}
}]]></source>
<p>
As you can see there is slightly more work involved in setting
up the Registry when using Groovy
module descriptors. The &api.RegistryBuilder; must be
instantiated manually and the
&api.ModuleDescriptorProvider; instances providing the module
descriptors must be registered with it
prior to the Registry can be built. The Groovy specific
provider is initialized with a single
Resource or a List of Resources (see
&api.GroovyModuleDescriptorProvider;).
</p>
</section>
</body>
</document>
1.13 +2 -0 jakarta-hivemind/library/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-hivemind/library/build.xml,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- build.xml 2 Nov 2004 22:32:16 -0000 1.12
+++ build.xml 11 Nov 2004 14:13:45 -0000 1.13
@@ -39,6 +39,8 @@
<ibiblio-dependency artifact="spring-full" version="1.0.1"
group="springframework"/>
<ibiblio-dependency artifact="commons-logging" version="1.0.3"
group="commons-logging"/>
+ <ibiblio-dependency artifact="groovy-all" version="1.0-beta-7"
group="groovy"/>
+
<ibiblio-dependency artifact="log4j" version="1.2.7"
group="log4j" use="test"/>
<ibiblio-dependency artifact="javassist"
version="${javassist.version}" group="jboss" use="test"/>
<ibiblio-dependency artifact="servletapi" version="2.3"
group="servletapi" use="test"/>
1.5 +7 -2
jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/XmlModuleDescriptorProvider.java
Index: XmlModuleDescriptorProvider.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/impl/XmlModuleDescriptorProvider.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- XmlModuleDescriptorProvider.java 10 Nov 2004 13:26:21 -0000 1.4
+++ XmlModuleDescriptorProvider.java 11 Nov 2004 14:13:45 -0000 1.5
@@ -158,7 +158,7 @@
_errorHandler = handler;
_assembly = assembly;
- _processor = new XmlResourceProcessor(_resolver, handler, assembly);
+ _processor = getResourceProcessor(_resolver, handler, assembly);
for (Iterator i = _resources.iterator(); i.hasNext();)
{
@@ -166,7 +166,7 @@
processResource(resource);
}
-
+
_processor = null;
_assembly = null;
@@ -227,4 +227,9 @@
}
}
+ protected XmlResourceProcessor getResourceProcessor(ClassResolver
resolver,
+ ErrorHandler handler, RegistryAssembly assembly)
+ {
+ return new XmlResourceProcessor(resolver, handler, assembly);
+ }
}
1.3 +32 -14
jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/XmlResourceProcessor.java
Index: XmlResourceProcessor.java
===================================================================
RCS file:
/home/cvs/jakarta-hivemind/framework/src/java/org/apache/hivemind/parse/XmlResourceProcessor.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- XmlResourceProcessor.java 10 Nov 2004 20:51:23 -0000 1.2
+++ XmlResourceProcessor.java 11 Nov 2004 14:13:45 -0000 1.3
@@ -14,6 +14,7 @@
package org.apache.hivemind.parse;
+import java.io.IOException;
import java.net.URL;
import javax.xml.parsers.FactoryConfigurationError;
@@ -45,14 +46,14 @@
{
private static final Log LOG =
LogFactory.getLog(XmlResourceProcessor.class);
- private ErrorHandler _errorHandler;
+ protected ClassResolver _resolver;
+
+ protected ErrorHandler _errorHandler;
private RegistryAssembly _assembly;
private DescriptorParser _contentHandler;
- private ClassResolver _resolver;
-
private SAXParser _saxParser;
public XmlResourceProcessor(ClassResolver resolver, ErrorHandler
errorHandler,
@@ -70,28 +71,22 @@
_contentHandler.initialize(resource, _resolver);
- URL url = resource.getResourceURL();
-
- if (url == null)
- throw new
ApplicationRuntimeException(ParseMessages.missingResource(resource),
- resource, null, null);
-
try
{
- InputSource source = new InputSource(url.openStream());
-
if (LOG.isDebugEnabled())
LOG.debug("Parsing " + resource);
- getSAXParser().parse(source, _contentHandler);
-
- ModuleDescriptor descriptor =
_contentHandler.getModuleDescriptor();
+ ModuleDescriptor descriptor = parseResource(resource,
getSAXParser(), _contentHandler);
if (LOG.isDebugEnabled())
LOG.debug("Result: " + descriptor);
return descriptor;
}
+ catch (ApplicationRuntimeException e)
+ {
+ throw e;
+ }
catch (Exception e)
{
_saxParser = null;
@@ -104,6 +99,29 @@
{
_contentHandler.resetParser();
}
+ }
+
+ /**
+ * Returns the ModuleDescriptor obtained by parsing the specified
Resource using the given
+ * SAXParser and DescriptorParser. Called by [EMAIL PROTECTED]
#processResource(Resource)}after the
+ * DescriptorParser has been
+ * [EMAIL PROTECTED] DescriptorParser#initialize(Resource,
ClassResolver) initialized}. Suitable for
+ * overriding by subclasses.
+ */
+ protected ModuleDescriptor parseResource(Resource resource, SAXParser
parser,
+ DescriptorParser contentHandler) throws SAXException, IOException
+ {
+ URL url = resource.getResourceURL();
+
+ if (url == null)
+ throw new
ApplicationRuntimeException(ParseMessages.missingResource(resource),
+ resource, null, null);
+
+ InputSource source = new InputSource(url.openStream());
+
+ parser.parse(source, contentHandler);
+
+ return contentHandler.getModuleDescriptor();
}
private SAXParser getSAXParser() throws ParserConfigurationException,
SAXException,
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]