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

Commit

Permalink
Browse files Browse the repository at this point in the history
rhbz870876 allow download of po zip for offline translation for non-p…
…o projects
  • Loading branch information
davidmason committed Mar 12, 2013
1 parent cc57236 commit b7cfba3
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 43 deletions.
Expand Up @@ -51,6 +51,14 @@ public class ConfigurationAction implements Serializable
private ConfigurationService configurationServiceImpl;

public void getData()
{
boolean useOfflinePo = false;
getData(useOfflinePo);
}

// FIXME need another public method to get offlinepo config file

private void getData(boolean useOfflinePo)
{
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setContentType("application/xml");
Expand All @@ -62,7 +70,7 @@ public void getData()
ServletOutputStream os = response.getOutputStream();

os.write(
configurationServiceImpl.getConfigurationFileContents(this.projectSlug, this.iterationSlug).getBytes());
configurationServiceImpl.getConfigurationFileContents(this.projectSlug, this.iterationSlug, useOfflinePo).getBytes());
os.flush();
os.close();
FacesContext.getCurrentInstance().responseComplete();
Expand Down
Expand Up @@ -494,6 +494,12 @@ public void setLocaleId(String localeId)
this.localeId = localeId;
}

public boolean isPoProject()
{
ProjectType type = projectIterationDAO.getBySlug(projectSlug, iterationSlug).getProjectType();
return type == ProjectType.Gettext || type == ProjectType.Podir;
}

public boolean isPoDocument(String docId)
{
return translationFileServiceImpl.isPoDocument(projectSlug, iterationSlug, docId);
Expand Down Expand Up @@ -571,8 +577,7 @@ public boolean isIterationActive()

public boolean isZipFileDownloadAllowed()
{
return getProjectIteration().getProjectType() == ProjectType.Gettext ||
getProjectIteration().getProjectType() == ProjectType.Podir;
return getProjectIteration().getProjectType() != null;
}

public String getZipFileDownloadTitle()
Expand Down
Expand Up @@ -21,9 +21,9 @@
@Scope(ScopeType.CONVERSATION)
public class ProjectIterationZipFileAction implements Serializable
{

private static final long serialVersionUID = 1L;

@In
private ProjectIterationDAO projectIterationDAO;

Expand All @@ -32,42 +32,43 @@ public class ProjectIterationZipFileAction implements Serializable

@In
private ApplicationConfiguration applicationConfiguration;

private String projectSlug;

private String iterationSlug;

private String localeId;

private ProcessHandle zipFilePrepHandle;

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

// Build a background process Handle
IterationZipFileBuildProcessHandle processHandle =
new IterationZipFileBuildProcessHandle();
this.zipFilePrepHandle = processHandle;
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();
}

@End
public void cancelFileDownload()
{
Expand All @@ -76,7 +77,7 @@ public void cancelFileDownload()
this.zipFilePrepHandle.stop();
}
}

