Package de.innovationgate.wgpublisher.design.fs

Source Code of de.innovationgate.wgpublisher.design.fs.FileSystemDesignManager$ModuleFile

/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

package de.innovationgate.wgpublisher.design.fs;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.commons.vfs.CacheStrategy;
import org.apache.commons.vfs.Capability;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystem;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.impl.DefaultFileReplicator;
import org.apache.commons.vfs.impl.StandardFileSystemManager;
import org.apache.log4j.Logger;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.Dom4JDriver;

import de.innovationgate.utils.DESEncrypter;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGCSSJSModule;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGDatabaseConnectListener;
import de.innovationgate.webgate.api.WGDatabaseEvent;
import de.innovationgate.webgate.api.WGDocument;
import de.innovationgate.webgate.api.WGFileContainer;
import de.innovationgate.webgate.api.WGTMLModule;
import de.innovationgate.wga.common.Constants;
import de.innovationgate.wga.common.DesignDirectory;
import de.innovationgate.wga.common.DesignDirectory.ScriptInformation;
import de.innovationgate.wga.common.beans.DesignDefinition;
import de.innovationgate.wga.common.beans.csconfig.v1.CSConfig;
import de.innovationgate.wga.common.beans.csconfig.v1.InvalidCSConfigVersionException;
import de.innovationgate.wga.common.beans.csconfig.v1.PluginConfig;
import de.innovationgate.wga.common.beans.csconfig.v1.PublisherOption;
import de.innovationgate.wgpublisher.ManagedDBAttribute;
import de.innovationgate.wgpublisher.WGACore;
import de.innovationgate.wgpublisher.design.sync.DesignSyncManager;
import de.innovationgate.wgpublisher.design.sync.WGDesignSyncException;
import de.innovationgate.wgpublisher.design.sync.WGInitialDeployException;

/**
* Common base class of {@link FileSystemDesignProvider} and {@link DesignSyncManager}
* implementing common functionalities
*
*/
public abstract class FileSystemDesignManager implements WGDatabaseConnectListener, ManagedDBAttribute {

    public static final String OPTION_DESIGNKEY = "designkey";

    public static final String LOGGER_DESIGNSYNC = "wga.designsync";

    public static final String SYNCSTATUS_MODULE = "designsyncstatus";

    public static final String DIRECTORY_DIVIDER = ":";

    public static Map<Integer, DesignInformation> _designTypes = new HashMap<Integer, DesignInformation>();

    protected static XStream _xstream = new XStream(new Dom4JDriver());

    private Pattern _validDesignName = Constants.PATTERN_FILENAMES;

    public static class FileSystemResources {

        private FileObject _baseFolder;

        private FileObject _filesFolder;

        private FileObject _tmlFolder;

        private FileObject _scriptFolder;
       
        private FileObject _javaFolder;

        private FileObject _designDefinitionFile;

        private boolean _updateableFileSystem = true;

        public FileSystemResources(FileObject baseFolder) throws FileSystemException {
            _baseFolder = baseFolder;
            _tmlFolder = _baseFolder.resolveFile(DesignDirectory.FOLDERNAME_TML);
            _scriptFolder = _baseFolder.resolveFile(DesignDirectory.FOLDERNAME_SCRIPT);
            _filesFolder = _baseFolder.resolveFile(DesignDirectory.FOLDERNAME_FILES);
            _javaFolder = _baseFolder.resolveFile(DesignDirectory.FOLDERNAME_JAVA);
           
           
            _designDefinitionFile = DesignDirectory.getDesignDefinitionFile(_baseFolder);
            if (_designDefinitionFile == null) {
                _designDefinitionFile = _baseFolder.resolveFile(DesignDirectory.DESIGN_DEFINITION_FILE);
            }
           
            _updateableFileSystem = !_baseFolder.getFileSystem().hasCapability(Capability.VIRTUAL);
           
        }

        protected FileObject getBaseFolder() {
            return _baseFolder;
        }

        protected FileObject getFilesFolder() {
            return _filesFolder;
        }

        protected FileObject getScriptFolder() {
            return _scriptFolder;
        }

        protected FileObject getDesignDefinitionFile() {
            return _designDefinitionFile;
        }

        protected FileObject getTmlFolder() {
            return _tmlFolder;
        }

        public FileObject getJavaFolder() {
            return _javaFolder;
        }

        protected boolean isUpdateableFileSystem() {
            return _updateableFileSystem;
        }

        public void refreshAll() throws FileSystemException {
            _baseFolder.refresh();
            _designDefinitionFile.refresh();
            _filesFolder.refresh();
            _javaFolder.refresh();
            _scriptFolder.refresh();
            _tmlFolder.refresh();
        }

    }

    public class ModuleFile {

        private FileObject _file;

        private String _prefix;

        private String _category;

        private int _type;

        public ModuleFile(FileObject file, String prefix, String category, int type) throws FileSystemException {
            _file = file;
            _prefix = prefix;
            _category = category;
            _type = type;
        }

        /**
         * @return Returns the file.
         */
        public FileObject getFile() {
            return _file;
        }

        /**
         * @return Returns the prefix.
         */
        public String getPrefix() {
            return _prefix;
        }

