mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
951
source/java/org/alfresco/web/bean/CheckinCheckoutBean.java
Normal file
951
source/java/org/alfresco/web/bean/CheckinCheckoutBean.java
Normal file
@@ -0,0 +1,951 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.bean;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.ActionEvent;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.version.VersionModel;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionType;
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.alfresco.web.app.context.UIContextService;
|
||||
import org.alfresco.web.app.servlet.DownloadContentServlet;
|
||||
import org.alfresco.web.bean.repository.Node;
|
||||
import org.alfresco.web.bean.repository.Repository;
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.ui.common.component.UIActionLink;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class CheckinCheckoutBean
|
||||
{
|
||||
// ------------------------------------------------------------------------------
|
||||
// Bean property getters and setters
|
||||
|
||||
/**
|
||||
* @return Returns the BrowseBean.
|
||||
*/
|
||||
public BrowseBean getBrowseBean()
|
||||
{
|
||||
return this.browseBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param browseBean The BrowseBean to set.
|
||||
*/
|
||||
public void setBrowseBean(BrowseBean browseBean)
|
||||
{
|
||||
this.browseBean = browseBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the NodeService.
|
||||
*/
|
||||
public NodeService getNodeService()
|
||||
{
|
||||
return this.nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService The NodeService to set.
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the VersionOperationsService.
|
||||
*/
|
||||
public CheckOutCheckInService getVersionOperationsService()
|
||||
{
|
||||
return this.versionOperationsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param versionOperationsService The VersionOperationsService to set.
|
||||
*/
|
||||
public void setVersionOperationsService(CheckOutCheckInService versionOperationsService)
|
||||
{
|
||||
this.versionOperationsService = versionOperationsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the ContentService.
|
||||
*/
|
||||
public ContentService getContentService()
|
||||
{
|
||||
return this.contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentService The ContentService to set.
|
||||
*/
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The document node being used for the current operation
|
||||
*/
|
||||
public Node getDocument()
|
||||
{
|
||||
return this.document;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param document The document node to be used for the current operation
|
||||
*/
|
||||
public void setDocument(Node document)
|
||||
{
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the working copy Document.
|
||||
*/
|
||||
public Node getWorkingDocument()
|
||||
{
|
||||
return this.workingDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param workingDocument The working copy Document to set.
|
||||
*/
|
||||
public void setWorkingDocument(Node workingDocument)
|
||||
{
|
||||
this.workingDocument = workingDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the document being checked in has
|
||||
* the versionable aspect applied
|
||||
*
|
||||
* @return true if the versionable aspect is applied
|
||||
*/
|
||||
public boolean isVersionable()
|
||||
{
|
||||
return getDocument().hasAspect(ContentModel.ASPECT_VERSIONABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keepCheckedOut The keepCheckedOut to set.
|
||||
*/
|
||||
public void setKeepCheckedOut(boolean keepCheckedOut)
|
||||
{
|
||||
this.keepCheckedOut = keepCheckedOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the keepCheckedOut.
|
||||
*/
|
||||
public boolean getKeepCheckedOut()
|
||||
{
|
||||
return this.keepCheckedOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param minorChange The minorChange to set.
|
||||
*/
|
||||
public void setMinorChange(boolean minorChange)
|
||||
{
|
||||
this.minorChange = minorChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the minorChange flag.
|
||||
*/
|
||||
public boolean getMinorChange()
|
||||
{
|
||||
return this.minorChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the version history notes.
|
||||
*/
|
||||
public String getVersionNotes()
|
||||
{
|
||||
return this.versionNotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param versionNotes The version history notes to set.
|
||||
*/
|
||||
public void setVersionNotes(String versionNotes)
|
||||
{
|
||||
this.versionNotes = versionNotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the selected Space Id.
|
||||
*/
|
||||
public NodeRef getSelectedSpaceId()
|
||||
{
|
||||
return this.selectedSpaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selectedSpaceId The selected Space Id to set.
|
||||
*/
|
||||
public void setSelectedSpaceId(NodeRef selectedSpaceId)
|
||||
{
|
||||
this.selectedSpaceId = selectedSpaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the copy location. Either the current or other space.
|
||||
*/
|
||||
public String getCopyLocation()
|
||||
{
|
||||
if (this.fileName != null)
|
||||
{
|
||||
return CheckinCheckoutBean.COPYLOCATION_OTHER;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.copyLocation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param copyLocation The copy location. Either the current or other space.
|
||||
*/
|
||||
public void setCopyLocation(String copyLocation)
|
||||
{
|
||||
this.copyLocation = copyLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the message to display when a file has been uploaded
|
||||
*/
|
||||
public String getFileUploadSuccessMsg()
|
||||
{
|
||||
String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success");
|
||||
return MessageFormat.format(msg, new Object[] {getFileName()});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name of the file
|
||||
*/
|
||||
public String getFileName()
|
||||
{
|
||||
// try and retrieve the file and filename from the file upload bean
|
||||
// representing the file we previously uploaded.
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
|
||||
get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
|
||||
if (fileBean != null)
|
||||
{
|
||||
this.file = fileBean.getFile();
|
||||
this.fileName = fileBean.getFileName();
|
||||
}
|
||||
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fileName The name of the file
|
||||
*/
|
||||
public void setFileName(String fileName)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
|
||||
// we also need to keep the file upload bean in sync
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
|
||||
get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
|
||||
if (fileBean != null)
|
||||
{
|
||||
fileBean.setFileName(this.fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the document content used for HTML in-line editing.
|
||||
*/
|
||||
public String getDocumentContent()
|
||||
{
|
||||
return this.documentContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param documentContent The document content for HTML in-line editing.
|
||||
*/
|
||||
public void setDocumentContent(String documentContent)
|
||||
{
|
||||
this.documentContent = documentContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns output from the in-line editor page.
|
||||
*/
|
||||
public String getEditorOutput()
|
||||
{
|
||||
return this.editorOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param editorOutput The output from the in-line editor page
|
||||
*/
|
||||
public void setEditorOutput(String editorOutput)
|
||||
{
|
||||
this.editorOutput = editorOutput;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Navigation action event handlers
|
||||
|
||||
/**
|
||||
* Action event called by all actions that need to setup a Content Document context on the
|
||||
* CheckinCheckoutBean before an action page/wizard is called. The context will be a Node in
|
||||
* setDocument() which can be retrieved on action pages via getDocument().
|
||||
*
|
||||
* @param event ActionEvent
|
||||
*/
|
||||
public void setupContentAction(ActionEvent event)
|
||||
{
|
||||
UIActionLink link = (UIActionLink)event.getComponent();
|
||||
Map<String, String> params = link.getParameterMap();
|
||||
String id = params.get("id");
|
||||
if (id != null && id.length() != 0)
|
||||
{
|
||||
setupContentDocument(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
setDocument(null);
|
||||
}
|
||||
|
||||
clearUpload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a content document node context
|
||||
*
|
||||
* @param id GUID of the node to setup as the content document context
|
||||
*
|
||||
* @return The Node
|
||||
*/
|
||||
private Node setupContentDocument(String id)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Setup for action, setting current document to: " + id);
|
||||
|
||||
Node node = null;
|
||||
|
||||
try
|
||||
{
|
||||
// create the node ref, then our node representation
|
||||
NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
|
||||
node = new Node(ref);
|
||||
|
||||
// create content URL to the content download servlet with ID and expected filename
|
||||
// the myfile part will be ignored by the servlet but gives the browser a hint
|
||||
String url = DownloadContentServlet.generateDownloadURL(ref, node.getName());
|
||||
node.getProperties().put("url", url);
|
||||
node.getProperties().put("workingCopy", node.hasAspect(ContentModel.ASPECT_WORKING_COPY));
|
||||
node.getProperties().put("fileType32", Utils.getFileTypeImage(node.getName(), false));
|
||||
|
||||
// remember the document
|
||||
setDocument(node);
|
||||
|
||||
// refresh the UI, calling this method now is fine as it basically makes sure certain
|
||||
// beans clear the state - so when we finish here other beans will have been reset
|
||||
UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
|
||||
}
|
||||
catch (InvalidNodeRefException refErr)
|
||||
{
|
||||
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action called upon completion of the Check Out file page
|
||||
*/
|
||||
public String checkoutFile()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
UserTransaction tx = null;
|
||||
|
||||
Node node = getDocument();
|
||||
if (node != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
|
||||
tx.begin();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Trying to checkout content node Id: " + node.getId());
|
||||
|
||||
// checkout the node content to create a working copy
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Checkout copy location: " + getCopyLocation());
|
||||
logger.debug("Selected Space Id: " + this.selectedSpaceId);
|
||||
}
|
||||
NodeRef workingCopyRef;
|
||||
if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null)
|
||||
{
|
||||
// checkout to a arbituary parent Space
|
||||
NodeRef destRef = this.selectedSpaceId;
|
||||
|
||||
ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(destRef);
|
||||
workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef(),
|
||||
destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName());
|
||||
}
|
||||
else
|
||||
{
|
||||
workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef());
|
||||
}
|
||||
|
||||
// set the working copy Node instance
|
||||
Node workingCopy = new Node(workingCopyRef);
|
||||
setWorkingDocument(workingCopy);
|
||||
|
||||
// create content URL to the content download servlet with ID and expected filename
|
||||
// the myfile part will be ignored by the servlet but gives the browser a hint
|
||||
String url = DownloadContentServlet.generateDownloadURL(workingCopyRef, workingCopy.getName());
|
||||
|
||||
workingCopy.getProperties().put("url", url);
|
||||
workingCopy.getProperties().put("fileType32", Utils.getFileTypeImage(workingCopy.getName(), false));
|
||||
|
||||
// commit the transaction
|
||||
tx.commit();
|
||||
|
||||
// show the page that display the checkout link
|
||||
outcome = "checkoutFileLink";
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
Utils.addErrorMessage(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), MSG_ERROR_CHECKOUT) + err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: checkoutFile called without a current Document!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action called upon completion of the Check Out file Link download page
|
||||
*/
|
||||
public String checkoutFileOK()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
Node node = getWorkingDocument();
|
||||
if (node != null)
|
||||
{
|
||||
// clean up and clear action context
|
||||
clearUpload();
|
||||
setDocument(null);
|
||||
setWorkingDocument(null);
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action called upon completion of the Edit File download page
|
||||
*/
|
||||
public String editFileOK()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
Node node = getDocument();
|
||||
if (node != null)
|
||||
{
|
||||
// clean up and clear action context
|
||||
clearUpload();
|
||||
setDocument(null);
|
||||
setWorkingDocument(null);
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: editFileOK called without a current Document!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action handler called to calculate which editing screen to display based on the mimetype
|
||||
* of a document. If appropriate, the in-line editing screen will be shown.
|
||||
*/
|
||||
public void editFile(ActionEvent event)
|
||||
{
|
||||
UIActionLink link = (UIActionLink)event.getComponent();
|
||||
Map<String, String> params = link.getParameterMap();
|
||||
String id = params.get("id");
|
||||
if (id != null && id.length() != 0)
|
||||
{
|
||||
Node node = setupContentDocument(id);
|
||||
|
||||
// detect the inline editing aspect to see which edit mode to use
|
||||
if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) &&
|
||||
node.getProperties().get(ContentModel.PROP_EDITINLINE) != null &&
|
||||
((Boolean)node.getProperties().get(ContentModel.PROP_EDITINLINE)).booleanValue() == true)
|
||||
{
|
||||
// retrieve the content reader for this node
|
||||
ContentReader reader = getContentService().getReader(node.getNodeRef(), ContentModel.PROP_CONTENT);
|
||||
String mimetype = reader.getMimetype();
|
||||
|
||||
// calculate which editor screen to display
|
||||
if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(mimetype) ||
|
||||
MimetypeMap.MIMETYPE_XML.equals(mimetype) ||
|
||||
MimetypeMap.MIMETYPE_TEXT_CSS.equals(mimetype))
|
||||
{
|
||||
// make content available to the editing screen
|
||||
if (reader != null)
|
||||
{
|
||||
setEditorOutput(reader.getContentString());
|
||||
}
|
||||
else
|
||||
{
|
||||
setEditorOutput("");
|
||||
}
|
||||
|
||||
// navigate to appropriate screen
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editTextInline");
|
||||
}
|
||||
else
|
||||
{
|
||||
// make content available to the editing screen
|
||||
if (reader != null)
|
||||
{
|
||||
setDocumentContent(reader.getContentString());
|
||||
}
|
||||
else
|
||||
{
|
||||
setDocumentContent("");
|
||||
}
|
||||
setEditorOutput(null);
|
||||
|
||||
// navigate to appropriate screen
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editHtmlInline");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal downloadable document
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editFile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action handler called to set the content of a node from an inline editing page.
|
||||
*/
|
||||
public String editInlineOK()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
UserTransaction tx = null;
|
||||
|
||||
Node node = getDocument();
|
||||
if (node != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
|
||||
tx.begin();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Trying to update content node Id: " + node.getId());
|
||||
|
||||
// get an updating writer that we can use to modify the content on the current node
|
||||
ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
|
||||
writer.putContent(this.editorOutput);
|
||||
|
||||
// commit the transaction
|
||||
tx.commit();
|
||||
|
||||
// clean up and clear action context
|
||||
clearUpload();
|
||||
setDocument(null);
|
||||
setDocumentContent(null);
|
||||
setEditorOutput(null);
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
Utils.addErrorMessage(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: editInlineOK called without a current Document!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to undo the checkout of a document just checked out from the checkout screen.
|
||||
*/
|
||||
public String undoCheckout()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
Node node = getWorkingDocument();
|
||||
if (node != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// try to cancel checkout of the working copy
|
||||
this.versionOperationsService.cancelCheckout(node.getNodeRef());
|
||||
|
||||
clearUpload();
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
Utils.addErrorMessage(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to undo the checkout of a locked document. This document may either by the original copy
|
||||
* or the working copy node. Therefore calculate which it is, if the working copy is found then
|
||||
* we simply cancel checkout on that document. If the original copy is found then we need to find
|
||||
* the appropriate working copy and perform the action on that node.
|
||||
*/
|
||||
public String undoCheckoutFile()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
Node node = getDocument();
|
||||
if (node != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
|
||||
{
|
||||
this.versionOperationsService.cancelCheckout(node.getNodeRef());
|
||||
}
|
||||
else if (node.hasAspect(ContentModel.ASPECT_LOCKABLE))
|
||||
{
|
||||
// TODO: find the working copy for this document and cancel the checkout on it
|
||||
// is this possible? as currently only the workingcopy aspect has the copyReference
|
||||
// attribute - this means we cannot find out where the copy is to cancel it!
|
||||
// can we construct an XPath node lookup?
|
||||
throw new RuntimeException("NOT IMPLEMENTED");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!");
|
||||
}
|
||||
|
||||
clearUpload();
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
Utils.addErrorMessage(MSG_ERROR_CANCELCHECKOUT + err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action called upon completion of the Check In file page
|
||||
*/
|
||||
public String checkinFileOK()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
UserTransaction tx = null;
|
||||
|
||||
// NOTE: for checkin the document node _is_ the working document!
|
||||
Node node = getDocument();
|
||||
if (node != null && (getCopyLocation().equals(COPYLOCATION_CURRENT) || this.getFileName() != null))
|
||||
{
|
||||
try
|
||||
{
|
||||
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
|
||||
tx.begin();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Trying to checkin content node Id: " + node.getId());
|
||||
|
||||
// we can either checkin the content from the current working copy node
|
||||
// which would have been previously updated by the user
|
||||
String contentUrl;
|
||||
String mimetype;
|
||||
if (getCopyLocation().equals(COPYLOCATION_CURRENT))
|
||||
{
|
||||
ContentData contentData = (ContentData) node.getProperties().get(ContentModel.PROP_CONTENT);
|
||||
contentUrl = (contentData == null ? null : contentData.getContentUrl());
|
||||
}
|
||||
// or specify a specific file as the content instead
|
||||
else
|
||||
{
|
||||
// add the content to an anonymous but permanent writer location
|
||||
// we can then retrieve the URL to the content to to be set on the node during checkin
|
||||
ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, false);
|
||||
// TODO: Adjust the mimetype
|
||||
writer.putContent(this.file);
|
||||
contentUrl = writer.getContentUrl();
|
||||
}
|
||||
|
||||
if (contentUrl == null || contentUrl.length() == 0)
|
||||
{
|
||||
throw new IllegalStateException("Content URL is empty for specified working copy content node!");
|
||||
}
|
||||
|
||||
// add version history text to props
|
||||
Map<String, Serializable> props = new HashMap<String, Serializable>(1, 1.0f);
|
||||
props.put(Version.PROP_DESCRIPTION, this.versionNotes);
|
||||
// set the flag for minor or major change
|
||||
if (this.minorChange)
|
||||
{
|
||||
props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
|
||||
}
|
||||
|
||||
NodeRef originalDoc = this.versionOperationsService.checkin(
|
||||
node.getNodeRef(),
|
||||
props,
|
||||
contentUrl,
|
||||
this.keepCheckedOut);
|
||||
|
||||
// commit the transaction
|
||||
tx.commit();
|
||||
|
||||
// clear action context
|
||||
setDocument(null);
|
||||
clearUpload();
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
Utils.addErrorMessage(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), MSG_ERROR_CHECKIN) + err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: checkinFileOK called without a current Document!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action called upon completion of the Update File page
|
||||
*/
|
||||
public String updateFileOK()
|
||||
{
|
||||
String outcome = null;
|
||||
|
||||
UserTransaction tx = null;
|
||||
|
||||
// NOTE: for update the document node _is_ the working document!
|
||||
Node node = getDocument();
|
||||
if (node != null && this.getFileName() != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
|
||||
tx.begin();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Trying to update content node Id: " + node.getId());
|
||||
|
||||
// get an updating writer that we can use to modify the content on the current node
|
||||
ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
|
||||
writer.putContent(this.file);
|
||||
|
||||
// commit the transaction
|
||||
tx.commit();
|
||||
|
||||
// clear action context
|
||||
setDocument(null);
|
||||
clearUpload();
|
||||
|
||||
outcome = "browse";
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
Utils.addErrorMessage(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("WARNING: updateFileOK called without a current Document!");
|
||||
}
|
||||
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deals with the cancel button being pressed on the check in file page
|
||||
*/
|
||||
public String cancel()
|
||||
{
|
||||
// reset the state
|
||||
clearUpload();
|
||||
|
||||
return "browse";
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear form state and upload file bean
|
||||
*/
|
||||
private void clearUpload()
|
||||
{
|
||||
// delete the temporary file we uploaded earlier
|
||||
if (this.file != null)
|
||||
{
|
||||
this.file.delete();
|
||||
}
|
||||
|
||||
this.file = null;
|
||||
this.fileName = null;
|
||||
this.keepCheckedOut = false;
|
||||
this.minorChange = true;
|
||||
this.copyLocation = COPYLOCATION_CURRENT;
|
||||
this.versionNotes = "";
|
||||
this.selectedSpaceId = null;
|
||||
|
||||
// remove the file upload bean from the session
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Private data
|
||||
|
||||
private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class);
|
||||
|
||||
/** I18N messages */
|
||||
private static final String MSG_ERROR_CHECKIN = "error_checkin";
|
||||
private static final String MSG_ERROR_CANCELCHECKOUT = "error_cancel_checkout";
|
||||
private static final String MSG_ERROR_UPDATE = "error_update";
|
||||
private static final String MSG_ERROR_CHECKOUT = "error_checkout";
|
||||
|
||||
/** constants for copy location selection */
|
||||
private static final String COPYLOCATION_CURRENT = "current";
|
||||
private static final String COPYLOCATION_OTHER = "other";
|
||||
|
||||
/** The current document */
|
||||
private Node document;
|
||||
|
||||
/** The working copy of the document we are checking out */
|
||||
private Node workingDocument;
|
||||
|
||||
/** Content of the document used for HTML in-line editing */
|
||||
private String documentContent;
|
||||
|
||||
/** Content of the document returned from in-line editing */
|
||||
private String editorOutput;
|
||||
|
||||
/** transient form and upload properties */
|
||||
private File file;
|
||||
private String fileName;
|
||||
private boolean keepCheckedOut = false;
|
||||
private boolean minorChange = true;
|
||||
private String copyLocation = COPYLOCATION_CURRENT;
|
||||
private String versionNotes = "";
|
||||
private NodeRef selectedSpaceId = null;
|
||||
|
||||
/** The BrowseBean to be used by the bean */
|
||||
private BrowseBean browseBean;
|
||||
|
||||
/** The NodeService to be used by the bean */
|
||||
private NodeService nodeService;
|
||||
|
||||
/** The VersionOperationsService to be used by the bean */
|
||||
private CheckOutCheckInService versionOperationsService;
|
||||
|
||||
/** The ContentService to be used by the bean */
|
||||
private ContentService contentService;
|
||||
}
|
Reference in New Issue
Block a user