public Object getProjectIteration()
{
return this.projectIterationDAO.getBySlug(this.projectSlug, this.iterationSlug);
Expand Down
Expand Up @@ -53,19 +53,19 @@
* @author Carlos Munoz <a href="mailto:camunoz@redhat.com">camunoz@redhat.com</a>
*/
public class IterationZipFileBuildProcess extends RunnableProcess<IterationZipFileBuildProcessHandle>
{
{
private DocumentDAO documentDAO;

private LocaleDAO localeDAO;

private ResourceUtils resourceUtils;

private TextFlowTargetDAO textFlowTargetDAO;

private ProjectIterationDAO projectIterationDAO;

private FileSystemService fileSystemServiceImpl;

private ConfigurationService configurationServiceImpl;

@Override
Expand All @@ -91,9 +91,9 @@ protected void run(IterationZipFileBuildProcessHandle zipHandle) throws Exceptio

final List<HDocument> allIterationDocs = this.documentDAO.getAllByProjectIteration(projectSlug, iterationSlug);
zipHandle.setMaxProgress(allIterationDocs.size() + 1);

zipHandle.ready();

final String projectDirectory = projectSlug + "-" + iterationSlug + "/";
final HLocale hLocale = this.localeDAO.findByLocaleId(new LocaleId(localeId));
final String mappedLocale = hLocale.getLocaleId().getId();
Expand All @@ -103,23 +103,23 @@ protected void run(IterationZipFileBuildProcessHandle zipHandle) throws Exceptio
final FileOutputStream output = new FileOutputStream( downloadFile );
final ZipOutputStream zipOutput = new ZipOutputStream(output);
zipOutput.setMethod(ZipOutputStream.DEFLATED);
final PoWriter2 poWriter = new PoWriter2();
final PoWriter2 poWriter = new PoWriter2(false, zipHandle.isOfflinePo());
final Set<String> extensions = new HashSet<String>();

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

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

// Add the config file at the root of the project directory
String configFilename = projectDirectory + this.configurationServiceImpl.getConfigurationFileName();
zipOutput.putNextEntry(new ZipEntry(configFilename));
zipOutput.write(
this.configurationServiceImpl.getConfigurationFileContents(projectSlug, iterationSlug, zipHandle.getServerPath()).getBytes());
this.configurationServiceImpl.getConfigurationFileContents(projectSlug, iterationSlug, zipHandle.isOfflinePo(), zipHandle.getServerPath()).getBytes());
zipOutput.closeEntry();
zipHandle.incrementProgress(1);

Expand All @@ -134,21 +134,21 @@ protected void run(IterationZipFileBuildProcessHandle zipHandle) throws Exceptio
this.fileSystemServiceImpl.deleteDownloadDescriptorFile(downloadId);
return;
}

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

Resource res = this.resourceUtils.buildResource( document );

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

zipOutput.flush();
zipOutput.close();
}
Expand Down
Expand Up @@ -34,6 +34,7 @@ public class IterationZipFileBuildProcessHandle extends ProcessHandle
private String projectSlug;
private String iterationSlug;
private String localeId;
private boolean offlinePo;
private String initiatingUserName;
private String downloadId;
private Semaphore readySemaphore;
Expand Down Expand Up @@ -82,11 +83,21 @@ public void setLocaleId(String localeId)
this.localeId = localeId;
}

public boolean isOfflinePo()
{
return offlinePo;
}

public void setOfflinePo(boolean offlinePo)
{
this.offlinePo = offlinePo;
}

public String getDownloadId()
{
return downloadId;
}

public void setDownloadId(String downloadId)
{
this.downloadId = downloadId;
Expand Down Expand Up @@ -129,13 +140,13 @@ public void waitUntilReady()
// If interrupted, just ignore
}
}

/**
* Signals that the process is ready.
*/
void ready()
{
this.readySemaphore.release();
}

}
Expand Up @@ -27,22 +27,24 @@ public interface ConfigurationService
*
* @param projectSlug
* @param iterationSlug
* @param useOfflinePo true to use 'offlinepo' instead of the configured project type
* @return The configuration file contents for the given project and
* iteration.
*/
String getConfigurationFileContents(String projectSlug, String iterationSlug);
String getConfigurationFileContents(String projectSlug, String iterationSlug, boolean useOfflinePo);

/**
* Returns the contents of the configuration for a given project. Use this method
* when the server path of the zanata server needs to be customized
*
* @param projectSlug
* @param iterationSlug
* @param useOfflinePo true to use 'offlinepo' instead of the configured project type
* @param serverPath
* @return The configuration file contents for the given project and
* iteration.
*/
String getConfigurationFileContents(String projectSlug, String iterationSlug, String serverPath);
String getConfigurationFileContents(String projectSlug, String iterationSlug, boolean useOfflinePo, String serverPath);