        public String getModuleName() {
            String fileName = _file.getName().getBaseName().toLowerCase();
            int suffixPos = fileName.lastIndexOf(".");

            String nameWithoutSuffix;
            if (suffixPos != -1) {
                nameWithoutSuffix = fileName.substring(0, suffixPos);
            }
            else {
                nameWithoutSuffix = fileName;
            }

            if (_prefix == null || _prefix.trim().equals("")) {
                return nameWithoutSuffix;
            }
            else {
                return _prefix + DIRECTORY_DIVIDER + nameWithoutSuffix;
            }
        }

        public String getCategory() {
            return _category;
        }

        public int getType() {
            return _type;
        }

    }

    public static class DesignInformation {

        private Class<? extends DesignMetadata> _metaDataClass;

        public DesignInformation(Class<? extends DesignMetadata> clazz) {
            _metaDataClass = clazz;
        }

        /**
         * @return Returns the metaDataClass.
         */
        public Class<? extends DesignMetadata> getMetaDataClass() {
            return _metaDataClass;
        }
    }

    static {
        // Map design types
        Class<ScriptMetadata> scriptClass = ScriptMetadata.class;
        _designTypes.put(new Integer(WGDocument.TYPE_CSSJS), new DesignInformation(ScriptMetadata.class));
        _designTypes.put(new Integer(WGDocument.TYPE_TML), new DesignInformation(TMLMetadata.class));
        _designTypes.put(new Integer(WGDocument.TYPE_FILECONTAINER), new DesignInformation(FCMetadata.class));
    }

    public static DesignInformation getDesignInformation(int type) {
        return _designTypes.get(new Integer(type));
    }

    protected WGDatabase _db;

    protected Logger _log;

    protected String _designKey;

    private String _fileEncoding = null;

    private DesignDefinition _syncInfo;

    protected WGACore _core;

    protected StandardFileSystemManager _fsManager;

    protected String _designPath;

    protected static final String LOGGER_DESIGNSYNC_QUIET = "wga.designsync.quiet";

    public static final String MODE_FULL = "full";

    public static final String MODE_VIRTUAL = "virtual";

    public static final String MODE_DIRECT = "direct";

    private FileSystemResources _fsResources = null;

    private DESEncrypter _cipher;

    protected boolean _directAccessDefault;

    private CSConfig _csconfig = null;

    protected Set<Integer> _syncedDoctypes = new HashSet<Integer>();

    protected Map<String, String> _designOptions;

    private String _javaClassesPath;

    private Long _designFileTimestamp = null;

    private Long _csconfigTimestamp = null;

    protected boolean _lookupVariants = false;
   
    public FileSystemDesignManager(WGACore core, WGDatabase db, String path, Map<String,String> options) throws WGDesignSyncException, IOException, WGAPIException, InstantiationException,
            IllegalAccessException, InvalidCSConfigVersionException {
        _core = core;

        // Init logger
        if (db.getDbReference().startsWith(PluginConfig.PLUGIN_DBKEY_PREFIX)) {
            _log = Logger.getLogger(LOGGER_DESIGNSYNC_QUIET);
        }
        else {
            _log = Logger.getLogger(LOGGER_DESIGNSYNC);
        }

        _fsManager = new StandardFileSystemManager();
        _fsManager.setCacheStrategy(CacheStrategy.MANUAL);
        _fsManager.setLogger(new Log4JLogger(Logger.getLogger(LOGGER_DESIGNSYNC_QUIET)));
        _fsManager.setClassLoader(WGACore.getLibraryLoader());
        _fsManager.setCacheStrategy(getVFSCacheStrategy());
        _fsManager.init();

        _designPath = path;
        _designOptions = options;
        _designKey = options.get(OPTION_DESIGNKEY);

        _db = db;

        _directAccessDefault = db.getBooleanAttribute(WGACore.DBATTRIB_DIRECTACCESSDEFAULT, false);

        // Determine provided types
        String optionProviderTypes = (String) db.getCreationOptions().get(WGDatabase.COPTION_DESIGNPROVIDERTYPES);
        if (optionProviderTypes != null) {
            Iterator<String> providerTypes = WGUtils.deserializeCollection(optionProviderTypes, ",", true).iterator();
            while (providerTypes.hasNext()) {
                String providerTypeName = providerTypes.next();
                int providerType = WGDocument.doctypeNameToNumber(providerTypeName);
                if (providerType != 0) {
                    _syncedDoctypes.add(new Integer(providerType));
                }
            }
        }
        else {
            _syncedDoctypes.add(new Integer(WGDocument.TYPE_FILECONTAINER));
            _syncedDoctypes.add(new Integer(WGDocument.TYPE_TML));
            _syncedDoctypes.add(new Integer(WGDocument.TYPE_CSSJS));
        }

        fetchFileSystem(core);
        if (_db.isConnected()) {
            init();
        }
        else {
            _db.addDatabaseConnectListener(this);
        }

    }

    protected CacheStrategy getVFSCacheStrategy() {
        return CacheStrategy.ON_RESOLVE;
    }

    protected void closeFileSystem() {

        if (_fsResources != null) {
            FileSystem fs = _fsResources.getBaseFolder().getFileSystem();
            _fsResources = null;
            _fsManager.closeFileSystem(fs);
            _fsManager.freeUnusedResources();
        }

    }

