001/*
002 *  Copyright 2024 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.workspaces.archive;
017
018import java.io.IOException;
019import java.nio.file.Path;
020import java.util.zip.ZipOutputStream;
021
022import javax.jcr.Node;
023import javax.jcr.NodeIterator;
024import javax.jcr.RepositoryException;
025
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.xml.sax.ContentHandler;
029
030import org.ametys.plugins.contentio.archive.DefaultPluginArchiver;
031import org.ametys.plugins.contentio.archive.ImportReport;
032import org.ametys.plugins.contentio.archive.Merger;
033import org.ametys.plugins.contentio.archive.SystemViewHandler;
034import org.ametys.plugins.contentio.archive.ZipEntryHelper;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.plugins.workspaces.project.objects.Project;
037
038/**
039 * Archiver handling the data stored by the workspaces plugin.
040 * Mainly this archiver will separate each projects in its own directory.
041 * Each project folder consisting of different directory for each module.
042 * And the data in the document module will be stored as file tree allowing easy access to each document
043 */
044public class WorkspacePluginArchiver extends DefaultPluginArchiver
045{
046    private static final String __PROJECTS_NODE_NAME = "projects";
047    /** the ametys object resolver */
048    protected AmetysObjectResolver _resolver;
049    /** the project archiver helper */
050    protected ProjectArchiverHelper _projectArchiverHelper;
051
052    @Override
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        super.service(manager);
056        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
057        _projectArchiverHelper = (ProjectArchiverHelper) manager.lookup(ProjectArchiverHelper.ROLE);
058    }
059    
060    @Override
061    protected ContentHandler getSystemViewHandler(ContentHandler initialHandler)
062    {
063        return new SystemViewHandler(initialHandler, name -> __PROJECTS_NODE_NAME.equals(name), __ -> false);
064    }
065    
066    @Override
067    public void export(String pluginName, Node pluginNode, ZipOutputStream zos, String prefix) throws IOException
068    {
069        // export every thing except the projets node
070        super.export(pluginName, pluginNode, zos, prefix);
071        
072        try
073        {
074            // then the contents if any, one by one
075            if (pluginNode.hasNode(__PROJECTS_NODE_NAME))
076            {
077                Node projectsNode = pluginNode.getNode(__PROJECTS_NODE_NAME);
078                NodeIterator it = projectsNode.getNodes();
079                while (it.hasNext())
080                {
081                    Node projectNode = it.nextNode();
082                    Project project = _resolver.resolve(projectNode, false);
083                    
084                    _projectArchiverHelper.exportProject(project, zos, prefix + "/" + __PROJECTS_NODE_NAME + "/" + project.getName() + "/");
085                }
086            }
087        }
088        catch (Exception e)
089        {
090            throw new RuntimeException("Unable to archive plugin " + pluginName, e);
091        }
092    }
093    
094    @Override
095    public ImportReport partialImport(String pluginName, Node allPluginsNode, Path zipPath, String zipPluginEntryPath, Merger merger) throws IOException
096    {
097        ImportReport report = super.partialImport(pluginName, allPluginsNode, zipPath, zipPluginEntryPath, merger);
098        
099        String baseImportProjectPath = zipPluginEntryPath + "/" + __PROJECTS_NODE_NAME;
100        if (ZipEntryHelper.zipEntryFolderExists(zipPath, baseImportProjectPath))
101        {
102            try
103            {
104                // The plugin node is created by the call to super
105                Node pluginNode = allPluginsNode.getNode(pluginName);
106                report.addFrom(_projectArchiverHelper.importProjects(pluginNode, zipPath, baseImportProjectPath, merger));
107            }
108            catch (RepositoryException e)
109            {
110                throw new IOException("Could not get plugin node for " + pluginName, e);
111            }
112        }
113        else
114        {
115            getLogger().info("No project node to import. The path '{}!{}' does not exist", zipPath, baseImportProjectPath);
116        }
117        return report;
118    }
119}