001/*
002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.platform.content.template.factories;
023
024import java.io.File;
025import java.io.IOException;
026import java.util.List;
027import java.util.Map;
028
029import org.apache.logging.log4j.LogManager;
030import org.apache.logging.log4j.Logger;
031import org.nuxeo.common.Environment;
032import org.nuxeo.common.utils.FileUtils;
033import org.nuxeo.ecm.core.api.Blob;
034import org.nuxeo.ecm.core.api.Blobs;
035import org.nuxeo.ecm.core.api.DocumentModel;
036import org.nuxeo.ecm.platform.content.template.service.ACEDescriptor;
037import org.nuxeo.ecm.platform.content.template.service.TemplateItemDescriptor;
038import org.nuxeo.ecm.platform.filemanager.api.FileImporterContext;
039import org.nuxeo.ecm.platform.filemanager.api.FileManager;
040import org.nuxeo.runtime.api.Framework;
041
042/**
043 * This factory will import a file using a path defined in the option of the factoryBinding extension point. This path
044 * can be defined using three different prefix. absolute:myAbsolute path will reference a file on the server's
045 * filesystem, nxData:myPath will reference a file inside nuxeo data folder and resource:myPath will reference a file in
046 * the bundle's resources. If the file exist, it's imported by the {@link FileManager} service.
047 *
048 * @author ldoguin
049 */
050public class ImportBasedFactory extends BaseContentFactory {
051
052    private static final Logger log = LogManager.getLogger(ImportBasedFactory.class);
053
054    public static final String IMPORT_FILE_PATH_OPTION = "path";
055
056    public static final String IMPORT_OVERWRITE_OPTION = "overwrite";
057
058    protected FileManager fileManager;
059
060    protected Map<String, String> options;
061
062    protected File importedFile;
063
064    protected Boolean overwrite = false;
065
066    public enum PathOptions {
067        resource {
068            @Override
069            public File getFile(String path) {
070                return FileUtils.getResourceFileFromContext(path);
071            }
072        },
073        nxData {
074            @Override
075            public File getFile(String path) {
076                File nxDdataFolder = Environment.getDefault().getData();
077                return new File(nxDdataFolder, path);
078            }
079        },
080        absolute {
081            @Override
082            public File getFile(String path) {
083                return new File(path);
084            }
085        };
086
087        protected abstract File getFile(String path);
088
089        public static File getResource(String path) {
090            String[] s = path.split(":", 2);
091            String resourceType = s[0];
092            String resourcePath = s[1];
093            PathOptions option = valueOf(resourceType);
094            if (option == null) {
095                log.error("Unsupported resource type: {}", resourceType);
096                return null;
097            } else {
098                return option.getFile(resourcePath);
099            }
100        }
101    }
102
103    @Override
104    public boolean initFactory(Map<String, String> options, List<ACEDescriptor> rootAcl,
105            List<TemplateItemDescriptor> template) {
106        this.options = options;
107        overwrite = Boolean.valueOf(options.get(IMPORT_OVERWRITE_OPTION));
108        String path = options.get(IMPORT_FILE_PATH_OPTION);
109        File file = PathOptions.getResource(path);
110        if (file != null) {
111            if (file.exists()) {
112                importedFile = file;
113                return true;
114            } else {
115                log.warn("Following file does not exist: {}", file::getAbsolutePath);
116            }
117        }
118        return false;
119    }
120
121    @Override
122    public void createContentStructure(DocumentModel eventDoc) {
123        initSession(eventDoc);
124
125        if (eventDoc.isVersion()) {
126            return;
127        }
128        try {
129            String parentPath = eventDoc.getPathAsString();
130            importBlob(importedFile, parentPath);
131        } catch (IOException e) {
132            throw new RuntimeException("Cannot import file: " + importedFile, e);
133        }
134
135    }
136
137    /**
138     * Use fileManager to import the given file.
139     *
140     * @param file to import
141     * @param parentPath of the targetDocument
142     */
143    protected void importBlob(File file, String parentPath) throws IOException {
144        if (file.isDirectory()) {
145            DocumentModel createdFolder = getFileManagerService().createFolder(session, file.getAbsolutePath(),
146                    parentPath, true);
147            File[] files = file.listFiles();
148            for (File childFile : files) {
149                importBlob(childFile, createdFolder.getPathAsString());
150            }
151        } else {
152            Blob fb = Blobs.createBlob(file);
153            fb.setFilename(file.getName());
154            FileImporterContext context = FileImporterContext.builder(session, fb, parentPath)
155                                                             .overwrite(overwrite)
156                                                             .build();
157            getFileManagerService().createOrUpdateDocument(context);
158        }
159    }
160
161    protected FileManager getFileManagerService() {
162        if (fileManager == null) {
163            fileManager = Framework.getService(FileManager.class);
164        }
165        return fileManager;
166    }
167}