    protected void fetchFileSystem(WGACore core) throws WGDesignSyncException, IOException {

        // Dont run if already fetched
        if (_fsResources != null) {
            return;
        }

        FileObject baseFolder = null;


        try {
            baseFolder = _fsManager.resolveFile(_designPath);
            if (!baseFolder.exists() || !baseFolder.getType().equals(FileType.FOLDER)) {
                throw new WGDesignSyncException("Directory location " + _designPath + " either does not exist or is not directory");
            }
        }
        catch (FileSystemException e) {
            throw new WGDesignSyncException("Unparseable VFS URI: " + _designPath, e);
        }

        _fsResources = new FileSystemResources(baseFolder);
    }

    /**
     * @param doInitSync
     * @return
     * @throws WGAPIException
     * @throws IOException
     * @throws WGDesignSyncException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvalidCSConfigVersionException
     */
    protected boolean init() throws WGAPIException, IOException, WGDesignSyncException, InstantiationException, IllegalAccessException, InvalidCSConfigVersionException {

        // Determine the state of the directory
        FileObject syncInfoFile = getSyncInfoFile();

        if (!syncInfoFile.exists()) {

            // A new directory. Do initial deployment
            if (getBaseFolder().getFileSystem().hasCapability(Capability.CREATE)) {
                _log.info("Performing initial deployment of design to directory '" + getBaseFolder().getURL().toString() + "'");
                _fileEncoding = _core.getWgaConfiguration().getDesignConfiguration().getDefaultEncoding();
                doInitialDeployment(_designKey);
                return true;
            }
            else {
                throw new WGDesignSyncException("Cannot perform initial deploy because the file system is readonly: " + getBaseFolder().getURL().toString());
            }
        }
        else {
            // Determine if syncdata file is present. If so, use this directory
            // as sync directory.
            getOrCreateFolders();
            updateConfiguration();
            return false;

        }

    }

    protected void updateConfiguration() throws IOException, WGDesignSyncException, FileSystemException, InvalidCSConfigVersionException {
       
        boolean configUpdated = false;
       
        // Import config files
        FileObject designFile = getSyncInfoFile();
        long currentDesignFileTimestamp = designFile.getContent().getLastModifiedTime();
        if (_designFileTimestamp == null || currentDesignFileTimestamp > _designFileTimestamp.longValue()) {
            _designFileTimestamp = new Long(currentDesignFileTimestamp);
            importSyncInfo(designFile);
            configUpdated = true;
        }

        FileObject csconfigFile = getFilesFolder().resolveFile("system/csconfig.xml");
        if (csconfigFile.exists()) {
            long currentCsconfigTimestamp = csconfigFile.getContent().getLastModifiedTime();
            if (_csconfigTimestamp == null || currentCsconfigTimestamp > _csconfigTimestamp.longValue()) {
                _csconfigTimestamp = new Long(currentCsconfigTimestamp);
                importCSConfig(csconfigFile);
                configUpdated = true;
            }
        }

        // Load configuration settings
        if (configUpdated) {
            determineFileEncoding();
            determineEncryption();
            determineSyncDefaults();
        }
    }

    private void determineSyncDefaults() {

        if (_csconfig != null) {
            PublisherOption option = _csconfig.findPublisherOption(WGACore.DBATTRIB_DIRECTACCESSDEFAULT);
            if (option != null) {
                _directAccessDefault = Boolean.valueOf(option.getValue()).booleanValue();
            }
        }

    }

    private void importCSConfig(FileObject csconfigFile) throws FileSystemException, IOException, WGDesignSyncException, InvalidCSConfigVersionException {
        if (csconfigFile.exists()) {
            _csconfig = CSConfig.load(csconfigFile);
        }

    }

    private void determineEncryption() throws WGDesignSyncException {
        try {
            FileObject file = getBaseFolder().resolveFile(DesignDirectory.OBFUSCATE_FLAGFILE);
            if (file.exists()) {
                _cipher = new DESEncrypter();
                _cipher.initObfuscation();
            }
        }
        catch (Exception e) {
            throw new WGDesignSyncException("Exception inizializing deobfuscation", e);
        }

    }

    private FileObject getSyncInfoFile() throws WGDesignSyncException {
        if (_fsResources != null) {
            return _fsResources.getDesignDefinitionFile();
        }
        else {
            throw new WGDesignSyncException("The base folder was retrieved from an illegal code position");
        }
    }

    public void close() {
        closeFileSystem();
        _fsManager.close();
    }

    private void importSyncInfo(FileObject syncInfoFile) throws IOException {
        _syncInfo = DesignDefinition.load(syncInfoFile);
    }

