To code needed to create a Pineapple module:
Links:
To create the module directory, invoke:
// get user.home String userHome = System.getProperty( "user.home" ); // define default pineapple runtime directory File runtimeDirectory = new File( userHome, ".pineapple" ); // define modules directory File modulesDirectory = new File( runtimeDirectory, "modules" ); // define my moduel directory String moduleId = "my-generated-module"; File moduleDirectory = new File( modulesDirectory, moduleId ); // create the directory if(!moduleDirectory.exists()) moduleDirectory.mkdirs();
The pineapple-test-utils>> project contains a utility named <<<ObjectMotherModule which can be used to create modules. To create the directory, invoke:
// create the module mother ObjectMotherModule moduleMother = new ObjectMotherModule(); // create module directory moduleMother.createNullModule( moduleId, moduleDirectory );
Pineapple modules are defined in the module schema. The project pineapple-api contains JAXB generated classes which are generated from the schema. The module classes are located in the com.alpha.pineapple.model.module package.
To create and marshall a module, implement:
// create module factory com.alpha.pineapple.model.module.ObjectFactory moduleFactory; moduleFactory = new com.alpha.pineapple.model.module.ObjectFactory(); // create module object moduleFactory = new com.alpha.pineapple.model.module.ObjectFactory(); Module module = moduleFactory.createModule(); // define environment for the module String environmentId = "some-test-environment"; // add a single environment to the module Environment environment = moduleFactory.createEnvironment(); environment.setId( environmentId ); module.setEnvironments( moduleFactory.createEnvironments() ); module.getEnvironments().getEnvironment().add( environment ); // set file name StringBuilder fileName; fileName = new StringBuilder(); fileName.append( moduleDir.getAbsolutePath() ); fileName.append( File.separatorChar ); fileName.append( "module.xml" ); // define stream for exception handling OutputStream os = null; try { // get package name String packageName = Module.class.getPackage().getName(); // marshall the module JAXBContext jaxbContext = JAXBContext.newInstance( packageName ); Marshaller marshaller = jaxbContext.createMarshaller(); os = new FileOutputStream( file ); marshaller.marshal( rootObject, os ); os.close(); } catch ( Exception e ) { // do exception handling } finally { // close OS if ( os != null ) { try { os.close(); } catch ( IOException e ) { // do exception handling } } }
Again the ObjectMotherModule can help:
// create module file Module module = moduleMother.createModuleObject(); Environment environment = moduleFactory.createEnvironment(); environment.setId( environmentId ); module.setEnvironments( moduleFactory.createEnvironments() ); module.getEnvironments().getEnvironment().add( environment ); moduleMother.addModuleFile( module );
A model file in a Pineapple module uses minimum two schemas:
When JAXB marshall the model to an XML file it is recommended that the file is marshalled with the elements prefixed with the their namespaces.
To enable this behavior in JAXB a NamespacePrefixMapper must be implemented which:
In this example these schemas are used:
The use prefixes:
The implemented mapper class:
class ModelNamespaceMapper extends NamespacePrefixMapper { @Override public String[] getPreDeclaredNamespaceUris() { return new String[]{ "http://pineapple.dev.java.net/ns/module_1_0", "http://pineapple.dev.java.net/ns/module_model_1_0", "http://pineapple.dev.java.net/ns/plugin/infrastructure_1_0" }; } @Override public String getPreferredPrefix( String namespaceUri, String arg1, boolean arg2 ) { if ( namespaceUri.equals( "http://pineapple.dev.java.net/ns/module_1_0" )) return "mdl"; if ( namespaceUri.equals( "http://pineapple.dev.java.net/ns/module_model_1_0" )) return "mmd"; if ( namespaceUri.equals( "http://pineapple.dev.java.net/ns/plugin/infrastructure_1_0" )) return "itp"; return null; // use default namespace } }
Three steps are involved in the creating the model file:
// create model file Models models = modelFactory.createModels(); AggregatedModel aggregatedModel = modelFactory.createAggregatedModel(); aggregatedModel.setTargetResource( resourceId ); aggregatedModel.setContent( modelFactory.createContent() ); models.getModel().add( aggregatedModel );
com.alpha.pineapple.plugin.infrastructure.model.ObjectFactory pluginFactory; pluginFactory = new com.alpha.pineapple.plugin.infrastructure.model.ObjectFactory(); // create infrastructure model Infrastructure infrastruture = pluginFactory.createInfrastructure(); // resolve to ip test container List<ResolveNameToIpTest> resolveToIpTests = infrastruture.getResolveToIpTest(); // create test case String host = // get host for test case. String description = // get description for test case. ResolveNameToIpTest resolveIP = pluginFactory.createResolveNameToIpTest(); resolveIP.setDescription(description); resolveIP.setHost( host ); ResolveNameToIpAssertionValues assertValues = pluginFactory.createResolveNameToIpAssertionValues(); assertValues.setIp( host ); resolveIP.setAssert( assertValues ); // add test to container resolveToIpTests.add( resolveIP );
The marshalling is done in two steps. First the objects from the intrastructure test plugin is marshalled into a DOM document.
Then the DOM document is then inserted into the model.
The reason for the intermediate marshalling to DOM is caused by the usage of the any type in the module model schema. The resulting JAXB classes represents the any type as a list of org.w3c.dom.Element, so it is needed to convert the infrastructure objects to something that can be inserted as DOM Elements.
Marshalling the infrastructures object to DOM, using the prefix mapper:
// get package name String packageName = Infrastructure.class.getPackage().getName(); // create the prefix mapper NamespacePrefixMapper prefixMapper = new ModelNamespaceMapper() // create JAXB context JAXBContext jaxbContext = JAXBContext.newInstance( packageName ); // create marsahller with mapper Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty( "com.sun.xml.bind.namespacePrefixMapper", mapper ); // create DOM document DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); // marshall JAXB object into DOM document marshaller.marshal( rootObject, doc );
Then the DOM document is added to the model object:
// get content root Content contentRoot = aggregatedModel.getContent(); // add test cases from infrastructure model to aggregated model // Any is defined with processContents="skip" which maps to org.w3c.dom.Element or List<Element> List<Element> domElements = contentRoot.getAny(); domElements.add( (Element) doc.getDocumentElement() );
Finally, the model is marshalled to XML:
// define the models directory in the module File modelsDirectory = new File( modulesDirectory, "models" ); // create the directory if(!modelsDirectory.exists()) modelsDirectory.mkdirs(); // set file name StringBuilder fileName; fileName = new StringBuilder(); fileName.append( environmentId ); fileName.append( ".xml" ); // create models file object File modelFile = new File (modelsDirectory, fileName.toString()); // define stream for exception handling OutputStream os = null; try { // get package name String packageName = Models.class.getPackage().getName(); // marshall the model JAXBContext jaxbContext = JAXBContext.newInstance( packageName ); Marshaller marshaller = jaxbContext.createMarshaller(); os = new FileOutputStream( file ); marshaller.marshal( rootObject, os ); os.close(); } catch ( Exception e ) { // do exception handling } finally { // close OS if ( os != null ) { try { os.close(); } catch ( IOException e ) { // do exception handling } } }
Again the ObjectMotherModule can help:
// marshal model moduleMother.addModelFile( environmentId, models );