com.xpn.xwiki.tool.backup.AbstractImportMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.xpn.xwiki.tool.backup.AbstractImportMojo.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package com.xpn.xwiki.tool.backup;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingResult;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.extension.Extension;
import org.xwiki.extension.InstallException;
import org.xwiki.extension.LocalExtension;
import org.xwiki.extension.repository.InstalledExtensionRepository;
import org.xwiki.extension.repository.LocalExtensionRepository;
import org.xwiki.extension.repository.LocalExtensionRepositoryException;
import org.xwiki.extension.repository.internal.local.DefaultLocalExtension;
import org.xwiki.properties.ConverterManager;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.user.api.XWikiRightService;

/**
 * Maven 2 plugin to generate XWiki data folder (database and extensions).
 *
 * @version $Id: ff8f8478aa94b33d6f43d03c1f8d4239d60d7ec9 $
 * @since 9.0RC1
 * @since 8.4.2
 */
public abstract class AbstractImportMojo extends AbstractMojo {
    public static final String MPKEYPREFIX = "xwiki.extension.";

    public static final String MPNAME_NAME = "name";

    public static final String MPNAME_SUMMARY = "summary";

    public static final String MPNAME_WEBSITE = "website";

    public static final String MPNAME_FEATURES = "features";

    public static class ExcludeArtifact {
        private String groupId;

        private String artifactId;

        private String version;

        private String type;

        public String getGroupId() {
            return groupId;
        }

        public void setGrouId(String grouId) {
            this.groupId = grouId;
        }

        public String getArtifactId() {
            return artifactId;
        }

        public void setArtifactId(String artifactId) {
            this.artifactId = artifactId;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }

    /**
     * @see com.xpn.xwiki.tool.backup.Importer#importDocuments(java.io.File, String, java.io.File)
     */
    @Parameter(defaultValue = "xwiki")
    protected String databaseName;

    /**
     * @see com.xpn.xwiki.tool.backup.Importer#importDocuments(java.io.File, String, java.io.File)
     */
    @Parameter(defaultValue = "${basedir}/src/main/packager/hibernate.cfg.xml")
    protected File hibernateConfig;

    /**
     * @see com.xpn.xwiki.tool.backup.Importer#importDocuments(java.io.File, String, java.io.File)
     */
    @Parameter(defaultValue = "${project.build.directory}/data/")
    protected File xwikiDataDir;

    /**
     * The namespace where to register the XAR extensions.
     */
    @Parameter(defaultValue = "wiki:xwiki")
    private String xarNamespace;

    /**
     * The reference of the user who installed the extensions.
     */
    @Parameter(defaultValue = XWikiRightService.SUPERADMIN_USER_FULLNAME)
    protected String installUser;

    /**
     * The maven project.
     */
    @Parameter(property = "project", required = true, readonly = true)
    protected MavenProject project;

    /**
     * The current Maven session being executed.
     */
    @Parameter(defaultValue = "${session}", readonly = true)
    protected MavenSession session;

    /**
     * Project builder -- builds a model from a pom.xml.
     */
    @Component
    protected ProjectBuilder projectBuilder;