    protected void doInitialDeployment(String designKey) throws WGAPIException, IOException, InstantiationException, IllegalAccessException, WGDesignSyncException {

        // Creat folders
        getOrCreateFolders();

        // Deploy TMLs
        Iterator modules = getDB().getTMLModules().iterator();
        WGTMLModule mod;
        while (modules.hasNext()) {
            mod = (WGTMLModule) modules.next();
            if (isValidDesignName(mod.getName())) {
                initialDeployTMLModule(mod);
            }
            else {
                _log.warn("Could not use '" + mod.getDocumentKey() + "' for design deployment since the name contains invalid characters");
            }
        }

        // Deploy file containers
        Iterator containers = getDB().getFileContainers().iterator();
        WGFileContainer con;
        while (containers.hasNext()) {
            con = (WGFileContainer) containers.next();
            if (isValidDesignName(con.getName())) {
                initialDeployFileContainer(con);
            }
            else {
                _log.warn("Could not use '" + con.getDocumentKey() + "' for design deployment since the name contains invalid characters");
            }
        }

        // Deploy script modules
        Iterator scripts = getDB().getCSSJSModules().iterator();
        WGCSSJSModule script;
        while (scripts.hasNext()) {
            script = (WGCSSJSModule) scripts.next();
            if (isValidDesignName(script.getName())) {
                initialDeployScriptModule(script);
            }
            else {
                _log.warn("Could not use '" + script.getDocumentKey() + "' for design deployment since the name contains invalid characters");
            }
        }

        // Create sync info and store it to directory
        _syncInfo = new DesignDefinition();
        _syncInfo.setDesignKey(designKey);
        if (_core.getWgaConfiguration().getDesignConfiguration().getDefaultEncoding() != null) {
            _syncInfo.setFileEncoding(_core.getWgaConfiguration().getDesignConfiguration().getDefaultEncoding());
        }
        else {
            // if encoding not specified set to platform encoding
            _syncInfo.setFileEncoding(System.getProperty("file.encoding"));
        }
        FileObject syncInfoFile = getSyncInfoFile();
        _log.info("Creating design definition file " + syncInfoFile.getName().getPath());
        syncInfoFile.createFile();
        storeSyncInfo(syncInfoFile);

        _log.info("Initial deploy finished");

    }

    private boolean isValidDesignName(String name) {

        return _validDesignName.matcher(name).matches();

    }

    private void getOrCreateFolders() throws IOException, WGDesignSyncException {
        if (getBaseFolder().getFileSystem().hasCapability(Capability.CREATE)) {
            WGUtils.getOrCreateFolder(getBaseFolder(), DesignDirectory.FOLDERNAME_TML);
            WGUtils.getOrCreateFolder(getBaseFolder(), DesignDirectory.FOLDERNAME_SCRIPT);
            WGUtils.getOrCreateFolder(getBaseFolder(), DesignDirectory.FOLDERNAME_FILES);

            Iterator scriptInfos = DesignDirectory.getScriptTypes().values().iterator();
            while (scriptInfos.hasNext()) {
                ScriptInformation info = (ScriptInformation) scriptInfos.next();
                if (info.isAutoCreate()) {
                    WGUtils.getOrCreateFolder(getScriptFolder(), info.getFolder());
                }
            }
           
            if (_fsResources.getJavaFolder().exists()) {
                _javaClassesPath = _fsResources.getJavaFolder().getName().getPath();
            }
        }
    }

    protected FileObject getFilesFolder() throws WGDesignSyncException {
        if (_fsResources != null) {
            return _fsResources.getFilesFolder();
        }
        else {
            throw new WGDesignSyncException("The files folder was retrieved from an illegal code position");
        }
    }

    protected FileObject getScriptTypeFolder(String folderName) throws FileSystemException, WGDesignSyncException {
        FileObject scriptFolder = getScriptFolder();
        if (scriptFolder.exists()) {
            return scriptFolder.getChild(folderName);
        }
        else {
            return null;
        }
    }

    protected FileObject getScriptFolder() throws WGDesignSyncException {
        if (_fsResources != null) {
            return _fsResources.getScriptFolder();
        }
        else {
            throw new WGDesignSyncException("The base folder was retrieved from an illegal code position");
        }
    }

    private void storeSyncInfo(FileObject syncInfoFile) throws IOException {
        _syncInfo.write(syncInfoFile);
    }

    private Writer createWriter(FileObject file) throws IOException {
        return new OutputStreamWriter(file.getContent().getOutputStream(), getFileEncoding());
    }

