mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
The Import dialog now allows ZIP file structure import into the repo from the web-client by any user with Write access to a folder - this is nice quick way for any user to import bulk data without using an FTP client or CIFS folder access.
Import action moved to top-level in the main browse screen now it is useful on a day-to-day basis. The 'import' repository action (ImporterActionExecuter) extended to support import of any zip flavour file. More zip flavour filetypes added to mimetype map. Improved debugging output added to BasePathResultsMap for xpaths executed in templates. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5760 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -344,6 +344,12 @@
|
||||
<property name="contentService">
|
||||
<ref bean="ContentService" />
|
||||
</property>
|
||||
<property name="mimetypeService">
|
||||
<ref bean="mimetypeService"/>
|
||||
</property>
|
||||
<property name="fileFolderService">
|
||||
<ref bean="FileFolderService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="export" class="org.alfresco.repo.action.executer.ExporterActionExecuter" parent="action-executer">
|
||||
|
@@ -292,7 +292,10 @@
|
||||
<extension>z</extension>
|
||||
</mimetype>
|
||||
<mimetype mimetype="application/zip" display="ZIP">
|
||||
<extension>zip</extension>
|
||||
<extension display="ZIP" default="true">zip</extension>
|
||||
<extension display="WAR">war</extension>
|
||||
<extension display="JAR">jar</extension>
|
||||
<extension display="EAR">ear</extension>
|
||||
</mimetype>
|
||||
<mimetype mimetype="image/x-dwg" display="AutoCAD Drawing">
|
||||
<extension>dwg</extension>
|
||||
|
@@ -24,9 +24,24 @@
|
||||
*/
|
||||
package org.alfresco.repo.action.executer;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ApplicationModel;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ParameterDefinitionImpl;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
@@ -34,13 +49,21 @@ import org.alfresco.repo.importer.ACPImportPackageHandler;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.model.FileExistsException;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
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.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.view.ImporterService;
|
||||
import org.alfresco.service.cmr.view.Location;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.tools.zip.ZipEntry;
|
||||
import org.apache.tools.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* Importer action executor
|
||||
@@ -53,8 +76,10 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
||||
public static final String PARAM_ENCODING = "encoding";
|
||||
public static final String PARAM_DESTINATION_FOLDER = "destination";
|
||||
|
||||
private static final int BUFFER_SIZE = 16384;
|
||||
private static final String TEMP_FILE_PREFIX = "alf";
|
||||
private static final String TEMP_FILE_SUFFIX = ".acp";
|
||||
private static final String TEMP_FILE_SUFFIX_ACP = ".acp";
|
||||
private static final String TEMP_FILE_SUFFIX_ZIP = ".zip";
|
||||
|
||||
/**
|
||||
* The importer service
|
||||
@@ -71,6 +96,16 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
||||
*/
|
||||
private ContentService contentService;
|
||||
|
||||
/**
|
||||
* The mimetype service
|
||||
*/
|
||||
private MimetypeService mimetypeService;
|
||||
|
||||
/**
|
||||
* The file folder service
|
||||
*/
|
||||
private FileFolderService fileFolderService;
|
||||
|
||||
/**
|
||||
* Sets the ImporterService to use
|
||||
*
|
||||
@@ -101,6 +136,26 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the MimetypeService to use
|
||||
*
|
||||
* @param mimetypeService The MimetypeService
|
||||
*/
|
||||
public void setMimetypeService(MimetypeService mimetypeService)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FileFolderService to use
|
||||
*
|
||||
* @param fileFolderService The FileFolderService
|
||||
*/
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.action.executer.ActionExecuter#execute(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.ref.NodeRef)
|
||||
*/
|
||||
@@ -112,19 +167,20 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
||||
ContentReader reader = this.contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
|
||||
if (reader != null)
|
||||
{
|
||||
NodeRef importDest = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER);
|
||||
if (MimetypeMap.MIMETYPE_ACP.equals(reader.getMimetype()))
|
||||
{
|
||||
// perform an import of an Alfresco ACP file (special format ZIP structure)
|
||||
File zipFile = null;
|
||||
try
|
||||
{
|
||||
// unfortunately a ZIP file can not be read directly from an input stream so we have to create
|
||||
// a temporary file first
|
||||
zipFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
|
||||
zipFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ACP);
|
||||
reader.getContent(zipFile);
|
||||
|
||||
ACPImportPackageHandler importHandler = new ACPImportPackageHandler(zipFile,
|
||||
(String)ruleAction.getParameterValue(PARAM_ENCODING));
|
||||
NodeRef importDest = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER);
|
||||
|
||||
this.importerService.importView(importHandler, new Location(importDest), null, null);
|
||||
}
|
||||
@@ -137,6 +193,104 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MimetypeMap.MIMETYPE_ZIP.equals(reader.getMimetype()))
|
||||
{
|
||||
// perform an import of a standard ZIP file
|
||||
ZipFile zipFile = null;
|
||||
File tempFile = null;
|
||||
try
|
||||
{
|
||||
tempFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ACP);
|
||||
reader.getContent(tempFile);
|
||||
// NOTE: This encoding allows us to workaround bug:
|
||||
// http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
|
||||
zipFile = new ZipFile(tempFile, "Cp437");
|
||||
|
||||
// build a temp dir name based on the ID of the noderef we are importing
|
||||
File alfTempDir = TempFileProvider.getTempDir();
|
||||
File tempDir = new File(alfTempDir.getPath() + File.separatorChar + actionedUponNodeRef.getId());
|
||||
try
|
||||
{
|
||||
// TODO: improve this code to directly pipe the zip stream output into the repo objects -
|
||||
// to remove the need to expand to the filesystem first?
|
||||
extractFile(zipFile, tempDir.getPath());
|
||||
importDirectory(tempDir.getPath(), importDest);
|
||||
}
|
||||
finally
|
||||
{
|
||||
deleteDir(tempDir);
|
||||
}
|
||||
}
|
||||
catch (IOException ioErr)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to import ZIP file.", ioErr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// now the import is done, delete the temporary file
|
||||
if (tempFile != null)
|
||||
{
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively import a directory structure into the specified root node
|
||||
*
|
||||
* @param dir The directory of files and folders to import
|
||||
* @param root The root node to import into
|
||||
*/
|
||||
private void importDirectory(String dir, NodeRef root)
|
||||
{
|
||||
File topdir = new File(dir);
|
||||
for (File file : topdir.listFiles())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (file.isFile())
|
||||
{
|
||||
String fileName = file.getName();
|
||||
|
||||
// create content node based on the file name
|
||||
FileInfo fileInfo = this.fileFolderService.create(root, fileName, ContentModel.TYPE_CONTENT);
|
||||
NodeRef fileRef = fileInfo.getNodeRef();
|
||||
|
||||
// add titled aspect for the read/edit properties screens
|
||||
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
|
||||
titledProps.put(ContentModel.PROP_TITLE, fileName);
|
||||
this.nodeService.addAspect(fileRef, ContentModel.ASPECT_TITLED, titledProps);
|
||||
|
||||
// push the content of the file into the node
|
||||
InputStream contentStream = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);
|
||||
ContentWriter writer = this.contentService.getWriter(fileRef, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype(this.mimetypeService.guessMimetype(fileName));
|
||||
writer.putContent(contentStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a folder based on the folder name
|
||||
FileInfo folderInfo = this.fileFolderService.create(root, file.getName(), ContentModel.TYPE_FOLDER);
|
||||
NodeRef folderRef = folderInfo.getNodeRef();
|
||||
|
||||
// add the uifacets aspect for the read/edit properties screens
|
||||
this.nodeService.addAspect(folderRef, ApplicationModel.ASPECT_UIFACETS, null);
|
||||
|
||||
importDirectory(file.getPath(), folderRef);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
// TODO: add failed file info to status message?
|
||||
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
// TODO: add failed file info to status message?
|
||||
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,4 +306,79 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
||||
true, getParamDisplayLabel(PARAM_ENCODING)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the file and folder structure of a ZIP file into the specified directory
|
||||
*
|
||||
* @param archive The ZIP archive to extract
|
||||
* @param extractDir The directory to extract into
|
||||
*/
|
||||
public static void extractFile(ZipFile archive, String extractDir)
|
||||
{
|
||||
String fileName;
|
||||
String destFileName;
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
extractDir = extractDir + File.separator;
|
||||
try
|
||||
{
|
||||
for (Enumeration e = archive.getEntries(); e.hasMoreElements();)
|
||||
{
|
||||
ZipEntry entry = (ZipEntry) e.nextElement();
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
fileName = entry.getName();
|
||||
fileName = fileName.replace('/', File.separatorChar);
|
||||
destFileName = extractDir + fileName;
|
||||
File destFile = new File(destFileName);
|
||||
String parent = destFile.getParent();
|
||||
if (parent != null)
|
||||
{
|
||||
File parentFile = new File(parent);
|
||||
if (!parentFile.exists()) parentFile.mkdirs();
|
||||
}
|
||||
InputStream in = new BufferedInputStream(archive.getInputStream(entry), BUFFER_SIZE);
|
||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(destFileName), BUFFER_SIZE);
|
||||
int count;
|
||||
while ((count = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
File newdir = new File(extractDir + entry.getName());
|
||||
newdir.mkdir();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ZipException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to process ZIP file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively delete a dir of files and directories
|
||||
*
|
||||
* @param dir directory to delete
|
||||
*/
|
||||
public static void deleteDir(File dir)
|
||||
{
|
||||
File elenco = new File(dir.getPath());
|
||||
for (File file : elenco.listFiles())
|
||||
{
|
||||
if (file.isFile()) file.delete();
|
||||
else deleteDir(file);
|
||||
}
|
||||
dir.delete();
|
||||
}
|
||||
}
|
||||
|
@@ -70,7 +70,18 @@ public abstract class BasePathResultsMap extends BaseTemplateMap
|
||||
if (xpath.length() != 0)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Executing xpath: " + xpath);
|
||||
{
|
||||
String out = "Executing xpath: " + xpath;
|
||||
if (params != null)
|
||||
{
|
||||
out += " with params:";
|
||||
for (QueryParameterDefinition p : params)
|
||||
{
|
||||
out += " " + p.getDefault();
|
||||
}
|
||||
}
|
||||
logger.debug(out);
|
||||
}
|
||||
|
||||
List<NodeRef> nodes = this.services.getSearchService().selectNodes(
|
||||
this.parent.getNodeRef(),
|
||||
|
Reference in New Issue
Block a user