Merged V2.1 to HEAD

6975: Fix for WCM-883 - ZIP files with non-ascii characters, now gives the user an option for the encoding of the ZIP filenames
   6978: Fixed test for 2.1 bean names.
   6981: Fixes test failure.
   6982: Integrity exception message carries full failure details.
   6983: Added upgrade script for SQL Server.
   6988: Replaced UserTransaction with RetryingTransactionHelper.
   6989: Added org.hibernate.ObjectNotFoundException RetryingTransactionHelper.
   6996: Added updated support for datetime tokens in the lucene index
   7001: FIx for AR-1806
   7015: Added missing post-create index script for QName columns on alf_child_assoc.
   7022: Merged V2.0 to V2.1:
      7013: Fixed primary child node status query


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7371 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-11-13 01:15:58 +00:00
parent 224a6b2fb8
commit 83919a08f1
3 changed files with 102 additions and 70 deletions

View File

@@ -1118,6 +1118,7 @@ task_done_resubmit_all=Task Done & Re-Submit All
title_import_content=Web Project Bulk Import title_import_content=Web Project Bulk Import
import_website_content_title=Bulk Import import_website_content_title=Bulk Import
import_website_content_desc=Use this dialog to import an archive of content into the web project. import_website_content_desc=Use this dialog to import an archive of content into the web project.
import_high_byte_zip_file=ZIP file contains high-byte filename characters such as Japanese, Chinese or Korean.
delete_avm_file_info=To remove this file from the sandbox, click OK. delete_avm_file_info=To remove this file from the sandbox, click OK.
delete_avm_file_confirm=Are you sure you want to remove \"{0}\" from the sandbox? delete_avm_file_confirm=Are you sure you want to remove \"{0}\" from the sandbox?
delete_form_instance_data_confirm=Are you sure you want to remove \"{0}\" and its {1} associated {1,choice,0#renditions|1#rendition|1<renditions} from the sandbox? delete_form_instance_data_confirm=Are you sure you want to remove \"{0}\" and its {1} associated {1,choice,0#renditions|1#rendition|1<renditions} from the sandbox?

View File