    protected FileObject initialDeployScriptModule(WGCSSJSModule script) throws IOException, InstantiationException, IllegalAccessException, WGAPIException, WGDesignSyncException {

        if (script.isMetadataModule()) {
            return null;
        }

        ScriptInformation info = DesignDirectory.getScriptInformation(script.getCodeType());
        if (info == null) {
            _log.warn("Cannot deploy unknown script code type: " + script.getCodeType());
            return null;
        }

        // Get script type folder
        FileObject scriptTypeFolder = getScriptTypeFolder(info.getFolder());

        // Eventually create intermediate directories
        List<String> path = WGUtils.deserializeCollection(script.getName(), ":", true);
        String localName = (String) path.get(path.size() - 1);
        FileObject currentDir = scriptTypeFolder;
        for (int i = 0; i < path.size() - 1; i++) {
            currentDir = currentDir.resolveFile((String) path.get(i));
            if (!currentDir.exists()) {
                _log.info("Creating script category directory" + getRelativePath(currentDir));
                try {
                    currentDir.createFolder();
                }
                catch (FileSystemException e) {
                    throw new WGInitialDeployException("Could not create script category folder '" + getRelativePath(currentDir) + "'", e);
                }
            }
            else if (!currentDir.getType().equals(FileType.FOLDER)) {
                throw new WGInitialDeployException("Cannot deploy " + script.getDocumentKey() + " to sync folder because the directory name '" + path.get(i) + "' is already used by another file");
            }
        }

        // Create code file
        FileObject codeFile = currentDir.resolveFile(localName + info.getSuffix());
        _log.info("Creating script module file " + getRelativePath(codeFile));
        try {
            codeFile.createFile();
        }
        catch (FileSystemException e) {
            throw new WGInitialDeployException("Could not create script code file '" + codeFile.getName().getPathDecoded() + "'");
        }
        Writer writer = createWriter(codeFile);
        writer.write(script.getCode());
        writer.close();

        // Create metadata file
        ScriptMetadata metaData = new ScriptMetadata(script);
        FileObject metadataDir = currentDir.resolveFile(DesignDirectory.NAME_METADATADIR);
        if (!metadataDir.exists()) {
            _log.info("Creating script metadata directory " + getRelativePath(metadataDir));
            try {
                metadataDir.createFolder();
            }
            catch (FileSystemException e) {
                throw new WGInitialDeployException("Could not create metadata folder '" + getRelativePath(metadataDir) + "'");
            }
        }
        FileObject metadataFile = metadataDir.resolveFile(localName + DesignDirectory.SUFFIX_METADATA);
        _log.info("Creating script metadata file " + getRelativePath(metadataFile));
        writer = createWriter(metadataFile);
        writer.write(_xstream.toXML(metaData.getInfo()));
        writer.close();

        return codeFile;
    }

    protected FileObject initialDeployFileContainer(WGFileContainer con) throws IOException, InstantiationException, IllegalAccessException, WGAPIException, WGDesignSyncException {

        // Create container folder
        FileObject containerFolder = getFilesFolder().resolveFile(con.getName());
        _log.info("Creating file container folder " + getRelativePath(containerFolder));
        try {
            containerFolder.createFolder();
        }
        catch (FileSystemException e) {
            throw new WGInitialDeployException("Could not create file container folder '" + containerFolder.getName().getPathDecoded() + "'", e);
        }

        // Create metadata file
        FCMetadata metaData = new FCMetadata(con);
        FileObject metadataFile = containerFolder.resolveFile(AbstractDesignFile.FILECONTAINER_METADATA_FILENAME + DesignDirectory.SUFFIX_METADATA);
        _log.info("Creating file container metadata file " + getRelativePath(metadataFile));
        Writer writer = createWriter(metadataFile);
        writer.write(_xstream.toXML(metaData.getInfo()));
        writer.close();

        // Create contained files
        Iterator fileNames = con.getFileNames().iterator();
        String fileName;
        FileObject file;
        while (fileNames.hasNext()) {
            fileName = (String) fileNames.next();
            InputStream in = con.getFileData(fileName);
            file = containerFolder.resolveFile(fileName);
            _log.info("Creating file container file " + getRelativePath(file));
            try {
                file.createFile();
            }
            catch (FileSystemException e) {
                throw new WGInitialDeployException("Could not create container file '" + getRelativePath(file) + "'", e);
            }
            OutputStream out = file.getContent().getOutputStream();
            WGUtils.inToOut(in, out, 2048);
            in.close();
            out.close();
        }

        return containerFolder;

    }

    protected FileObject initialDeployTMLModule(WGTMLModule mod) throws IOException, InstantiationException, IllegalAccessException, WGAPIException, WGDesignSyncException {

        // Find/create media key folder
        FileObject mediaKeyFolder = getTmlFolder().resolveFile(mod.getMediaKey());
        if (!mediaKeyFolder.exists()) {
            _log.info("Creating media key folder " + getRelativePath(mediaKeyFolder));
            try {
                mediaKeyFolder.createFolder();
            }
            catch (FileSystemException e) {
                throw new WGInitialDeployException("Could not create media key folder '" + mediaKeyFolder.getName().getPathDecoded() + "'");
            }
        }

        // Eventually create intermediate directories
        List<String> path = WGUtils.deserializeCollection(mod.getName(), ":", true);
        String localName = (String) path.get(path.size() - 1);
        FileObject currentDir = mediaKeyFolder;
        for (int i = 0; i < path.size() - 1; i++) {
            currentDir = currentDir.resolveFile((String) path.get(i));
            if (!currentDir.exists()) {
                _log.info("Creating tml category directory " + getRelativePath(currentDir));
                try {
                    currentDir.createFolder();
                }
                catch (FileSystemException e) {
                    throw new WGInitialDeployException("Could not create tml category folder '" + getRelativePath(currentDir) + "'", e);
                }
            }
            else if (!currentDir.getType().equals(FileType.FOLDER)) {
                throw new WGInitialDeployException("Cannot deploy " + mod.getDocumentKey() + " to sync folder because the directory name '" + path.get(i) + "' is already used by another file");

            }
        }

        // Create code file
        FileObject tmlCodeFile = currentDir.resolveFile(localName + DesignDirectory.SUFFIX_TML);
        _log.info("Creating tml module file " + getRelativePath(tmlCodeFile));
        try {
            tmlCodeFile.createFile();
        }
        catch (FileSystemException e) {
            throw new WGInitialDeployException("Could not create tml code file '" + getRelativePath(tmlCodeFile) + "'");
        }
        Writer writer = createWriter(tmlCodeFile);
        writer.write(mod.getCode());
        writer.close();

        // Create metadata file
        TMLMetadata metaData = new TMLMetadata(mod);
        FileObject metadataDir = currentDir.resolveFile(DesignDirectory.NAME_METADATADIR);
        if (!metadataDir.exists()) {
            _log.info("Creating tml metadata directory " + getRelativePath(metadataDir));
            try {
                metadataDir.createFolder();
            }
            catch (FileSystemException e) {
                throw new WGInitialDeployException("Could not create metadata folder '" + metadataDir.getName().getPathDecoded() + "'");
            }
        }

        FileObject metadataFile = metadataDir.resolveFile(localName + DesignDirectory.SUFFIX_METADATA);
        _log.info("Creating tml metadata file " + getRelativePath(metadataFile));
        writer = createWriter(metadataFile);
        writer.write(_xstream.toXML(metaData.getInfo()));
        writer.close();

        return tmlCodeFile;
    }

