first pass at add content from xforms ui

- added an add content panel to the file picker which enables browsing the local disk to select content to upload.  the file is uploaded without requiring a browser refresh by targeting a hidden iframe.  the server response includes a js call which notifies the form that the upload is complete.
- added annotations to ajax methods to enable specifying the response mime type of the method.  needed for uploadFile which returns html rather than xml
- minor cleanup in schemaformbuilder
- added mapping between xsl-fo mimetypes and those in mimetype map


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4576 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Ariel Backenroth
2006-12-12 03:13:23 +00:00
parent 66ca97a16a
commit cb80c75014
12 changed files with 559 additions and 176 deletions

View File

@@ -35,9 +35,11 @@ public interface FormProcessor
*/
public interface InstanceData
{
public Document getContent();
public void setContent(final Document d);
public Document load();
public void save(final Document d,
final String[] uploadedFilePaths);
}
/////////////////////////////////////////////////////////////////////////////

View File

@@ -89,9 +89,6 @@ public final class FormsService
private static FormsService INSTANCE;
private static DocumentBuilder documentBuilder;
/** internal storage of forms, keyed by the form name */
private HashMap<String, Form> forms = new HashMap<String, Form>();
private static final RenderingEngine[] RENDERING_ENGINES = new RenderingEngine[]
{
new FreeMarkerRenderingEngine(),
@@ -101,8 +98,6 @@ public final class FormsService
private final ContentService contentService;
private final NodeService nodeService;
private final FileFolderService fileFolderService;
private final DictionaryService dictionaryService;
private final NamespaceService namespaceService;
private final SearchService searchService;
private final AVMService avmService;
@@ -112,16 +107,12 @@ public final class FormsService
/** instantiated using spring */
public FormsService(final ContentService contentService,
final NodeService nodeService,
final FileFolderService fileFolderService,
final DictionaryService dictionaryService,
final NamespaceService namespaceService,
final SearchService searchService,
final AVMService avmService)
{
this.contentService = contentService;
this.nodeService = nodeService;
this.fileFolderService = fileFolderService;
this.dictionaryService = dictionaryService;
this.namespaceService = namespaceService;
this.searchService = searchService;
this.avmService = avmService;

View File

@@ -37,6 +37,11 @@ public interface RenderingEngine
extends Exception
{
public RenderingException(final String msg)
{
super(msg);
}
public RenderingException(final Exception cause)
{
super(cause);

View File

@@ -22,9 +22,6 @@ import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.*;
@@ -33,9 +30,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.FormattingResults;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.apps.PageSequenceResults;
/**
* A rendering engine which uses xsl-fo templates to generate renditions of
@@ -49,6 +44,33 @@ public class XSLFORenderingEngine
private static final Log LOGGER = LogFactory.getLog(XSLFORenderingEngine.class);
private static final Map<String, String> MIME_TYPES =
new HashMap<String, String>();
static
{
MIME_TYPES.put(MimeConstants.MIME_PDF, MimeConstants.MIME_PDF);
MIME_TYPES.put(MimeConstants.MIME_POSTSCRIPT, MimeConstants.MIME_POSTSCRIPT);
MIME_TYPES.put(MimeConstants.MIME_EPS, MimeConstants.MIME_POSTSCRIPT);
MIME_TYPES.put(MimeConstants.MIME_PLAIN_TEXT, MimeConstants.MIME_PLAIN_TEXT);
MIME_TYPES.put(MimeConstants.MIME_RTF, MimeConstants.MIME_RTF);
MIME_TYPES.put(MimeConstants.MIME_RTF_ALT1, MimeConstants.MIME_RTF);
MIME_TYPES.put(MimeConstants.MIME_RTF_ALT2, MimeConstants.MIME_RTF);
MIME_TYPES.put(MimeConstants.MIME_MIF, MimeConstants.MIME_MIF);
MIME_TYPES.put("application/x-mif", MimeConstants.MIME_MIF);
MIME_TYPES.put(MimeConstants.MIME_SVG, MimeConstants.MIME_SVG);
MIME_TYPES.put("image/svg", MimeConstants.MIME_SVG);
MIME_TYPES.put(MimeConstants.MIME_GIF, MimeConstants.MIME_GIF);
MIME_TYPES.put(MimeConstants.MIME_PNG, MimeConstants.MIME_PNG);
MIME_TYPES.put(MimeConstants.MIME_JPEG, MimeConstants.MIME_JPEG);
MIME_TYPES.put(MimeConstants.MIME_TIFF, MimeConstants.MIME_TIFF);
};
public XSLFORenderingEngine()
{
super();
@@ -72,16 +94,21 @@ public class XSLFORenderingEngine
RenderingEngine.RenderingException
{
Result result = null;
String mimetype = MIME_TYPES.get(ret.getMimetypeForRendition());
if (mimetype == null)
{
throw new RenderingEngine.RenderingException("mimetype " + ret.getMimetypeForRendition() +
" is not supported by " + this.getName());
}
try
{
final FopFactory fopFactory = FopFactory.newInstance();
final FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
final Fop fop = fopFactory.newFop(ret.getMimetypeForRendition(),
final Fop fop = fopFactory.newFop(mimetype,
foUserAgent,
out);
// Resulting SAX events (the generated FO) must be piped through to FOP
result = new SAXResult(fop.getDefaultHandler());
}
catch (FOPException fope)
{

View File

@@ -390,7 +390,6 @@ public class SchemaFormBuilder
formContentWrapper,
schema,
rootElementDecl,
rootElementDecl.getTypeDefinition(),
"/" + getElementName(rootElementDecl, xForm));
if (importedInstanceDocumentElement != null)
{
@@ -1058,9 +1057,9 @@ public class SchemaFormBuilder
final Element formSection,
final XSModel schema,
final XSElementDeclaration elementDecl,
XSTypeDefinition controlType,
final String pathToRoot) {
final String pathToRoot)
{
XSTypeDefinition controlType = elementDecl.getTypeDefinition();
if (controlType == null)
{
// TODO!!! Figure out why this happens... for now just warn...
@@ -1664,7 +1663,6 @@ public class SchemaFormBuilder
repeatContentWrapper,
schema,
element,
element.getTypeDefinition(),
path);
final SchemaUtil.Occurance elementOccurs = SchemaUtil.getOccurance(element);

View File

@@ -16,50 +16,51 @@
*/
package org.alfresco.web.forms.xforms;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
import java.util.LinkedList;
import java.io.*;
import java.util.*;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ExternalContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.web.bean.wcm.AVMConstants;
import org.alfresco.web.forms.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.alfresco.util.TempFileProvider;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.FileUploadBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.wcm.AVMBrowseBean;
import org.alfresco.web.bean.wcm.AVMConstants;
import org.alfresco.web.forms.*;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.chiba.xml.xforms.ChibaBean;
import org.chiba.xml.xforms.Instance;
import org.chiba.xml.xforms.XFormsElement;
import org.chiba.xml.xforms.connector.http.AbstractHTTPConnector;
import org.chiba.xml.xforms.core.ModelItem;
import org.chiba.xml.xforms.exception.XFormsException;
import org.chiba.xml.xforms.events.XFormsEvent;
import org.chiba.xml.xforms.events.XFormsEventFactory;
import org.chiba.xml.xforms.exception.XFormsException;
import org.chiba.xml.xforms.ui.BoundElement;
import org.chiba.xml.xforms.ui.Upload;
import org.springframework.util.FileCopyUtils;
import org.w3c.dom.*;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.*;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.ls.*;
import org.xml.sax.SAXException;
/**
@@ -72,9 +73,10 @@ public class XFormsBean
private Form form;
private FormProcessor.InstanceData instanceData = null;
private ChibaBean chibaBean;
private final ChibaBean chibaBean = new ChibaBean();
private SchemaFormBuilder schemaFormBuilder = null;
private final LinkedList<XFormsEvent> eventLog = new LinkedList<XFormsEvent>();
private final HashMap<String, String> uploads = new HashMap<String, String>();
private final List<XFormsEvent> eventLog = new LinkedList<XFormsEvent>();
/** @return the form */
public Form getForm()
@@ -105,7 +107,6 @@ public class XFormsBean
{
LOGGER.debug("initializing " + this + " with form " + this.form.getName());
}
this.chibaBean = new ChibaBean();
final FacesContext facesContext = FacesContext.getCurrentInstance();
final ExternalContext externalContext = facesContext.getExternalContext();
final HttpServletRequest request = (HttpServletRequest)
@@ -139,7 +140,7 @@ public class XFormsBean
final Document schemaDocument = this.form.getSchema();
this.rewriteInlineURIs(schemaDocument, cwdAVMPath);
final Document xformsDocument =
this.schemaFormBuilder.buildXForm(instanceData.getContent(),
this.schemaFormBuilder.buildXForm(instanceData.load(),
schemaDocument,
this.form.getSchemaRootElementName());
@@ -290,20 +291,29 @@ public class XFormsBean
* handles submits and sets the instance data.
*/
public void handleAction()
throws Exception
{
LOGGER.debug(this + ".handleAction");
final FacesContext context = FacesContext.getCurrentInstance();
final HttpServletRequest request = (HttpServletRequest)
context.getExternalContext().getRequest();
final FormsService formsService = FormsService.getInstance();
final Document result = formsService.parseXML(request.getInputStream());
this.schemaFormBuilder.removePrototypeNodes(result.getDocumentElement());
this.instanceData.setContent(result);
try
{
final FacesContext context = FacesContext.getCurrentInstance();
final HttpServletRequest request = (HttpServletRequest)
context.getExternalContext().getRequest();
final FormsService formsService = FormsService.getInstance();
final Document result = formsService.parseXML(request.getInputStream());
this.schemaFormBuilder.removePrototypeNodes(result.getDocumentElement());
final ResponseWriter out = context.getResponseWriter();
formsService.writeXML(result, out);
out.close();
final String[] uploadedFilePaths = (String[])
this.uploads.values().toArray(new String[0]);
this.instanceData.save(result, uploadedFilePaths);
final ResponseWriter out = context.getResponseWriter();
formsService.writeXML(result, out);
out.close();
}
catch (Throwable t)
{
LOGGER.error(t);
}
}
/**
@@ -329,6 +339,7 @@ public class XFormsBean
/**
* Provides data for a file picker widget.
*/
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_XML)
public void getFilePickerData()
throws Exception
{
@@ -347,7 +358,10 @@ public class XFormsBean
}
else
{
currentPath = AVMConstants.buildAbsoluteAVMPath(browseBean.getCurrentPath(),
final String previewStorePath =
browseBean.getCurrentPath().replaceFirst(AVMConstants.STORE_MAIN,
AVMConstants.STORE_PREVIEW);
currentPath = AVMConstants.buildAbsoluteAVMPath(previewStorePath,
currentPath);
}
LOGGER.debug(this + ".getFilePickerData(" + currentPath + ")");
@@ -403,6 +417,94 @@ public class XFormsBean
FormsService.getInstance().writeXML(result, out);
out.close();
}
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void uploadFile()
throws Exception
{
LOGGER.debug(this + ".uploadFile()");
final FacesContext facesContext = FacesContext.getCurrentInstance();
final ExternalContext externalContext = facesContext.getExternalContext();
final HttpServletRequest request = (HttpServletRequest)
externalContext.getRequest();
final HttpSession session = (HttpSession)
externalContext.getSession(true);
final AVMBrowseBean browseBean = (AVMBrowseBean)
session.getAttribute("AVMBrowseBean");
final ServletFileUpload upload =
new ServletFileUpload(new DiskFileItemFactory());
upload.setHeaderEncoding("UTF-8");
final List<FileItem> fileItems = upload.parseRequest(request);
final FileUploadBean bean = new FileUploadBean();
String uploadId = null;
String currentPath = null;
String filename = null;
InputStream fileInputStream = null;
for (FileItem item : fileItems)
{
LOGGER.debug("item = " + item);
if (item.isFormField() && item.getFieldName().equals("id"))
{
uploadId = item.getString();
LOGGER.debug("uploadId is " + uploadId);
}
else if (item.isFormField() && item.getFieldName().equals("currentPath"))
{
final String previewStorePath =
browseBean.getCurrentPath().replaceFirst(AVMConstants.STORE_MAIN,
AVMConstants.STORE_PREVIEW);
currentPath = AVMConstants.buildAbsoluteAVMPath(previewStorePath,
item.getString());
LOGGER.debug("currentPath is " + currentPath);
}
else
{
filename = item.getName();
int idx = filename.lastIndexOf('\\');
if (idx == -1)
{
idx = filename.lastIndexOf('/');
}
if (idx != -1)
{
filename = filename.substring(idx + File.separator.length());
}
fileInputStream = item.getInputStream();
LOGGER.debug("parsed file " + filename);
}
}
final ServiceRegistry serviceRegistry =
Repository.getServiceRegistry(facesContext);
final AVMService avmService = serviceRegistry.getAVMService();
LOGGER.debug("saving file " + filename + " to " + currentPath);
FileCopyUtils.copy(fileInputStream,
avmService.createFile(currentPath, filename));
this.uploads.put(uploadId, currentPath + "/" + filename);
LOGGER.debug("upload complete. sending response");
final FormsService formsService = FormsService.getInstance();
final Document result = formsService.newDocument();
final Element htmlEl = result.createElement("html");
result.appendChild(htmlEl);
final Element bodyEl = result.createElement("body");
htmlEl.appendChild(bodyEl);
final Element scriptEl = result.createElement("script");
bodyEl.appendChild(scriptEl);
scriptEl.setAttribute("type", "text/javascript");
final Node scriptText =
result.createTextNode("window.parent.FilePickerWidget." +
"_upload_completeHandler('" + uploadId + "');");
scriptEl.appendChild(scriptText);
final ResponseWriter out = facesContext.getResponseWriter();
formsService.writeXML(result, out);
out.close();
}
private void swapRepeatItems(final XFormsElement from,
final XFormsElement to)