package org.mobicents.ant; import java.io.File; import java.io.FileOutputStream; import java.util.Iterator; import java.util.LinkedList; import java.util.StringTokenizer; import javax.xml.parsers.DocumentBuilder; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.Reference; import org.apache.tools.ant.types.ZipFileSet; import org.mobicents.util.XMLParser; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; // // The DeployableJar task automates the construction of a deployable unit jar that // may subsequently deployed in a SLEE. Nested elements of the DeployableJar are the // consituent elements in the deployable unit. DeployableJar generates a appropriate // deployable-unit.xml descriptor. // // The metainfbase attribute is optional. It contains a path that is preprended to // the location of all deployment descriptors in the deployable unit - if present the value // of this attribute is passed to the nested elements. // // The extxml attribute is optional. It contains the name of an oc service extension // deployment descriptor. The name is relative to metainfbase, or the current directory // if metainfbase is not defined. The file is added as META-INF/oc-service.xml into // the deployable unit. // // <deployableunit destfile="pathname.jar" metainfbase="foo/bar" servicexml="my-service.xml"> // <component file="foo.jar"> // <component refid="bar"> // <sbbjar ...> // <eventjar ...> // <profilespecjar ...> // <resourceadaptortypejar ...> // <resourceadaptorjar ...> // <fileset ...> // </deployableunit> // // Here is an example from the jcc call forwarding example app: // // <deployablejar destfile="${jars}/call-forwarding.jar" metainfbase="${src}/com/opencloud/slee/services/callforwarding/META-INF"> // <profilespecjar destfile="${jars}/profile.jar" classpath="${classes}/jcc-callforwarding" /> // <sbbjar destfile="${jars}/sbb.jar" classpath="${classes}/jcc-callforwarding" /> // </deployablejar> public class DeployableJar extends org.apache.tools.ant.taskdefs.Jar { public DeployableJar() { super(); archiveType = "deployable-unit-jar"; emptyBehavior = "create"; this.serviceXmlStr = "service.xml"; } public void setMetainfbase(String metainfbase) { this.metainfbase = new File(metainfbase); } public void setServicexml(String serviceXmlStr) { this.serviceXmlStr = serviceXmlStr; } public final void setExtxml(String extXmlStr) { this.extXmlStr = extXmlStr; } public void execute() throws BuildException { processServiceXml(); // Execute subtasks as necessary. for (Iterator i = tasks.iterator(); i.hasNext(); ) { Task task = (Task)i.next(); if (task instanceof SleeJar) ((SleeJar)task).setMetaInfBase(metainfbase); task.perform(); } if (deployableunitxml == null) { // Build our deployable-unit.xml. try { // ... build a DOM tree and serialize it out. DocumentBuilder builder = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); DOMImplementation domImpl = builder.getDOMImplementation(); DocumentType docType = domImpl.createDocumentType("deployable-unit", "-//Sun Microsystems, Inc.//DTD JAIN SLEE Deployable Unit 1.0//EN", "http://java.sun.com/dtd/slee-deployable-unit_1_0.dtd"); Document doc = domImpl.createDocument(null, docType.getName(), docType); Element root = doc.getDocumentElement(); // Add <jar> elements for (Iterator i = components.iterator(); i.hasNext(); ) { Component component = (Component)i.next(); File componentFile = component.getComponentFile(getProject()); // Add a fileset for this component. ZipFileSet fs = new ZipFileSet(); fs.setFile(componentFile); fs.setFullpath(componentFile.getName()); super.addFileset(fs); XMLParser.createTextElement(root, "jar", componentFile.getName()); } if (servicexml != null) { for (int i = 0; i < servicexml.length; i++) { File serviceXmlFile = (File) servicexml[i]; XMLParser.createTextElement(root, "service-xml", serviceXmlFile.getName()); } // Add <service-xml> to the output doc. // @@ XMLParser.createTextElement(root, "service-xml", "service-jar.xml"); } // Create the deployable-unit.xml. deployableunitxml = File.createTempFile("deployable-unit", ".xml"); deployableunitxml.deleteOnExit(); FileOutputStream duDDOut = new FileOutputStream(deployableunitxml); TransformerFactory factory = TransformerFactory.newInstance(); Transformer identityTransformer = factory.newTransformer(); identityTransformer.setOutputProperty(OutputKeys.METHOD, "xml"); identityTransformer.setOutputProperty(OutputKeys.INDENT, "yes"); identityTransformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, docType.getPublicId()); identityTransformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, docType.getSystemId()); identityTransformer.transform(new DOMSource(doc), new StreamResult(duDDOut)); duDDOut.close(); // Add a new fileset for deployable-unit.xml. ZipFileSet fs = new ZipFileSet(); fs.setFile(deployableunitxml); fs.setFullpath("META-INF/deployable-unit.xml"); super.addFileset(fs); } catch (Exception e) { throw new BuildException(e); } } super.execute(); } // servicexml="..." private void processServiceXml() { StringTokenizer tok = new StringTokenizer(serviceXmlStr); File [] files = new File[tok.countTokens()]; int i = 0; while (tok.hasMoreElements()) { files[i++] = (null == metainfbase) ? new File(tok.nextToken()) : new File(metainfbase, tok.nextToken()); } setServicexml(files); } private void setServicexml(File [] servicexml) { this.servicexml = servicexml; for (int i = 0; i < servicexml.length; i++) { if (!servicexml[i].exists()) { throw new BuildException("Service deployment descriptor: " + servicexml[i] + " does not exist."); } } for (int i = 0; i < servicexml.length; i++) { ZipFileSet fs = new ZipFileSet(); fs.setFile(servicexml[i]); fs.setFullpath(servicexml[i].getName()); super.addFileset(fs); } // look for oc-service.xml extension dd if (extXmlStr != null) { File extXml = (metainfbase == null) ? new File(extXmlStr) : new File(metainfbase, extXmlStr); if (!extXml.exists()) { throw new BuildException("Service extension deployment descriptor: " + extXml + " does not exist."); } ZipFileSet fs = new ZipFileSet(); fs.setFile(extXml); fs.setFullpath("META-INF/oc-service.xml"); super.addFileset(fs); } } // Nested <component ...> public Component createComponent() { SimpleComponent newComponent = new SimpleComponent(); components.add(newComponent); return newComponent; } // Nested <sbbjar ...> public SbbJar createSbbjar() { SbbJar sbbTask = new SbbJar(); sbbTask.setGeneratename(true); components.add(sbbTask); tasks.add(sbbTask); return sbbTask; } public EventJar createEventJar() { EventJar eventTask = new EventJar(); eventTask.setGeneratename(true); components.add(eventTask); tasks.add(eventTask); return eventTask; } public ProfileSpecJar createProfileSpecJar() { ProfileSpecJar profileSpecTask = new ProfileSpecJar(); profileSpecTask.setGeneratename(true); components.add(profileSpecTask); tasks.add(profileSpecTask); return profileSpecTask; } public ResourceAdaptorTypeJar createResourceAdaptorTypeJar() { ResourceAdaptorTypeJar raTypeTask = new ResourceAdaptorTypeJar(); raTypeTask.setGeneratename(true); components.add(raTypeTask); tasks.add(raTypeTask); return raTypeTask; } public ResourceAdaptorJar createResourceAdaptorJar() { ResourceAdaptorJar raTask = new ResourceAdaptorJar(); raTask.setGeneratename(true); components.add(raTask); tasks.add(raTask); return raTask; } protected void cleanUp() { // Delete temporary deployable-unit.xml if (deployableunitxml != null) { deployableunitxml.delete(); deployableunitxml = null; } } // SimpleComponent: // <component file="location"/> // <component refid="id"/> public static final class SimpleComponent implements Component { public SimpleComponent() {} public File getComponentFile(Project project) throws BuildException { if (file != null) return file; if (ref != null) { try { Component referenced = (Component)ref.getReferencedObject(project); return referenced.getComponentFile(project); } catch (ClassCastException cce) { throw new BuildException("Referenced task is not a Component task"); } } throw new BuildException("One of ref or file attribute must be specified"); } public void setFile(File file) { this.file = file; } public void setRefid(Reference ref) { this.ref = ref; } private File file; private Reference ref; } private File metainfbase = null; private String serviceXmlStr; private String extXmlStr; private File deployableunitxml; private File [] servicexml; private final LinkedList components = new LinkedList(); private final LinkedList tasks = new LinkedList(); }