    protected String getRelativePath(FileObject file) throws FileSystemException, WGDesignSyncException {
        return getBaseFolder().getName().getRelativeName(file.getName());
    }

    public WGDatabase getDB() {
        return _db;
    }

    private void determineFileEncoding() throws IOException, WGDesignSyncException, InvalidCSConfigVersionException {

        // Either encoding is set in syncinfo.xml, or syncinfo.xml points to
        // csconfig.xml
        if (_syncInfo.getFileEncoding() == null) {
            _fileEncoding = System.getProperty("file.encoding");
            _log.debug("Design of " + _db.getDbReference() + " uses file encoding " + _fileEncoding + " to read design files (platform default)");
        }
        else if (_syncInfo.getFileEncoding().equals(DesignDefinition.FILEENCODING_CSCONFIG_DEFINED)) {
            if (_csconfig != null) {
                PublisherOption option = _csconfig.findPublisherOption(WGACore.DBATTRIB_DESIGN_ENCODING);
                if (option != null) {
                    _fileEncoding = option.getValue();
                    _log.debug("Design of " + _db.getDbReference() + " uses file encoding '" + _fileEncoding + "' to read design files (as specified in design configuration)");
                }
                else {
                    _fileEncoding = System.getProperty("file.encoding");
                    _log.debug("Design of " + _db.getDbReference() + " uses file encoding " + _fileEncoding + " to read design files (platform default)");
                }
            }
            else {
                _fileEncoding = System.getProperty("file.encoding");
                _log.warn("Error in design of " + _db.getDbReference() + ": According to the design definition the design file encoding is configured in design configuration (csconfig.xml), but there is no csconfig.xml");
                _log.warn("WGA will use the platform encoding '" + _fileEncoding + "' for reading text files");
            }
        }

        else {
            _fileEncoding = _syncInfo.getFileEncoding();
            _log.debug("Design of " + _db.getDbReference() + " uses file encoding '" + _fileEncoding + "' to read design files (as specified in design configuration)");
        }

    }

    protected List<ModuleFile> getModuleFiles(int type, FileObject dir, String category) throws WGDesignSyncException, FileSystemException {
        return getModuleFiles(type, dir, "", category);

    }

    private List<ModuleFile> getModuleFiles(int type, FileObject dir, String prefix, String category) throws WGDesignSyncException, FileSystemException {

        List<ModuleFile> moduleFiles = new ArrayList<ModuleFile>();
        if (dir == null || !dir.exists()) {
            return moduleFiles;
        }

        FileObject[] files = dir.getChildren();
        if (files == null) {
            throw new WGDesignSyncException("Cannot collect files from directory '" + dir.getName().getPathDecoded() + "'. Please verify directory existence.");
        }

        FileObject file;
        for (int i = 0; i < files.length; i++) {
            file = files[i];
            if (!isValidDesignFile(file)) {
                continue;
            }
            if (file.getType().equals(FileType.FOLDER)) {
                if (file.getName().getBaseName().equals(DesignDirectory.NAME_METADATADIR)) {
                    continue;
                }
                String newPrefix = (prefix.trim().equals("") ? file.getName().getBaseName().toLowerCase() : prefix + DIRECTORY_DIVIDER + file.getName().getBaseName().toLowerCase());
                moduleFiles.addAll(getModuleFiles(type, file, newPrefix, category));
            }
            else {
                // Test the file suffix
                if (type == WGDocument.TYPE_TML) {
                    if (!file.getName().getBaseName().contains(DesignDirectory.SUFFIX_TML)) {
                        continue;
                    }
                }
                else if (type == WGDocument.TYPE_CSSJS) {
                    ScriptInformation scriptInfo = DesignDirectory.getScriptInformationBySuffix("." + file.getName().getExtension());
                    if (scriptInfo == null) {
                        continue;
                    }
                }
                moduleFiles.add(new ModuleFile(file, prefix, category, type));
            }
        }

        return moduleFiles;

    }

    /**
     * @return Returns the tmlFolder.
     * @throws WGDesignSyncException
     */
    public FileObject getTmlFolder() throws WGDesignSyncException {
        if (_fsResources != null) {
            return _fsResources.getTmlFolder();
        }
        else {
            throw new WGDesignSyncException("The base folder was retrieved from an illegal code position");
        }
    }