@@ -15,11 +15,11 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of * As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing * FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * http://www.alfresco.com/legal/licensing"
*/ */
package org.alfresco.web.bean.wcm; package org.alfresco.web.bean.wcm;
@@ -45,6 +45,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.ImporterActionExecuter; import org.alfresco.repo.action.executer.ImporterActionExecuter;
import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
@@ -62,31 +63,35 @@ import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.FileUploadBean; import org.alfresco.web.bean.FileUploadBean;
import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.zip.ZipFile; import org.apache.tools.zip.ZipFile;
/** /**
* Backing bean for the Import Website Content dialog. * Backing bean for the Import Website Content dialog.
* *
* This dialog manages the upload of a ZIP archive file, which is then unpacked and loaded into * This dialog manages the upload of a ZIP archive file, which is then unpacked and loaded into
* the AVM store with the complete folder and file structure. * the AVM store with the complete folder and file structure.
* *
* @author Kevin Roast * @author Kevin Roast
*/ */
public class ImportWebsiteDialog public class ImportWebsiteDialog
{ {
private static final int BUFFER_SIZE = 16384; private static final int BUFFER_SIZE = 16384;
private static Log logger = LogFactory.getLog(ImportWebsiteDialog.class);
protected File file; protected File file;
protected String fileName; protected String fileName;
protected boolean isFinished = false; protected boolean isFinished = false;
protected boolean highByteZip = false;
protected FileFolderService fileFolderService; protected FileFolderService fileFolderService;
protected ContentService contentService; protected ContentService contentService;
protected AVMBrowseBean avmBrowseBean; protected AVMBrowseBean avmBrowseBean;
protected AVMService avmService; protected AVMService avmService;
protected NodeService nodeService; protected NodeService nodeService;
/** /**
* @param contentService The ContentService to set. * @param contentService The ContentService to set.
*/ */
@@ -102,7 +107,7 @@ public class ImportWebsiteDialog
{ {
this.fileFolderService = fileFolderService; this.fileFolderService = fileFolderService;
} }
/** /**
* @param avmBrowseBean The AVMBrowseBean to set. * @param avmBrowseBean The AVMBrowseBean to set.
*/ */
@@ -118,7 +123,7 @@ public class ImportWebsiteDialog
{ {
this.avmService = avmService; this.avmService = avmService;
} }
/** /**
* @param nodeService The NodeService to set. * @param nodeService The NodeService to set.
*/ */
@@ -142,7 +147,7 @@ public class ImportWebsiteDialog
this.file = fileBean.getFile(); this.file = fileBean.getFile();
this.fileName = fileBean.getFileName(); this.fileName = fileBean.getFileName();
} }
return this.fileName; return this.fileName;
} }
@@ -152,7 +157,7 @@ public class ImportWebsiteDialog
public void setFileName(String fileName) public void setFileName(String fileName)
{ {
this.fileName = fileName; this.fileName = fileName;
// we also need to keep the file upload bean in sync // we also need to keep the file upload bean in sync
FacesContext ctx = FacesContext.getCurrentInstance(); FacesContext ctx = FacesContext.getCurrentInstance();
FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap(). FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
@@ -162,16 +167,32 @@ public class ImportWebsiteDialog
fileBean.setFileName(this.fileName); fileBean.setFileName(this.fileName);
} }
} }
/**
* @return the highByteZip encoding switch
*/
public boolean isHighByteZip()
{
return this.highByteZip;
}
/**
* @param highByteZip the encoding switch for high-byte ZIP filenames to set
*/
public void setHighByteZip(boolean highByteZip)
{
this.highByteZip = highByteZip;
}
public boolean getFinishButtonDisabled() public boolean getFinishButtonDisabled()
{ {
return (this.fileName == null || this.fileName.length() == 0); return (this.fileName == null || this.fileName.length() == 0);
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
// Action event handlers // Action event handlers
/** /**
* Action listener called when the add content dialog is called * Action listener called when the add content dialog is called
*/ */
@@ -180,55 +201,58 @@ public class ImportWebsiteDialog
clearUpload(); clearUpload();
this.fileName = null; this.fileName = null;
} }
/** /**
* Action handler called when the Finish button is pressed * Action handler called when the Finish button is pressed
*/ */
public String finish() public String finish()
{ {
String outcome = null; String outcome = null;
// check the isFinished flag to stop the finish button // check the isFinished flag to stop the finish button
// being pressed multiple times // being pressed multiple times
if (this.isFinished == false) if (this.isFinished == false)
{ {
this.isFinished = true; this.isFinished = true;
UserTransaction tx = null; UserTransaction tx = null;
try try
{ {
FacesContext context = FacesContext.getCurrentInstance(); FacesContext context = FacesContext.getCurrentInstance();
tx = Repository.getUserTransaction(context); RetryingTransactionHelper.RetryingTransactionCallback<String> cb =
tx.begin(); new RetryingTransactionHelper.RetryingTransactionCallback<String>()
{
// get the AVM path that will contain the imported content public String execute()
String rootPath = this.avmBrowseBean.getCurrentPath(); {
// get the AVM path that will contain the imported content
// convert the AVM path to a NodeRef so we can use the NodeService to perform import String rootPath = avmBrowseBean.getCurrentPath();
NodeRef importRef = AVMNodeConverter.ToNodeRef(-1, rootPath);
processZipImport(this.file, importRef); // convert the AVM path to a NodeRef so we can use the NodeService to perform import
NodeRef importRef = AVMNodeConverter.ToNodeRef(-1, rootPath);
// After a bulk import it's a good idea to snapshot the store processZipImport(file, importRef);
this.avmService.createSnapshot(
AVMUtil.getStoreName(rootPath), // After a bulk import it's a good idea to snapshot the store
"Import of file: " + this.fileName, null); avmService.createSnapshot(
AVMUtil.getStoreName(rootPath),
tx.commit(); "Import of file: " + fileName, null);
return rootPath;
}
};
String rootPath = Repository.getRetryingTransactionHelper(context).doInTransaction(cb);
// Reload virtualisation server as required // Reload virtualisation server as required
AVMUtil.updateVServerWebapp(rootPath, true); AVMUtil.updateVServerWebapp(rootPath, true);
UIContextService.getInstance(context).notifyBeans(); UIContextService.getInstance(context).notifyBeans();
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
} }
catch (Throwable e) catch (Throwable e)
{ {
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
Utils.addErrorMessage(MessageFormat.format( Utils.addErrorMessage(MessageFormat.format(
Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC),
e.getMessage()), e); e.getMessage()), e);
} }
finally finally
@@ -237,38 +261,38 @@ public class ImportWebsiteDialog
this.isFinished = false; this.isFinished = false;
} }
} }
return outcome; return outcome;
} }
/** /**
* Action handler called when the user wishes to remove an uploaded file * Action handler called when the user wishes to remove an uploaded file
*/ */
public String removeUploadedFile() public String removeUploadedFile()
{ {
clearUpload(); clearUpload();
// also clear the file name // also clear the file name
this.fileName = null; this.fileName = null;
// refresh the current page // refresh the current page
return null; return null;
} }
/** /**
* Action handler called when the dialog is cancelled * Action handler called when the dialog is cancelled
*/ */
public String cancel() public String cancel()
{ {
clearUpload(); clearUpload();
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
} }
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
// Helper Methods // Helper Methods
/** /**
* Deletes the uploaded file and removes the FileUploadBean from the session * Deletes the uploaded file and removes the FileUploadBean from the session
*/ */
@@ -279,9 +303,9 @@ public class ImportWebsiteDialog
{ {
this.file.delete(); this.file.delete();
} }
this.file = null; this.file = null;
// remove the file upload bean from the session // remove the file upload bean from the session
FacesContext ctx = FacesContext.getCurrentInstance(); FacesContext ctx = FacesContext.getCurrentInstance();
ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME); ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
@@ -289,7 +313,7 @@ public class ImportWebsiteDialog
/** /**
* Process ZIP file for import into an AVM repository store location * Process ZIP file for import into an AVM repository store location
* *
* @param file ZIP format file * @param file ZIP format file
* @param rootRef Root reference of the AVM location to import into * @param rootRef Root reference of the AVM location to import into
*/ */
@@ -299,7 +323,7 @@ public class ImportWebsiteDialog
{ {
// NOTE: This encoding allows us to workaround bug: // NOTE: This encoding allows us to workaround bug:
// http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807 // http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
ZipFile zipFile = new ZipFile(file, "Cp437"); ZipFile zipFile = new ZipFile(file, this.highByteZip ? "Cp437" : null);
File alfTempDir = TempFileProvider.getTempDir(); File alfTempDir = TempFileProvider.getTempDir();
// build a temp dir name based on the name of the file we are importing // build a temp dir name based on the name of the file we are importing
File tempDir = new File(alfTempDir.getPath() + File.separatorChar + file.getName() + "_unpack"); File tempDir = new File(alfTempDir.getPath() + File.separatorChar + file.getName() + "_unpack");
@@ -321,10 +345,10 @@ public class ImportWebsiteDialog
throw new AlfrescoRuntimeException("Unable to process Zip file. File may not be of the expected format.", e); throw new AlfrescoRuntimeException("Unable to process Zip file. File may not be of the expected format.", e);
} }
} }
/** /**
* Recursively import a directory structure into the specified root node * Recursively import a directory structure into the specified root node
* *
* @param dir The directory of files and folders to import * @param dir The directory of files and folders to import
* @param root The root node to import into * @param root The root node to import into
*/ */
@@ -346,12 +370,12 @@ public class ImportWebsiteDialog
List<QName> aspects = new ArrayList<QName>(); List<QName> aspects = new ArrayList<QName>();
aspects.add(ContentModel.ASPECT_TITLED); aspects.add(ContentModel.ASPECT_TITLED);
Map<QName, PropertyValue> properties = new HashMap<QName, PropertyValue>(); Map<QName, PropertyValue> properties = new HashMap<QName, PropertyValue>();
properties.put(ContentModel.PROP_TITLE, properties.put(ContentModel.PROP_TITLE,
new PropertyValue(DataTypeDefinition.TEXT, fileName)); new PropertyValue(DataTypeDefinition.TEXT, fileName));
this.avmService.createFile( this.avmService.createFile(
avmPath, fileName,new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE), avmPath, fileName,new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE),
aspects, properties); aspects, properties);
// TODO: restore this code once performance is acceptable // TODO: restore this code once performance is acceptable
// NodeRef fileRef = AVMNodeConverter.ToNodeRef(-1, filePath); // NodeRef fileRef = AVMNodeConverter.ToNodeRef(-1, filePath);
// see AVMBrowseBean.setAVMNodeDescriptor // see AVMBrowseBean.setAVMNodeDescriptor
@@ -359,19 +383,19 @@ public class ImportWebsiteDialog
// Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f); // Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
// titledProps.put(ContentModel.PROP_TITLE, fileName); // titledProps.put(ContentModel.PROP_TITLE, fileName);
// this.nodeService.addAspect(fileRef, ContentModel.ASPECT_TITLED, titledProps); // this.nodeService.addAspect(fileRef, ContentModel.ASPECT_TITLED, titledProps);
// for now use the avm service directly // for now use the avm service directly
// String filePath = avmPath + '/' + fileName; // String filePath = avmPath + '/' + fileName;
// this.avmService.addAspect(filePath, ContentModel.ASPECT_TITLED); // this.avmService.addAspect(filePath, ContentModel.ASPECT_TITLED);
// this.avmService.setNodeProperty(filePath, ContentModel.PROP_TITLE, // this.avmService.setNodeProperty(filePath, ContentModel.PROP_TITLE,
// new PropertyValue(DataTypeDefinition.TEXT, fileName)); // new PropertyValue(DataTypeDefinition.TEXT, fileName));
// create content node based on the filename // create content node based on the filename
/*FileInfo contentFile = fileFolderService.create(root, fileName, ContentModel.TYPE_AVM_PLAIN_CONTENT); /*FileInfo contentFile = fileFolderService.create(root, fileName, ContentModel.TYPE_AVM_PLAIN_CONTENT);
NodeRef content = contentFile.getNodeRef(); NodeRef content = contentFile.getNodeRef();
InputStream contentStream = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE); InputStream contentStream = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);
ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true); ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);
writer.setMimetype(mimetypeService.guessMimetype(file.getAbsolutePath())); writer.setMimetype(mimetypeService.guessMimetype(file.getAbsolutePath()));
// TODO: what should we set this too? (definitely not Cp437...!) // TODO: what should we set this too? (definitely not Cp437...!)
@@ -381,17 +405,17 @@ public class ImportWebsiteDialog
else else
{ {
//FileInfo fileInfo = fileFolderService.create(root, file.getName(), ContentModel.TYPE_AVM_PLAIN_FOLDER); //FileInfo fileInfo = fileFolderService.create(root, file.getName(), ContentModel.TYPE_AVM_PLAIN_FOLDER);
// Create a directory in the AVM store // Create a directory in the AVM store
String avmPath = AVMNodeConverter.ToAVMVersionPath(root).getSecond(); String avmPath = AVMNodeConverter.ToAVMVersionPath(root).getSecond();
List<QName> aspects = new ArrayList<QName>(); List<QName> aspects = new ArrayList<QName>();
aspects.add(ApplicationModel.ASPECT_UIFACETS); aspects.add(ApplicationModel.ASPECT_UIFACETS);
this.avmService.createDirectory(avmPath, file.getName(), aspects, null); this.avmService.createDirectory(avmPath, file.getName(), aspects, null);
String folderPath = avmPath + '/' + file.getName(); String folderPath = avmPath + '/' + file.getName();
NodeRef folderRef = AVMNodeConverter.ToNodeRef(-1, folderPath); NodeRef folderRef = AVMNodeConverter.ToNodeRef(-1, folderPath);
importDirectory(file.getPath(), folderRef); importDirectory(file.getPath(), folderRef);
// TODO: restore this code once performance is acceptable // TODO: restore this code once performance is acceptable
// see AVMBrowseBean.setAVMNodeDescriptor // see AVMBrowseBean.setAVMNodeDescriptor
// add the uifacets aspect for the read/edit properties screens // add the uifacets aspect for the read/edit properties screens

View File

@@ -177,8 +177,15 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr><td colspan="2" class="paddingRow"></td></tr>
<tr>
<td colspan="2">
<h:selectBooleanCheckbox id="chkHighByte" value="#{ImportWebsiteDialog.highByteZip}" />&nbsp;
<span style="vertical-align:20%"><h:outputText id="msgHighByte" value="#{msg.import_high_byte_zip_file}"/></span>
</td>
</tr>
<tr><td colspan="2" class="paddingRow"></td></tr>
<% } %> <% } %>
</table> </table>
<% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %> <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "white"); %>
</td> </td>