org.bimserver.servlets.DownloadServlet Maven / Gradle / Ivy
package org.bimserver.servlets;
/******************************************************************************
* Copyright (C) 2009-2016 BIMserver.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see {@literal }.
*****************************************************************************/
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.activation.DataSource;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.bimserver.BimServer;
import org.bimserver.BimserverDatabaseException;
import org.bimserver.interfaces.objects.SCompareType;
import org.bimserver.interfaces.objects.SDownloadResult;
import org.bimserver.interfaces.objects.SExtendedData;
import org.bimserver.interfaces.objects.SFile;
import org.bimserver.interfaces.objects.SProject;
import org.bimserver.interfaces.objects.SSerializerPluginConfiguration;
import org.bimserver.models.log.AccessMethod;
import org.bimserver.models.store.ActionState;
import org.bimserver.models.store.LongActionState;
import org.bimserver.models.store.StoreFactory;
import org.bimserver.notifications.ProgressTopic;
import org.bimserver.plugins.PluginConfiguration;
import org.bimserver.plugins.serializers.ExtendedDataSource;
import org.bimserver.plugins.serializers.ProgressReporter;
import org.bimserver.plugins.serializers.SerializerException;
import org.bimserver.plugins.serializers.SerializerPlugin;
import org.bimserver.shared.exceptions.ServerException;
import org.bimserver.shared.exceptions.ServiceException;
import org.bimserver.shared.exceptions.UserException;
import org.bimserver.webservices.ServiceMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Charsets;
public class DownloadServlet extends SubServlet {
private static final Logger LOGGER = LoggerFactory.getLogger(DownloadServlet.class);
public DownloadServlet(BimServer bimServer, ServletContext servletContext) {
super(bimServer, servletContext);
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String acceptEncoding = request.getHeader("Accept-Encoding");
boolean useGzip = false;
if (acceptEncoding != null && acceptEncoding.contains("gzip")) {
useGzip = true;
}
OutputStream outputStream = response.getOutputStream();
boolean zip = request.getParameter("zip") != null && request.getParameter("zip").equals("on");
if (useGzip && !zip) {
response.setHeader("Content-Encoding", "gzip");
outputStream = new GZIPOutputStream(response.getOutputStream());
}
String token = (String) request.getSession().getAttribute("token");
if (token == null) {
token = request.getParameter("token");
}
long topicId = -1;
if (request.getParameter("topicId") != null) {
topicId = Long.parseLong(request.getParameter("topicId"));
}
ServiceMap serviceMap = getBimServer().getServiceFactory().get(token, AccessMethod.INTERNAL);
String action = request.getParameter("action");
if (action != null) {
if (action.equals("extendeddata")) {
SExtendedData sExtendedData = serviceMap.getBimsie1ServiceInterface().getExtendedData(Long.parseLong(request.getParameter("edid")));
SFile file = serviceMap.getServiceInterface().getFile(sExtendedData.getFileId());
if (file.getMime() != null) {
response.setContentType(file.getMime());
}
if (file.getFilename() != null) {
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getFilename() + "\"");
}
outputStream.write(file.getData());
if (outputStream instanceof GZIPOutputStream) {
((GZIPOutputStream) outputStream).finish();
}
outputStream.flush();
return;
} else if (action.equals("getfile")) {
String type = request.getParameter("type");
if (type.equals("proto")) {
try {
String protocolBuffersFile = serviceMap.getAdminInterface().getProtocolBuffersFile(request.getParameter("name"));
outputStream.write(protocolBuffersFile.getBytes(Charsets.UTF_8));
outputStream.flush();
} catch (ServiceException e) {
LOGGER.error("", e);
}
} else if (type.equals("serverlog")) {
try {
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
writer.write(serviceMap.getAdminInterface().getServerLog());
writer.flush();
} catch (ServerException e) {
LOGGER.error("", e);
} catch (UserException e) {
LOGGER.error("", e);
}
}
}
} else {
SSerializerPluginConfiguration serializer = null;
if (request.getParameter("serializerOid") != null) {
long serializerOid = Long.parseLong(request.getParameter("serializerOid"));
serializer = serviceMap.getBimsie1ServiceInterface().getSerializerById(serializerOid);
} else {
serializer = serviceMap.getBimsie1ServiceInterface().getSerializerByName(request.getParameter("serializerName"));
}
if (request.getParameter("multiple") != null) {
Set roids = new HashSet();
for (Object key : request.getParameterMap().keySet()) {
String keyString = (String) key;
if (keyString.startsWith("download_")) {
if (!request.getParameter(keyString).equals("[off]")) {
roids.add(Long.parseLong(request.getParameter(keyString)));
}
}
}
topicId = serviceMap.getBimsie1ServiceInterface().downloadRevisions(roids, serializer.getOid(), true);
} else if (request.getParameter("compare") != null) {
SCompareType sCompareType = SCompareType.valueOf(request.getParameter("type"));
Long roid1 = Long.parseLong(request.getParameter("roid1"));
Long roid2 = Long.parseLong(request.getParameter("roid2"));
topicId = serviceMap.getServiceInterface().downloadCompareResults(serializer.getOid(), roid1, roid2, Long.valueOf(request.getParameter("mcid")), sCompareType, true);
} else if (request.getParameter("topicId") != null) {
topicId = Long.parseLong(request.getParameter("topicId"));
} else {
long roid = -1;
if (request.getParameter("roid") == null) {
if (request.getParameter("poid") != null) {
long poid = Long.parseLong(request.getParameter("poid"));
SProject projectByPoid = serviceMap.getBimsie1ServiceInterface().getProjectByPoid(poid);
if (projectByPoid == null) {
throw new UserException("Project with oid " + poid + " not found");
}
roid = projectByPoid.getLastRevisionId();
if (roid == -1) {
throw new UserException("No revisions");
}
} else {
throw new UserException("A poid or roid is required for downloading");
}
} else {
roid = Long.parseLong(request.getParameter("roid"));
}
if (request.getParameter("checkout") != null) {
topicId = serviceMap.getBimsie1ServiceInterface().checkout(roid, serializer.getOid(), true);
} else {
if (request.getParameter("classses") != null) {
Set classes = new HashSet();
for (String className : request.getParameter("classses").split(";")) {
classes.add(className);
}
Set roids = new HashSet();
roids.add(roid);
topicId = serviceMap.getBimsie1ServiceInterface().downloadByTypes(roids, "ifc2x3tc1", classes, serializer.getOid(), false, true, true, true);
} else if (request.getParameter("oids") != null) {
Set oids = new HashSet();
for (String oidString : request.getParameter("oids").split(";")) {
oids.add(Long.parseLong(oidString));
}
Set roids = new HashSet();
roids.add(roid);
topicId = serviceMap.getBimsie1ServiceInterface().downloadByOids(roids, oids, serializer.getOid(), true, true);
} else if (request.getParameter("guids") != null) {
Set guids = new HashSet();
for (String guid : request.getParameter("guids").split(";")) {
guids.add(guid);
}
Set roids = new HashSet();
roids.add(roid);
topicId = serviceMap.getBimsie1ServiceInterface().downloadByGuids(roids, guids, serializer.getOid(), false, true);
} else {
topicId = serviceMap.getBimsie1ServiceInterface().download(roid, serializer.getOid(), true, true);
}
}
}
if (topicId == -1) {
response.getWriter().println("No valid topicId");
return;
}
SDownloadResult checkoutResult = serviceMap.getBimsie1ServiceInterface().getDownloadData(topicId);
if (checkoutResult == null) {
LOGGER.error("Invalid topicId: " + topicId);
} else {
DataSource dataSource = checkoutResult.getFile().getDataSource();
PluginConfiguration pluginConfiguration = new PluginConfiguration(serviceMap.getPluginInterface().getPluginSettings(serializer.getOid()));
final ProgressTopic progressTopic = getBimServer().getNotificationsManager().getProgressTopic(topicId);
ProgressReporter progressReporter = new ProgressReporter() {
private long lastMax;
private long lastProgress;
private int stage = 3;
private Date start = new Date();
private String title = "Downloading...";
@Override
public void update(long progress, long max) {
if (progressTopic != null) {
LongActionState ds = StoreFactory.eINSTANCE.createLongActionState();
ds.setStart(start);
ds.setState(progress == max ? ActionState.FINISHED : ActionState.STARTED);
ds.setTitle(title);
ds.setStage(stage);
ds.setProgress((int) Math.round(100.0 * progress / max));
progressTopic.stageProgressUpdate(ds);
this.lastMax = max;
this.lastProgress = progress;
}
}
@Override
public void setTitle(String title) {
if (progressTopic != null) {
stage++;
this.title = title;
LongActionState ds = StoreFactory.eINSTANCE.createLongActionState();
ds.setStart(new Date());
ds.setState(lastProgress == lastMax ? ActionState.FINISHED : ActionState.STARTED);
ds.setTitle(title);
ds.setStage(stage);
ds.setProgress((int) Math.round(100.0 * lastProgress / lastMax));
progressTopic.stageProgressUpdate(ds);
}
}
};
try {
if (zip) {
if (pluginConfiguration.getString("ZipExtension") != null) {
response.setHeader("Content-Disposition", "inline; filename=\"" + dataSource.getName() + "." + pluginConfiguration.getString(SerializerPlugin.ZIP_EXTENSION) + "\"");
} else {
response.setHeader("Content-Disposition", "inline; filename=\"" + dataSource.getName() + ".zip" + "\"");
}
response.setContentType("application/zip");
String nameInZip = dataSource.getName() + "." + pluginConfiguration.getString(SerializerPlugin.EXTENSION);
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
zipOutputStream.putNextEntry(new ZipEntry(nameInZip));
processDataSource(zipOutputStream, dataSource, progressReporter);
try {
zipOutputStream.finish();
} catch (IOException e) {
// Sometimes it's already closed, that's no problem
}
} else {
if (request.getParameter("mime") == null) {
response.setContentType(pluginConfiguration.getString(SerializerPlugin.CONTENT_TYPE));
response.setHeader("Content-Disposition", "inline; filename=\"" + dataSource.getName() + "." + pluginConfiguration.getString(SerializerPlugin.EXTENSION) + "\"");
} else {
response.setContentType(request.getParameter("mime"));
}
processDataSource(outputStream, dataSource, progressReporter);
}
} catch (SerializerException s) {
LOGGER.error("", s);
LongActionState ds = StoreFactory.eINSTANCE.createLongActionState();
ds.setStart(new Date());
ds.setState(ActionState.AS_ERROR);
ds.setTitle("Serialization Error");
ds.setProgress(-1);
ds.setStage(3);
ds.getErrors().add(s.getMessage());
progressTopic.stageProgressUpdate(ds);
}
}
}
if (outputStream instanceof GZIPOutputStream) {
((GZIPOutputStream) outputStream).finish();
}
outputStream.flush();
} catch (NumberFormatException e) {
LOGGER.error("", e);
response.getWriter().println("Some number was incorrectly formatted");
} catch (ServiceException e) {
LOGGER.error("", e);
response.getWriter().println(e.getUserMessage());
} catch (EOFException e) {
} catch (Exception e) {
LOGGER.error("", e);
}
}
private void processDataSource(OutputStream outputStream, DataSource dataSource, ProgressReporter progressReporter) throws IOException, SerializerException, BimserverDatabaseException {
if (dataSource instanceof ExtendedDataSource) {
((ExtendedDataSource) dataSource).writeToOutputStream(outputStream, progressReporter);
} else {
throw new SerializerException("Unsupported datasource type: " + dataSource);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy