001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.requests;
019
020import static io.stallion.utils.Literals.*;
021import static io.stallion.Context.*;
022
023import java.io.*;
024import java.net.URL;
025import java.nio.charset.StandardCharsets;
026import java.nio.file.FileSystems;
027import java.nio.file.Files;
028import java.util.List;
029import java.util.Map;
030
031import io.stallion.services.Log;
032import io.stallion.utils.GeneralUtils;
033
034import javax.servlet.ServletOutputStream;
035
036/**
037 * A collection of methods for sending static assets files as a buffered servlet responses.
038 */
039public class ServletFileSender {
040    private StResponse response;
041    private IRequest request;
042
043    public ServletFileSender(IRequest request, StResponse response) {
044        this.request = request;
045        this.response = response;
046    }
047
048    public void sendContentResponse(String content, String fullPath) {
049        sendContentResponse(content, 0, fullPath);
050    }
051
052    public void sendContentResponse(String content, long modifyTime, String fullPath) {
053        byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
054        InputStream stream = new ByteArrayInputStream(bytes);
055        sendAssetResponse(stream, modifyTime, bytes.length, fullPath);
056    }
057
058    public void sendResource(URL url, String path) {
059        try {
060            int length = url.openConnection().getContentLength();
061            sendAssetResponse(url.openStream(), 0, length, url.toString());
062        } catch (Exception e) {
063            throw new RuntimeException(e);
064        }
065    }
066
067
068    public void sendAssetResponse(File file) {
069        try {
070            sendAssetResponse(new FileInputStream(file), file.lastModified(), file.length(), file.getAbsolutePath());
071        } catch (FileNotFoundException e) {
072            throw new RuntimeException(e);
073        }
074    }
075
076    public void sendAssetResponse(InputStream stream, long modifyTime, long contentLength, String fullPath) {
077        try {
078            // Set the caching headers
079            Long duration = 60 * 60 * 24 * 365 * 10L; // 10 years
080            Long durationMils = duration * 1000;
081            response.addHeader("Cache-Control", "max-age=" + duration);
082            response.setDateHeader("Expires", System.currentTimeMillis() + durationMils);
083            if (modifyTime > 0) {
084                response.setDateHeader("Last-Modified", modifyTime);
085            }
086
087            // Set the Content-type
088            String contentType = GeneralUtils.guessMimeType(fullPath);
089            if (empty(contentType)) {
090                contentType = Files.probeContentType(FileSystems.getDefault().getPath(fullPath));
091            }
092            response.setContentType(contentType);
093
094
095            Integer BUFF_SIZE = 8192;
096            if (response.getHttpServletResponse() != null) {
097                response.getHttpServletResponse().setBufferSize(BUFF_SIZE);
098                //response.getHttpServletResponse().
099            }
100            byte[] buffer = new byte[BUFF_SIZE];
101            ServletOutputStream os = response.getOutputStream();
102            response.setContentLength((int) contentLength);
103
104            try {
105                int byteRead = 0;
106                int readCount = 0;
107                int totalRead = 0;
108                while (true) {
109                    byteRead = stream.read(buffer);
110                    if (byteRead == -1) {
111                        break;
112                    }
113                    //totalRead += byteRead;
114                    //Log.info("Bytes sent {0}", totalRead);
115                    os.write(buffer, 0, byteRead);
116                }
117                //os.flush();
118            } catch (Exception e) {
119                e.printStackTrace();
120            } finally {
121                //os.close();
122                stream.close();
123            }
124        } catch (IOException e) {
125            throw new RuntimeException(e);
126        }
127
128    }
129
130
131}