package com.thespeechcorporation.plugin.maven; import java.io.File; import java.util.List; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.xmldb.api.DatabaseManager; import org.xmldb.api.base.Collection; import org.xmldb.api.base.Database; import org.xmldb.api.base.Resource; import org.xmldb.api.base.XMLDBException; import org.xmldb.api.modules.CollectionManagementService; /** * This plugin communicates with the eXist database. This plugin is considered a replacement of the * existing possibility to communicate with the database from maven, namely the Ant plugin. The root * of the database is initialized as follow: *
 * Collection root = DatabaseManager.getCollection("xmldb:exist://localhost:8080/exist/xmlrpc/db", "username", "password");
 * 
* @goal execute * @phase install */ public class ExistPlugin extends AbstractMojo { // Constants private final String CLASSNAME = this.getClass().getName(); private final String XML = "XMLResource"; // According to XM:DB API specification private final String BINARY = "BinaryResource"; // According to XM:DB API specification private final String COLLECTION_MANAGEMENT_SERVICE = "CollectionManagementService"; private final String COLLECTION_MANAGEMENT_SERVICE_VERSION = "1.0"; private final String DELIMITER = "/"; // Globals private Collection root = null; private CollectionManagementService service = null; private Database database = null; /** * The url, the database is running under * @parameter default-value="" * @required */ private String url = null; /** * The username associated with the eXist user. * @parameter default-value="" * @required */ private String username = null; /** * The password associated with the eXist user. * @parameter default-value="" */ private String password = null; /** * The List of collections to be created * @parameter */ private List createCollections = null; /** * The List of collections to be deleted * @parameter */ private List deleteCollections = null; /** * The List of resources to be created * @parameter */ private List createData = null; /** * The list of resources to be deleted * @parameter */ private List deleteData = null; /** * An auxiliary to initialize the maven plugin. * @throws MojoExecutionException When intialization failed. */ private void init() throws MojoExecutionException { try { Class driver = Class.forName("org.exist.xmldb.DatabaseImpl"); this.database = (Database) driver.newInstance(); this.database.setProperty("create-database", "true"); DatabaseManager.registerDatabase(this.database); this.root = DatabaseManager.getCollection(this.url, this.username, this.password); this.service = (CollectionManagementService) root.getService(COLLECTION_MANAGEMENT_SERVICE, COLLECTION_MANAGEMENT_SERVICE_VERSION); } catch (Exception e) { if(super.getLog().isErrorEnabled()) { super.getLog().error(e.getMessage(), e); } throw new MojoExecutionException(e.getMessage(), e); } } /** * The method to execute the maven plugin. * @throws MojoExecutionException When execution failed. */ public void execute() throws MojoExecutionException, MojoFailureException { this.init(); if(super.getLog().isInfoEnabled()) { super.getLog().info("[" + CLASSNAME + "] executing..."); super.getLog().info("\tUsing url: " + this.url); super.getLog().info("\tUsing username: " + this.username); super.getLog().info("\tUsing password: " + this.password); } // Delete collections this.deleteCollections(); // Create collections this.createCollections(); // Create files this.createFiles(); // Delete files this.deleteFiles(); if(super.getLog().isInfoEnabled()) { super.getLog().info("[" + CLASSNAME + "] executing... done!"); } } /** * An auxiliary method to delete collections. Note that subdirectories are deleted as well. */ private void deleteCollections() throws MojoExecutionException { if(this.deleteCollections == null || this.deleteCollections.size() == 0) { if(super.getLog().isInfoEnabled()) { super.getLog().info("No collections to delete"); } return; } try { for(String collection : this.deleteCollections) { if(super.getLog().isInfoEnabled()) { super.getLog().info("Deleted collection: " + collection); } this.service.removeCollection(collection); } } catch (Exception e) { if(super.getLog().isErrorEnabled()) { super.getLog().error(e.getMessage(), e); } throw new MojoExecutionException(e.getMessage(), e); } } /** * An auxiliary method to create collections. Note that subdirectories are created as well when the parent * is non existent, i.e. the parent is created along. * @throws MojoExecutionException When the database is non responsive. */ private void createCollections() throws MojoExecutionException { if(this.createCollections == null || this.createCollections.size() == 0) { if(super.getLog().isInfoEnabled()) { super.getLog().info("No collections to create"); } return; } try { for(String collection : this.createCollections) { if(super.getLog().isInfoEnabled()) { super.getLog().info("Created collection: " + collection); } this.service.createCollection(collection); } } catch (Exception e) { if(super.getLog().isErrorEnabled()) { super.getLog().error(e.getMessage(), e); } throw new MojoExecutionException(e.getMessage(), e); } } /** * An auxiliary method to create files. * @throws MojoExecutionException */ private void createFiles() throws MojoExecutionException { Collection target = null; File file = null; Resource resource = null; if(this.createData == null || this.createData.size() == 0) { if(super.getLog().isInfoEnabled()) { super.getLog().info("No files to create"); } return; } if(super.getLog().isInfoEnabled()) { super.getLog().info("Total files to create: " + this.createData.size()); } try { for(Data data : this.createData) { if(super.getLog().isInfoEnabled()) { super.getLog().info("Resource to be created:"); } file = new File(data.getSource()); if(super.getLog().isInfoEnabled()) { super.getLog().info("\tResource source: " + data.getSource() + ", exist: " + file.exists()); super.getLog().info("\tResource destination: " + data.getDestination()); } if(data.getType() == null || data.getType().trim().equals("") || data.getType().trim().equals("xml") || data.getType().trim().equals(XML)) { data.setType(XML); // Set type default to XML } else { data.setType(BINARY); // All other is considered binary content } if(super.getLog().isInfoEnabled()) { super.getLog().info("\tResource type: " + data.getType()); } // Get target Collection target = this.navigateToCollection(data.getDestination(), this.root, false); if(target == null) { if(super.getLog().isInfoEnabled()) { super.getLog().info("Target collection (" + data.getDestination() + ") does not exist, aborting..."); } continue; } resource = target.createResource(file.getName(), data.getType()); resource.setContent(file); target.storeResource(resource); } } catch (Exception e) { if(super.getLog().isErrorEnabled()) { super.getLog().error(e.getMessage(), e); } throw new MojoExecutionException(e.getMessage(), e); } } /** * An auxiliary method to delete files. * @throws MojoExecutionException */ private void deleteFiles() throws MojoExecutionException { Collection target = null; Resource resource = null; if(this.deleteData == null || this.deleteData.size() == 0) { if(super.getLog().isInfoEnabled()) { super.getLog().info("No files to delete"); } return; } if(super.getLog().isInfoEnabled()) { super.getLog().info("Total files to delete: " + this.deleteData.size()); } try { for(String data : this.deleteData) { // Get target Collection target = this.navigateToCollection(data, this.root, true); data = data.substring(data.lastIndexOf(DELIMITER) + 1, data.length()); resource = target.getResource(data); if(resource != null) { target.removeResource(resource); } } } catch (Exception e) { if(super.getLog().isErrorEnabled()) { super.getLog().error(e.getMessage(), e); } throw new MojoExecutionException(e.getMessage(), e); } } /** * Auxiliary method to navigate to the correct Collection. This is typically used for creation and deletion * of resources in sub collections. * @param path The path of the collection. * @param current The current collection. * @return The target collection. * @throws XMLDBException When a database error occurs. */ private Collection navigateToCollection(String path, Collection current, boolean fileIncluded) throws XMLDBException { int index = -1; index = path.indexOf(DELIMITER); if(index == -1) { if(fileIncluded) { return current; } else { return current.getChildCollection(path); } } else { return this.navigateToCollection(path.substring(index + 1), current.getChildCollection(path.substring(0, index)), fileIncluded); } } }