Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
First attempt at migrating the Zip file process to the new Async task…
Browse files Browse the repository at this point in the history
… framework.
  • Loading branch information
carlosmunoz committed Aug 18, 2013
1 parent 8a2eec1 commit b4860c4
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 34 deletions.
@@ -1,5 +1,6 @@
package org.zanata.action;

import java.io.InputStream;
import java.io.Serializable;

import org.jboss.seam.ScopeType;
Expand All @@ -11,11 +12,14 @@
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.security.Identity;
import org.zanata.ApplicationConfiguration;
import org.zanata.async.AsyncHandle;
import org.zanata.async.tasks.ZipFileBuildTask;
import org.zanata.dao.ProjectIterationDAO;
import org.zanata.process.IterationZipFileBuildProcess;
import org.zanata.process.IterationZipFileBuildProcessHandle;
import org.zanata.process.ProcessHandle;
import org.zanata.service.ProcessManagerService;
import org.zanata.service.impl.AsyncTaskManagerServiceImpl;

@Name("projectIterationZipFileAction")
@Scope(ScopeType.CONVERSATION)
Expand All @@ -28,7 +32,7 @@ public class ProjectIterationZipFileAction implements Serializable
private ProjectIterationDAO projectIterationDAO;

@In
ProcessManagerService processManagerServiceImpl;
AsyncTaskManagerServiceImpl asyncTaskManagerServiceImpl;

@In
private ApplicationConfiguration applicationConfiguration;
Expand All @@ -39,43 +43,29 @@ public class ProjectIterationZipFileAction implements Serializable

private String localeId;

private ProcessHandle zipFilePrepHandle;
private AsyncHandle<InputStream> zipFilePrepHandle;

@Begin(join = true)
@Restrict("#{s:hasPermission(projectIterationZipFileAction.projectIteration, 'download-all')}")
public void prepareIterationZipFile(boolean offlinePo)
{
if( this.zipFilePrepHandle != null && this.zipFilePrepHandle.isInProgress() )
if( this.zipFilePrepHandle != null && !this.zipFilePrepHandle.isDone() )
{
// Cancel any other processes
this.zipFilePrepHandle.stop();
// Cancel any other processes for this conversation
this.zipFilePrepHandle.cancel(true);
}

// Build a background process Handle
IterationZipFileBuildProcessHandle processHandle =
new IterationZipFileBuildProcessHandle();
this.zipFilePrepHandle = processHandle;
processHandle.setProjectSlug( this.projectSlug );
processHandle.setIterationSlug( this.iterationSlug );
processHandle.setLocaleId( this.localeId );
processHandle.setOfflinePo(offlinePo);
processHandle.setInitiatingUserName( Identity.instance().getCredentials().getUsername() );
processHandle.setServerPath(applicationConfiguration.getServerPath()); // This needs to be done here as the server
// path may not be available when running
// asynchronously

// Fire the zip file building process and wait until it is ready to return
this.processManagerServiceImpl.startProcess( new IterationZipFileBuildProcess(), processHandle );
processHandle.waitUntilReady();
// Start a zip file task
ZipFileBuildTask task = new ZipFileBuildTask(this.projectSlug, this.iterationSlug, this.localeId,
Identity.instance().getCredentials().getUsername(), offlinePo);

asyncTaskManagerServiceImpl.startTask(task);
}

@End
public void cancelFileDownload()
{
if( this.zipFilePrepHandle.isInProgress() )
{
this.zipFilePrepHandle.stop();
}
this.zipFilePrepHandle.cancel(false);
}

public Object getProjectIteration()
Expand Down Expand Up @@ -113,12 +103,12 @@ public void setLocaleId(String localeId)
this.localeId = localeId;
}

public ProcessHandle getZipFilePrepHandle()
public AsyncHandle<InputStream> getZipFilePrepHandle()
{
return zipFilePrepHandle;
}

