Hello

I've been working on integrating a registry/repository support into CAMEL. The current implementation uses XML files, later it should also be linked with real-life repositories (Galaxy, OW2 Registry, ...). The implementation is now complete, and here's how I've done it:

   * To use the registry, I use the Spring camel-context XML file and
     map the "registry:" protocol to the lookup class:

     <!-- The registry component, configured as a File Registry -->
     <bean id="registry" class="test.FileRegistryComponent">
         <property name="file" value="registry.xml"/>
     </bean>
   * The file-based registry/repository is an XML file:

     <?xml version="1.0" encoding="UTF-8"?>
     <registry xmlns="custom:FileRegistry"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
         xsi:schemaLocation="custom:FileRegistry FileRegistry.xsd">
         <entry>
             <logicalName>queue</logicalName>
             <technicalName>
                 joram:queue:sampleQueue
             </technicalName>
         </entry>
         <entry>
             <logicalName>topic</logicalName>
             <technicalName>
                 joram:topic:sampleTopic
             </technicalName>
         </entry>
         <entry>
             <logicalName>sampleWebService</logicalName>
             <technicalName>
             <![CDATA[
                 cxf://
                     http://localhost:9000/CxfService_1/SayHello
                     ?serviceClass=test.ISayHello
&wsdlURL=http://localhost:9000/CxfService_1/SayHello?wsdl
                     &serviceName={http://test/}SayHello
                     &portName={http://test/}SayHelloPort
                     &dataFormat=POJO
             ]]>
             </technicalName>
         </entry>
     </registry>

     The XSD for the XML is attached.
   * Finally, you simply prefix your endpoint with "registry:" to point
     it to a registry/repository entry. For example, in DSL:

     from("registry:queue").process(new Processor() {
         public void process(Exchange e) {
             // Convert JMS message content into WS request
             final List<String> params = new ArrayList<String>();
             e.getIn().setHeader(CxfConstants.OPERATION_NAME, "hello");
             String body = e.getIn().getBody(String.class);
             params.add(body);
             e.getIn().setBody(params);
         }
     }).to("registry:sampleWebService").to("registry:topic");

I'm attaching the registry/repository's Java implementation. Any comments are welcome.

PS: I know that based on the fact that I'm using an XSD schema I could have also used the JAXB APIs to match XML files to Java classes (tools automatically do it, so why bother!). If you think that's better, I could well switch to that as well.

PPS: When CAMEL 1.5.1 will be out, the parent class that's used for the registry will be RefComponent. The modification is minor, but neat.

Do you think this can be commited into the CAMEL examples?

Thanks

--

S. Ali Tokmen
[EMAIL PROTECTED]

Office: +33 4 76 29 76 19
GSM:    +33 66 43 00 555

Bull, Architect of an Open World TM
http://www.bull.com

package test;

import org.apache.camel.CamelContext;
import org.apache.camel.Component;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;

public abstract class AbstractRegistryComponent implements Component<Exchange> {

    private CamelContext context;

    public CamelContext getCamelContext() {
        return this.context;
    }

    public void setCamelContext(CamelContext context) {
        this.context = context;
    }

    protected abstract String lookup(String name) throws Exception;

    @SuppressWarnings("unchecked")
    public Endpoint<Exchange> createEndpoint(final String name) throws 
Exception {
        final String logicalAddress = name.substring(name.indexOf(':') + 1);
        final String technicalAddress = lookup(logicalAddress);

        final String scheme;
        final int schemeStart = technicalAddress.indexOf(':');
        if (schemeStart > 0) {
            scheme = technicalAddress.substring(0, schemeStart);
        } else {
            scheme = technicalAddress;
        }

        System.out.println("AbstractRegistryComponent creating endpoint: name 
is " + name + ", logicalAddress is "
            + logicalAddress + ", technicalAddress is " + technicalAddress + ", 
scheme is " + scheme);

        return context.getComponent(scheme).createEndpoint(technicalAddress);
    }
}
package test;

import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class FileRegistryComponent extends AbstractRegistryComponent {

    private String file;

    private Map<String, String> registry;

    private Pattern whitespace = Pattern.compile("\\s");

    public String getFile() {
        return this.file;
    }

    public void setFile(String file) {
        try {
            this.file = file;
            this.registry = new HashMap<String, String>();

            DocumentBuilderFactory docBuilderFactory = 
DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc;
            ClassLoader cl = this.getClass().getClassLoader();
            if (cl.getResource(file) != null) {
                InputStream resource = cl.getResourceAsStream(file);
                doc = docBuilder.parse(resource);
                resource.close();
            } else {
                doc = docBuilder.parse(new File(file));
            }
            doc.getDocumentElement().normalize();

            NodeList listOfEntries = doc.getElementsByTagName("entry");
            for (int i = 0; i < listOfEntries.getLength(); i++) {
                String name = null;
                String value = null;
                NodeList entry = listOfEntries.item(i).getChildNodes();
                for (int j = 0; j < entry.getLength(); j++) {
                    Node entryDetail = entry.item(j);
                    if ("logicalName".equals(entryDetail.getNodeName())) {
                        name = getValueAndRemoveAllWhitespace(entryDetail);
                    } else if 
("technicalName".equals(entryDetail.getNodeName())) {
                        value = getValueAndRemoveAllWhitespace(entryDetail);
                    }
                }
                this.registry.put(name, value);
            }
        } catch (Exception e) {
            this.file = null;
            this.registry = null;
            throw new IllegalArgumentException("Cannot read file \"" + file + 
"\"", e);
        }
    }

    private String getValueAndRemoveAllWhitespace(Node node) {
        StringBuilder result = new StringBuilder();
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            result.append(children.item(i).getNodeValue());
        }
        return this.whitespace.matcher(result.toString()).replaceAll("");
    }

    @Override
    protected String lookup(String name) {
        if (registry == null) {
            throw new IllegalStateException("FileRegistryComponent doesn't have 
a valid file specified");
        }

        return this.registry.get(name);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="custom:FileRegistry" elementFormDefault="qualified"
	xmlns="http://www.w3.org/2001/XMLSchema"; xmlns:tns="custom:FileRegistry">
	<element name="registry" type="tns:registry"></element>

	<complexType name="registry">
		<sequence maxOccurs="unbounded" minOccurs="0">
			<element name="entry" type="tns:entry"></element>
		</sequence>
	</complexType>

	<complexType name="entry">
		<sequence maxOccurs="1" minOccurs="1">
			<element name="logicalName" type="string"></element>
			<element name="technicalName" type="string"></element>
		</sequence>
	</complexType>
</schema>

Reply via email to