/*
* Copyright (C) 2015 University of Dundee & Open Microscopy Environment.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package omero.gateway.facility;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import omero.RType;
import omero.ServerError;
import omero.api.IQueryPrx;
import omero.api.RawFileStorePrx;
import omero.gateway.Gateway;
import omero.gateway.SecurityContext;
import omero.gateway.exception.DSAccessException;
import omero.gateway.exception.DSOutOfServiceException;
import omero.gateway.model.ImageData;
import omero.model.Fileset;
import omero.model.FilesetEntry;
import omero.model.OriginalFile;
import omero.sys.ParametersI;
import org.apache.commons.collections.CollectionUtils;
/**
* Encapsulates some functionality needed by the {@link TransferFacility}
*
* @author Dominik Lindner <a
* href="mailto:d.lindner@dundee.ac.uk">d.lindner@dundee.ac.uk</a>
*/
public class TransferFacilityHelper {
/** Maximum size of bytes read at once. */
private static final int INC = 262144;//
private BrowseFacility browse;
private Gateway gateway;
/**
* Creates a new instance.
*
* @param gateway
* Reference to the gateway.
* @param datamanager
* Reference to the manager facility.
* @param parent
* Reference to the parent.
* @throws ExecutionException
*/
TransferFacilityHelper(Gateway gateway) throws ExecutionException {
this.gateway = gateway;
this.browse = gateway.getFacility(BrowseFacility.class);
}
/**
* Downloads the original file of an image from the server.
*
* @param context
* The security context.
* @param targetPath
* Path to the file.
* @param imageId
* The identifier of the image.
* @return See above
* @throws DSOutOfServiceException
* @throws DSAccessException
*/
List<File> downloadImage(SecurityContext context, String targetPath,
long imageId) throws DSAccessException, DSOutOfServiceException {
List<File> files = new ArrayList<File>();
ImageData image = browse.findObject(context, ImageData.class, imageId,
true);
String query;
List<?> filesets;
try {
IQueryPrx service = gateway.getQueryService(context);
ParametersI param = new ParametersI();
long id;
if (image.isFSImage()) {
id = image.getId();
List<RType> l = new ArrayList<RType>();
l.add(omero.rtypes.rlong(id));
param.add("imageIds", omero.rtypes.rlist(l));
query = createFileSetQuery();
} else {// Prior to FS
if (image.isArchived()) {
StringBuffer buffer = new StringBuffer();
id = image.getDefaultPixels().getId();
buffer.append("select ofile from OriginalFile as ofile ");
buffer.append("join fetch ofile.hasher ");
buffer.append("left join ofile.pixelsFileMaps as pfm ");
buffer.append("left join pfm.child as child ");
buffer.append("where child.id = :id");
param.map.put("id", omero.rtypes.rlong(id));
query = buffer.toString();
} else
return null;
}
filesets = service.findAllByQuery(query, param);
} catch (Exception e) {
throw new DSAccessException("Cannot retrieve original file", e);
}
if (CollectionUtils.isEmpty(filesets))
return files;
Iterator<?> i;
List<OriginalFile> values = new ArrayList<OriginalFile>();
if (image.isFSImage()) {
i = filesets.iterator();
Fileset set;
List<FilesetEntry> entries;
Iterator<FilesetEntry> j;
while (i.hasNext()) {
set = (Fileset) i.next();
entries = set.copyUsedFiles();
j = entries.iterator();
while (j.hasNext()) {
FilesetEntry fs = j.next();
values.add(fs.getOriginalFile());
}
}
} else
values.addAll((List<OriginalFile>) filesets);
RawFileStorePrx store = null;
OriginalFile of;
long size;
FileOutputStream stream = null;
long offset = 0;
i = values.iterator();
File f = null;
while (i.hasNext()) {
of = (OriginalFile) i.next();
try {
store = gateway.getRawFileService(context);
store.setFileId(of.getId().getValue());
f = new File(targetPath, of.getName().getValue());
files.add(f);
stream = new FileOutputStream(f);
size = of.getSize().getValue();
try {
try {
for (offset = 0; (offset + INC) < size;) {
stream.write(store.read(offset, INC));
offset += INC;
}
} finally {
stream.write(store.read(offset, (int) (size - offset)));
stream.close();
}
} catch (Exception e) {
if (stream != null)
stream.close();
if (f != null) {
f.delete();
files.remove(f);
}
}
} catch (IOException e) {
if (f != null) {
f.delete();
files.remove(f);
}
throw new DSAccessException("Cannot create file in folderPath",
e);
} catch (Throwable t) {
throw new DSAccessException("ServerError on retrieveArchived",
t);
} finally {
try {
store.close();
} catch (ServerError e) {
}
}
}
return files;
}
/**
* Creates the query to load the file set corresponding to a given image.
*
* @return See above.
*/
private String createFileSetQuery() {
StringBuffer buffer = new StringBuffer();
buffer.append("select fs from Fileset as fs ");
buffer.append("join fetch fs.images as image ");
buffer.append("left outer join fetch fs.usedFiles as usedFile ");
buffer.append("join fetch usedFile.originalFile as f ");
buffer.append("join fetch f.hasher ");
buffer.append("where image.id in (:imageIds)");
return buffer.toString();
}
}