public void setZipFilePrepHandle(ProcessHandle zipFilePrepHandle)
public void setZipFilePrepHandle(AsyncHandle<InputStream> zipFilePrepHandle)
{
this.zipFilePrepHandle = zipFilePrepHandle;
}
Expand Down
12 changes: 9 additions & 3 deletions zanata-war/src/main/java/org/zanata/async/AsyncHandle.java
Expand Up @@ -36,13 +36,13 @@
public class AsyncHandle<V> extends AbstractFuture<V>
{
@Getter @Setter
public int maxProgress;
public int maxProgress = 100;

@Getter @Setter
public int minProgress;
public int minProgress = 0;

@Getter @Setter
public int currentProgress;
public int currentProgress = 0;

@Override
protected boolean setException(Throwable throwable)
Expand All @@ -55,4 +55,10 @@ protected boolean set(@Nullable V value)
{
return super.set(value);
}

public int increaseProgress(int increaseBy)
{
currentProgress += increaseBy;
return currentProgress;
}
}
Expand Up @@ -52,7 +52,7 @@ public class TaskExecutor
*
* @param handle The handle to be used for the running process.
*/
public <V, H extends AsyncHandle<V>> AsyncHandle<V> startProcess(AsyncTask<V, H> task)
public <V, H extends AsyncHandle<V>> AsyncHandle<V> startTask(AsyncTask<V, H> task)
{
H handle = task.getHandle();
if( handle == null )
Expand Down
178 changes: 178 additions & 0 deletions zanata-war/src/main/java/org/zanata/async/tasks/ZipFileBuildTask.java
@@ -0,0 +1,178 @@
/*
* Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the
* @author tags. See the copyright.txt file in the distribution for a full
* listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.zanata.async.tasks;

import com.google.common.base.Optional;
import lombok.AllArgsConstructor;
import org.jboss.seam.Component;
import org.zanata.ApplicationConfiguration;
import org.zanata.adapter.po.PoWriter2;
import org.zanata.async.AsyncHandle;
import org.zanata.async.AsyncTask;
import org.zanata.common.LocaleId;
import org.zanata.dao.DocumentDAO;
import org.zanata.dao.LocaleDAO;
import org.zanata.dao.TextFlowTargetDAO;
import org.zanata.model.HDocument;
import org.zanata.model.HLocale;
import org.zanata.model.HTextFlowTarget;
import org.zanata.rest.dto.resource.Resource;
import org.zanata.rest.dto.resource.TranslationsResource;
import org.zanata.rest.service.ResourceUtils;
import org.zanata.service.ConfigurationService;
import org.zanata.service.FileSystemService;
import org.zanata.service.impl.ConfigurationServiceImpl;
import org.zanata.service.impl.FileSystemServiceImpl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
* This is an asynchronous task to build a zip file containing all files for a Project
* Iteration. its expected return value is an input stream with the contents of the Zip file.
* Currently only supports PO files.
*
* @author Carlos Munoz <a href="mailto:camunoz@redhat.com">camunoz@redhat.com</a>
*/
public class ZipFileBuildTask implements AsyncTask<InputStream, AsyncHandle<InputStream>>
{

private final String projectSlug;
private final String iterationSlug;
private final String localeId;
private final String userName;
private final boolean isOfflinePo;

private AsyncHandle<InputStream> handle;

public ZipFileBuildTask(String projectSlug, String iterationSlug, String localeId, String userName, boolean offlinePo)
{
this.projectSlug = projectSlug;
this.iterationSlug = iterationSlug;
this.localeId = localeId;
this.userName = userName;
isOfflinePo = offlinePo;
}

@Override
public AsyncHandle<InputStream> getHandle()
{
if( handle == null )
{
handle = buildHandle();
}
return handle;
}

private AsyncHandle<InputStream> buildHandle()
{
AsyncHandle<InputStream> newHandle = new AsyncHandle<InputStream>();

// Max documents to process
DocumentDAO documentDAO = (DocumentDAO) Component.getInstance(DocumentDAO.class);
final List<HDocument> allIterationDocs = documentDAO.getAllByProjectIteration(projectSlug, iterationSlug);
newHandle.setMaxProgress(allIterationDocs.size() + 1); // all files plus the zanata.xml file

return newHandle;
}

@Override
public InputStream call() throws Exception
{
// Needed Components
DocumentDAO documentDAO = (DocumentDAO) Component.getInstance(DocumentDAO.class);
LocaleDAO localeDAO = (LocaleDAO)Component.getInstance(LocaleDAO.class);
ResourceUtils resourceUtils = (ResourceUtils)Component.getInstance(ResourceUtils.class);
TextFlowTargetDAO textFlowTargetDAO = (TextFlowTargetDAO)Component.getInstance(TextFlowTargetDAO.class);
FileSystemService fileSystemService = (FileSystemService) Component.getInstance(FileSystemServiceImpl.class);
ConfigurationService configurationService = (ConfigurationService)Component.getInstance(ConfigurationServiceImpl.class);
ApplicationConfiguration applicationConfiguration = (ApplicationConfiguration)Component.getInstance(ApplicationConfiguration.class);

final String projectDirectory = projectSlug + "-" + iterationSlug + "/";
final HLocale hLocale = localeDAO.findByLocaleId(new LocaleId(localeId));
final String mappedLocale = hLocale.getLocaleId().getId();
final String localeDirectory = projectDirectory + mappedLocale + "/";

final File downloadFile = fileSystemService.createDownloadStagingFile("zip");
final FileOutputStream output = new FileOutputStream( downloadFile );
final ZipOutputStream zipOutput = new ZipOutputStream(output);
zipOutput.setMethod(ZipOutputStream.DEFLATED);
final PoWriter2 poWriter = new PoWriter2(false, isOfflinePo);
final Set<String> extensions = new HashSet<String>();

extensions.add("gettext");
extensions.add("comment");

// Generate the download descriptor file
String downloadId = fileSystemService.createDownloadDescriptorFile(downloadFile,
projectSlug + "_" + iterationSlug + "_" + localeId + ".zip",
userName);
//zipHandle.setDownloadId(downloadId);

// Add the config file at the root of the project directory
String configFilename = projectDirectory + configurationService.getConfigurationFileName();
zipOutput.putNextEntry(new ZipEntry(configFilename));
zipOutput.write(configurationService.getConfigurationFileContents(
projectSlug, iterationSlug, hLocale, isOfflinePo, applicationConfiguration.getServerPath())
.getBytes());
zipOutput.closeEntry();
getHandle().increaseProgress(1);

final List<HDocument> allIterationDocs = documentDAO.getAllByProjectIteration(projectSlug, iterationSlug);
for (HDocument document : allIterationDocs)
{
// Stop the process if signaled to do so
if (getHandle().isCancelled())
{
zipOutput.close();
downloadFile.delete();
fileSystemService.deleteDownloadDescriptorFile(downloadId);
return null;
}

TranslationsResource translationResource = new TranslationsResource();
List<HTextFlowTarget> hTargets = textFlowTargetDAO.findTranslations(document, hLocale);
resourceUtils.transferToTranslationsResource(
translationResource, document, hLocale, extensions, hTargets, Optional.<String>absent());

Resource res = resourceUtils.buildResource( document );

String filename = localeDirectory + document.getDocId() + ".po";
zipOutput.putNextEntry(new ZipEntry(filename));
poWriter.writePo(zipOutput, "UTF-8", res, translationResource);
zipOutput.closeEntry();

getHandle().increaseProgress(1);
}

zipOutput.flush();
zipOutput.close();

return new FileInputStream(downloadFile);
}
}

0 comments on commit b4860c4

Please sign in to comment.