001/*
002 *  Copyright 2010 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.workflow;
017
018import java.io.ByteArrayInputStream;
019import java.io.File;
020import java.io.IOException;
021import java.io.InputStream;
022import java.nio.charset.StandardCharsets;
023import java.nio.file.Files;
024import java.nio.file.Paths;
025
026import org.apache.commons.io.FileUtils;
027import org.apache.commons.io.FilenameUtils;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030import org.w3c.dom.Element;
031
032import com.opensymphony.workflow.loader.XMLWorkflowFactory;
033
034/**
035 * A XML factory for finding workflows definitions in
036 * <code>context://WEB-INF/param/workflows.xml</code>
037 * 
038 * or if the file does not exits, built from the content of the <code>context://WEB-INF/workflows/*.xml</code> files 
039 */
040public class XmlWorkflowFactory extends XMLWorkflowFactory
041{
042    // Path to the XML for the configuration of the workflow.
043    private static final String __CONFIG_FILE = "workflows.xml";
044    // Path to the directory having the XML workflows.
045    private static final String __CONFIG_DIRECTORY = "workflows";
046
047    /** Logger for traces. */
048    protected Logger _logger = LoggerFactory.getLogger(getClass());
049    
050    private String _contextPath;
051
052    /**
053     * Constructor.
054     * @param contextPath The webapp context path 
055     * @throws Exception if an error occurs.
056     */
057    public XmlWorkflowFactory(String contextPath) throws Exception
058    {
059        _contextPath = contextPath;
060    }
061
062    @Override
063    protected InputStream getInputStream(String name)
064    {
065        File workflowsFile = new File(_contextPath, __CONFIG_FILE);
066        if (workflowsFile.exists() && workflowsFile.isFile())
067        {
068            if (_logger.isDebugEnabled())
069            {
070                _logger.debug("Readinng workflows configuration file at " + workflowsFile.getAbsolutePath());
071            }
072            try
073            {
074                return Files.newInputStream(Paths.get(workflowsFile.getAbsolutePath()));
075            }
076            catch (IOException e)
077            {
078                _logger.error("An error occurred reading the workflows configuration file at " + workflowsFile.getAbsolutePath(), e);
079                return null;
080            }
081        }
082        else
083        {
084            if (_logger.isDebugEnabled())
085            {
086                _logger.debug("No workflows configuration file at " + workflowsFile.getAbsolutePath() + ". Creating it.");
087            }
088            
089            File workflowsDirectory = new File(_contextPath, __CONFIG_DIRECTORY);
090            if (workflowsDirectory.exists() && workflowsDirectory.isDirectory())
091            {
092                StringBuilder hotFile = new StringBuilder();
093                hotFile.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
094                hotFile.append("<workflows>\n");
095                
096                for (File file : FileUtils.listFiles(workflowsDirectory, new String[] {"xml"}, false))
097                {
098                    hotFile.append("\t<workflow name=\"");
099                    hotFile.append(FilenameUtils.removeExtension(file.getName()));
100                    hotFile.append("\" type=\"file\" location=\"");
101                    hotFile.append(__CONFIG_DIRECTORY);
102                    hotFile.append(File.separator);
103                    hotFile.append(file.getName());
104                    hotFile.append("\"/>\n");
105                }
106    
107                hotFile.append("</workflows>\n");
108                
109                return new ByteArrayInputStream(hotFile.toString().getBytes(StandardCharsets.UTF_8));
110            }
111            else
112            {
113                _logger.error("Found neither workflows configuration file at " + workflowsFile.getAbsolutePath() + " nor workflows directory at " + workflowsDirectory.getAbsolutePath());
114                return null;
115            }
116        }
117    }
118
119    @Override
120    protected String getBaseDir(Element root)
121    {
122        return new File(_contextPath).getPath();
123    }
124}