/**
* Returns the default configuration file Name.
Expand Down
Expand Up @@ -43,6 +43,8 @@
public class ConfigurationServiceImpl implements ConfigurationService
{
private static final String FILE_NAME = "zanata.xml";

private static final String PROJECT_TYPE_OFFLINE_PO = "offlinepo";

@In
private LocaleService localeServiceImpl;
Expand All @@ -54,13 +56,13 @@ public class ConfigurationServiceImpl implements ConfigurationService
private ApplicationConfiguration applicationConfiguration;

@Override
public String getConfigurationFileContents(String projectSlug, String iterationSlug)
public String getConfigurationFileContents(String projectSlug, String iterationSlug, boolean useOfflinePo)
{
return getConfigurationFileContents(projectSlug, iterationSlug, applicationConfiguration.getServerPath());
return getConfigurationFileContents(projectSlug, iterationSlug, useOfflinePo, applicationConfiguration.getServerPath());
}

@Override
public String getConfigurationFileContents(String projectSlug, String iterationSlug, String serverPath)
public String getConfigurationFileContents(String projectSlug, String iterationSlug, boolean useOfflinePo, String serverPath)
{
HProjectIteration projectIteration = projectIterationDAO.getBySlug(projectSlug, iterationSlug);
ProjectType projectType = projectIteration.getProjectType();
Expand All @@ -71,16 +73,23 @@ public String getConfigurationFileContents(String projectSlug, String iterationS
var.append(" <url>").append(serverPath).append("/</url>\n");
var.append(" <project>").append(projectSlug).append("</project>\n");
var.append(" <project-version>").append(iterationSlug).append("</project-version>\n");
if ( projectType != null )
if (useOfflinePo)
{
var.append(" <!-- NB project-type set to 'offlinepo' to allow offline po translation\n")
.append(" from non-po documents, project-type on server is '")
.append(String.valueOf(projectType).toLowerCase()).append("' -->\n")
.append(" <project-type>").append(PROJECT_TYPE_OFFLINE_PO).append("</project-type>\n");
}
else if ( projectType != null )
{
if( projectType == ProjectType.Gettext )
{
var.append(" <!-- NB project-type set to 'podir' to allow uploads, but original was 'gettext' -->\n");
var.append(" <project-type>").append(ProjectType.Podir.toString()).append("</project-type>\n");
var.append(" <project-type>").append(ProjectType.Podir.toString().toLowerCase()).append("</project-type>\n");
}
else
{
var.append(" <project-type>").append(projectType).append("</project-type>\n");
var.append(" <project-type>").append(projectType.toString().toLowerCase()).append("</project-type>\n");
}
}
else
Expand Down
2 changes: 2 additions & 0 deletions zanata-war/src/main/resources/messages.properties
Expand Up @@ -354,6 +354,8 @@ jsf.iteration.files.dotpot=.pot
jsf.iteration.files.Download=Download
jsf.iteration.files.DownloadAllFiles=Download All Files (zip)
jsf.iteration.files.DownloadAllFiles.title=Download all translated files.
jsf.iteration.files.DownloadAllFilesOfflinePo=Download All Files (offline po zip)
jsf.iteration.files.DownloadAllFilesOfflinePo.title=Download all translated files in po format for offline translation.
jsf.iteration.files.DownloadAllFiles.ProjectTypeNotAllowed=The project type must be set to 'Gettext' or 'Podir'. Contact the project maintainer.
jsf.iteration.files.DownloadAllFiles.ProjectTypeNotSet=The project type for this iteration has not been set. Contact the project maintainer.
jsf.iteration.files.Filter.title=Filter by document name
Expand Down
13 changes: 12 additions & 1 deletion zanata-war/src/main/webapp/iteration/files.xhtml
Expand Up @@ -341,13 +341,24 @@
</h:outputLink>

<ui:param name="downloadAllAllowed" value="#{projectIterationFilesAction.zipFileDownloadAllowed}" />
<!-- show this when downloads are prohibited, or it is gettext -->
<a4j:commandLink styleClass="action_link #{downloadAllAllowed ? '' : 'disabled'}"
rendered="#{projectIterationFilesAction.poProject or not downloadAllAllowed}"
value="#{messages['jsf.iteration.files.DownloadAllFiles']}"
action="#{projectIterationZipFileAction.prepareIterationZipFile}"
action="#{projectIterationZipFileAction.prepareIterationZipFile(false)}"
onclick="if(!downloadAllFilesClick()){ return false; }"
reRender="downloadProgressBar"
disabled="#{not downloadAllAllowed}"
title="#{projectIterationFilesAction.zipFileDownloadTitle}"/>
<!-- separate download link for 'offline po' bundled package -->
<a4j:commandLink styleClass="action_link #{downloadAllAllowed ? '' : 'disabled'}"
rendered="#{downloadAllAllowed and !projectIterationFilesAction.poProject}"
value="#{messages['jsf.iteration.files.DownloadAllFilesOfflinePo']}"
action="#{projectIterationZipFileAction.prepareIterationZipFile(true)}"
onclick="if(!downloadAllFilesClick()){ return false; }"
reRender="downloadProgressBar"
disabled="#{not downloadAllAllowed}"
title="#{messages['jsf.iteration.files.DownloadAllFilesOfflinePo.title']}"/>
</a4j:form>
</rich:panel>

Expand Down

0 comments on commit b7cfba3

Please sign in to comment.