    public boolean isValidDesignFile(FileObject file) {
        return !file.getName().getBaseName().startsWith(".") && _core.getDesignFileValidator().isValidFileName(file.getName().getBaseName());
    }

    public WGACore getWGACore() {
        return _core;
    }

    public DesignDefinition getSyncInfo() {
        return _syncInfo;
    }

    protected String getFileEncoding() {
        return _fileEncoding;
    }

    protected FileObject getBaseFolder() throws WGDesignSyncException {
        if (_fsResources != null) {
            return _fsResources.getBaseFolder();
        }
        else {
            throw new WGDesignSyncException("The base folder was retrieved from an illegal code position");
        }
    }

    protected DESEncrypter getCipher() {
        return _cipher;
    }

    public String getDesignPath() {
        return _designPath;
    }

    public Logger getLog() {
        return _log;
    }

    public boolean isDirectAccessDefault() {
        return _directAccessDefault;
    }

    public Set<Integer> getSyncedDoctypes() {
        return _syncedDoctypes;
    }

    public void databaseConnected(WGDatabaseEvent event) {

        try {
            fetchFileSystem(_core);
            try {
                init();
            }
            catch (Exception e) {
                _log.error("Error initializing file system design", e);
            }

        }
        catch (Exception e) {
            _log.error("Error fetching file system for WGA design of lazily connected db", e);
        }
    }

    public void databaseConnectionError(WGDatabaseEvent event) {
    }

    protected List<ModuleFile> getTMLModuleFiles() throws FileSystemException, WGDesignSyncException {
        // Iterate thru media key folders
        FileObject[] mediaKeyFolders = getTmlFolder().getChildren();
        if (mediaKeyFolders == null) {
            throw new WGDesignSyncException("Cannot collect modules from directory '" + getTmlFolder().getName().getPathDecoded() + "'. Please verify directory existence.");
        }

        FileObject mediaKeyFolder;
        List<ModuleFile> files = new ArrayList();
        for (int mediaKeyIdx = 0; mediaKeyIdx < mediaKeyFolders.length; mediaKeyIdx++) {
            mediaKeyFolder = mediaKeyFolders[mediaKeyIdx];
            if (!mediaKeyFolder.getType().equals(FileType.FOLDER)) {
                continue;
            }
            if (!isValidDesignFile(mediaKeyFolder)) {
                continue;
            }
            String mediaKey = mediaKeyFolder.getName().getBaseName().toLowerCase();
            files.addAll(getModuleFiles(WGDocument.TYPE_TML, mediaKeyFolder, mediaKey));
        }
        return files;
    }

    protected List<ModuleFile> getScriptModuleFiles() throws WGDesignSyncException, FileSystemException {
        List<ModuleFile> files = new ArrayList();

        // Get all files from script folders
        Iterator scriptInfos = DesignDirectory.getScriptTypes().values().iterator();
        while (scriptInfos.hasNext()) {
            ScriptInformation info = (ScriptInformation) scriptInfos.next();
            files.addAll(getModuleFiles(WGDocument.TYPE_CSSJS, getScriptTypeFolder(info.getFolder()), info.getType()));

        }
        return files;
    }

    protected List<ModuleFile> getFileContainerFiles() throws FileSystemException, WGDesignSyncException {
        FileObject filesFolder = getFilesFolder();
        List<ModuleFile> designFiles = getFileContainerFiles(filesFolder, "");
       
        return designFiles;
    }

    private List<ModuleFile> getFileContainerFiles(FileObject filesFolder, String prefix) throws FileSystemException {
        FileObject[] files = filesFolder.getChildren();
        List<ModuleFile> designFiles = new ArrayList<ModuleFile>();
        for (int i = 0; i < files.length; i++) {
            FileObject file = files[i];
            if (file.getType().equals(FileType.FOLDER) && isValidDesignFile(file)) {
                designFiles.add(new ModuleFile(file, prefix, "", WGDocument.TYPE_FILECONTAINER));
                String newPrefix = (prefix.trim().equals("") ? file.getName().getBaseName().toLowerCase() : prefix + DIRECTORY_DIVIDER + file.getName().getBaseName().toLowerCase());
                designFiles.addAll(getFileContainerFiles(file, newPrefix));
            }
        }
        return designFiles;
    }

    protected ModuleFile getFileContainerFile(String name) throws FileSystemException, WGDesignSyncException {
       
        FileObject folder = getFilesFolder();
        List<String> paths = WGUtils.deserializeCollection(name, ":");
        boolean found = false;
       
        for (String path : paths) {
            FileObject fileContainer = findMatchingChild(folder, path, true);
            if (fileContainer != null && fileContainer.getType().equals(FileType.FOLDER) && isValidDesignFile(fileContainer)) {
                found = true;
                folder = fileContainer;
            }
            else {
                found = false;
                break;
            }
        }
       
        if (found == true) {
            return new ModuleFile(folder, WGUtils.serializeCollection(paths.subList(0, paths.size() - 1), ":")"", WGDocument.TYPE_FILECONTAINER);
        }
        else {
            return null;
        }
       
       
    }