    /**
     * @param importer the importer
     * @param databaseName some database name (TODO: find out what this name is really)
     * @param hibernateConfig the Hibernate config fill containing the database definition (JDBC driver, username and
     *            password, etc)
     * @throws Exception failed to import dependencies
     */
    protected void importDependencies(Importer importer, String databaseName, File hibernateConfig)
            throws Exception {
        XWikiContext xcontext = importer.createXWikiContext(databaseName, hibernateConfig);

        // We need to distinguish between extensions installed explicitly and their transitive dependencies.
        // We have to create our own Set because Maven changes the fields from the dependency Artifacts (e.g. resolves
        // their version) after they are added to the Set of dependencies and this causes the hash code to change. As a
        // result the #contains(Artifact) method doesn't work as expected because it uses the new hash code.
        Set<Artifact> directDependencies = new HashSet<>(this.project.getDependencyArtifacts());

        // Reverse artifact order to have dependencies first (despite the fact that it's a Set it's actually an ordered
        // LinkedHashSet behind the scene)
        List<Artifact> dependenciesFirstArtifacts = new ArrayList<>(this.project.getArtifacts());
        Collections.reverse(dependenciesFirstArtifacts);

        for (Artifact artifact : dependenciesFirstArtifacts) {
            if (!artifact.isOptional()) {
                if ("xar".equals(artifact.getType())) {
                    installXAR(artifact, importer, xcontext);
                }
            }
        }

        // We MUST shutdown HSQLDB because otherwise the last transactions will not be flushed
        // to disk and will be lost. In practice this means the last Document imported has a
        // very high chance of not making it...
        // TODO: Find a way to implement this generically for all databases and inside
        // XWikiHibernateStore (cf https://jira.xwiki.org/browse/XWIKI-471).
        importer.shutdownHSQLDB(xcontext);

        importer.disposeXWikiContext(xcontext);

    }

    protected void installXAR(Artifact artifact, Importer importer, XWikiContext xcontext) throws Exception {
        getLog().info("  ... Importing XAR file: " + artifact.getFile());

        // Import XAR into database
        int nb = importer.importXAR(artifact.getFile(), null, xcontext);

        getLog().info("  ..... Imported " + nb + " documents");

        // Install extension
        installExtension(artifact, (ComponentManager) xcontext.get(ComponentManager.class.getName()),
                this.xarNamespace);
    }

    protected void installExtension(Artifact artifact, ComponentManager componentManager, String namespace)
            throws ComponentLookupException, InstallException, LocalExtensionRepositoryException,
            MojoExecutionException {
        // We need to distinguish between extensions installed explicitly and their transitive dependencies.
        // We have to create our own Set because Maven changes the fields from the dependency Artifacts (e.g. resolves
        // their version) after they are added to the Set of dependencies and this causes the hash code to change. As a
        // result the #contains(Artifact) method doesn't work as expected because it uses the new hash code.
        Set<Artifact> directDependencies = new HashSet<>(this.project.getDependencyArtifacts());

        LocalExtensionRepository localExtensionRepository = componentManager
                .getInstance(LocalExtensionRepository.class);
        InstalledExtensionRepository installedExtensionRepository = componentManager
                .getInstance(InstalledExtensionRepository.class);

        MavenProject dependencyProject = getMavenProject(artifact);

        ConverterManager converter = componentManager.getInstance(ConverterManager.class);
        Extension mavenExtension = converter.convert(Extension.class, dependencyProject.getModel());

        DefaultLocalExtension extension = new DefaultLocalExtension(null, mavenExtension);

        extension.setFile(artifact.getFile());

        LocalExtension localExtension = localExtensionRepository.storeExtension(extension);
        installedExtensionRepository.installExtension(localExtension, namespace,
                !directDependencies.contains(artifact),
                Collections.<String, Object>singletonMap("user.reference", this.installUser));

        getLog().info("  ... Registered extension [" + extension + "]");
    }

    protected MavenProject getMavenProject(Artifact artifact) throws MojoExecutionException {
        try {
            ProjectBuildingRequest request = new DefaultProjectBuildingRequest(
                    this.session.getProjectBuildingRequest())
                            // We don't want to execute any plugin here
                            .setProcessPlugins(false)
                            // It's not this plugin job to validate this pom.xml
                            .setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL)
                            // Use the repositories configured for the built project instead of the default Maven ones
                            .setRemoteRepositories(
                                    this.session.getCurrentProject().getRemoteArtifactRepositories());
            // Note: build() will automatically get the POM artifact corresponding to the passed artifact.
            ProjectBuildingResult result = this.projectBuilder.build(artifact, request);
            return result.getProject();
        } catch (ProjectBuildingException e) {
            throw new MojoExecutionException(String.format("Failed to build project for [%s]", artifact), e);
        }
    }
}