    protected ModuleFile getScriptModuleFile(String name, String type) throws FileSystemException, WGDesignSyncException {

        ScriptInformation info = DesignDirectory.getScriptInformation(type);
        if (info == null) {
            return null;
        }
       
        FileObject scriptTypeFolder = getScriptTypeFolder(info.getFolder());
        if (scriptTypeFolder == null) {
            return null;
        }
       
        return resolveModuleFile(scriptTypeFolder, name, info.getFolder(), WGDocument.TYPE_CSSJS);

    }

    protected ModuleFile getTMLModuleFile(String name, String strMediaKey) throws FileSystemException, WGDesignSyncException {
        return resolveModuleFile(getTmlFolder().getChild(strMediaKey.toLowerCase()), name, strMediaKey, WGDocument.TYPE_TML);

    }

    private ModuleFile resolveModuleFile(FileObject folder, String name, String category, int type) throws FileSystemException {

        if (folder == null || !folder.exists() || !folder.getType().equals(FileType.FOLDER)) {
            return null;
        }

        String prefix;
        String baseName;
        String suffix = (type == WGDocument.TYPE_TML ? DesignDirectory.SUFFIX_TML : DesignDirectory.getScriptInformation(category).getSuffix());
        int lastColon = name.lastIndexOf(":");
        if (lastColon != -1) {
            prefix = name.substring(0, lastColon);
            baseName = name.substring(lastColon + 1) + suffix;
        }
        else {
            prefix = "";
            baseName = name + suffix;
        }

        // Find correct folder
        if (!prefix.equals("")) {
            List<String> path = WGUtils.deserializeCollection(prefix, ":");
            Iterator<String> elems = path.iterator();
            while (elems.hasNext()) {
                String elem = (String) elems.next();
                FileObject matchingChild = findMatchingChild(folder, elem, true);

                // Use matching child as next folder
                if (matchingChild != null && matchingChild.getType().equals(FileType.FOLDER)) {
                    folder = matchingChild;
                }

                // Exit if we did not find a matching folder
                else {
                    return null;
                }

            }
        }

        // Find the file
        FileObject file = findMatchingChild(folder, baseName, false);
        if (file != null) {
            return new ModuleFile(file, prefix, category, type);
        }
        else {
            return null;
        }

    }

    /**
     * Does a case insensitive search for a file of the given name in the given
     * folder
     *
     * @param folder
     *            The folder to search
     * @param elem
     *            File name to search
     * @return
     * @throws FileSystemException
     */
    private FileObject findMatchingChild(FileObject folder, String elem, boolean exactMatch) throws FileSystemException {
        FileObject matchingChild = null;

        // First try fast straight fetch using lowercase file
        FileObject straightChild = folder.getChild(elem.toLowerCase());
        if (straightChild != null && straightChild.exists()) {
            matchingChild = straightChild;
        }
        else {
            // Secondly we iterate over all children and to a case-insensitive
            // equals
            FileObject[] children = folder.getChildren();

            for (FileObject child : children) {
                if (exactMatch) {
                    if (child.getName().getBaseName().equalsIgnoreCase(elem)) {
                        matchingChild = child;
                        break;
                    }
                }
                else {
                    String fileName = child.getName().getBaseName().toLowerCase();
                    String elementName = elem.toLowerCase();
                    if (fileName.startsWith(elementName) && fileName.indexOf(".", elem.length()) == -1) {
                        matchingChild = child;
                        break;
                    }
                }
            }
        }
        return matchingChild;
    }

    protected static String getLOGGER_DESIGNSYNC() {
        return LOGGER_DESIGNSYNC;
    }

    protected static String getSYNCSTATUS_MODULE() {
        return SYNCSTATUS_MODULE;
    }

    protected static String getDIRECTORY_DIVIDER() {
        return DIRECTORY_DIVIDER;
    }

    protected static Map<Integer, DesignInformation> getDesignTypes() {
        return _designTypes;
    }

    protected static XStream getXstream() {
        return _xstream;
    }

    protected Pattern getValidDesignName() {
        return _validDesignName;
    }

    protected WGDatabase getDb() {
        return _db;
    }

    protected String getDesignKey() {
        return _designKey;
    }

    protected WGACore getCore() {
        return _core;
    }

    protected StandardFileSystemManager getFsManager() {
        return _fsManager;
    }

    protected static String getLOGGER_DESIGNSYNC_QUIET() {
        return LOGGER_DESIGNSYNC_QUIET;
    }

    protected static String getMODE_FULL() {
        return MODE_FULL;
    }

    protected static String getMODE_VIRTUAL() {
        return MODE_VIRTUAL;
    }

    protected static String getMODE_DIRECT() {
        return MODE_DIRECT;
    }

    protected FileSystemResources getFsResources() {
        return _fsResources;
    }

    protected CSConfig getCsconfig() {
        return _csconfig;
    }

    protected Map<String, String> getDesignOptions() {
        return _designOptions;
    }

    public String getJavaClassesPath() {
        return _javaClassesPath;
    }

    public int designHashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((_designPath == null) ? 0 : _designPath.hashCode());
        result = prime * result + ((_fileEncoding == null) ? 0 : _fileEncoding.hashCode());
        return result;
    }



}
TOP

Related Classes of de.innovationgate.wgpublisher.design.fs.FileSystemDesignManager$ModuleFile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.