View Javadoc
1   package fr.ifremer.quadrige2.ui.swing.common.synchro.action;
2   
3   /*-
4    * #%L
5    * Quadrige2 Core :: Quadrige2 UI Common
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2017 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  
27  import fr.ifremer.quadrige2.ui.swing.common.synchro.SynchroUIHandler;
28  import org.apache.commons.io.FileUtils;
29  import org.apache.commons.io.FilenameUtils;
30  import org.apache.commons.lang3.StringUtils;
31  import org.apache.http.HttpException;
32  import org.apache.http.HttpStatus;
33  import org.apache.http.client.CredentialsProvider;
34  import org.apache.http.client.methods.CloseableHttpResponse;
35  import org.apache.http.client.methods.HttpGet;
36  import org.apache.http.client.utils.URIBuilder;
37  import org.apache.http.impl.client.CloseableHttpClient;
38  import org.apache.http.impl.client.HttpClients;
39  import org.nuiton.util.ZipUtil;
40  
41  import java.io.*;
42  import java.net.URI;
43  
44  import static org.nuiton.i18n.I18n.t;
45  
46  /**
47   * <p>Abstract AbstractDownloadAction class.</p>
48   *
49   * @author Ludovic Pecquot <ludovic.pecquot@e-is.pro>
50   */
51  public abstract class AbstractDownloadAction extends AbstractSynchroAction {
52  
53      private boolean downloaded;
54      private boolean toUncompress;
55      private File resultDir = null;
56  
57      /**
58       * <p>getTargetDirectory.</p>
59       *
60       * @return a {@link File} object.
61       */
62      public abstract File getTargetDirectory();
63  
64      /**
65       * <p>getUrlPath.</p>
66       *
67       * @return a {@link String} object.
68       */
69      public abstract String getUrlPath();
70  
71      /**
72       * <p>Constructor for AbstractDownloadAction.</p>
73       *
74       * @param handler a {@link SynchroUIHandler} object.
75       */
76      public AbstractDownloadAction(SynchroUIHandler handler) {
77          super(handler);
78  
79          toUncompress = true;
80      }
81  
82      /**
83       * <p>Setter for the field <code>toUncompress</code>.</p>
84       *
85       * @param toUncompress a boolean.
86       */
87      public void setToUncompress(boolean toUncompress) {
88          this.toUncompress = toUncompress;
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public boolean initAction() {
94          super.initAction();
95  
96          getHandler().showProgressCard();
97  
98          downloaded = false;
99          getModel().setWorkingDirectory(null);
100 
101         return true;
102     }
103 
104     /** {@inheritDoc} */
105     @Override
106     public void doAction() throws Exception {
107 
108         CredentialsProvider credentialsProvider = getCredentialsProvider();
109 
110         try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
111                 .setDefaultCredentialsProvider(credentialsProvider)
112                 .build()) {
113 
114             String fileName = getModel().getTransferFilename();
115 
116             if (StringUtils.isBlank(fileName)) {
117                 throw new IOException("can not get the file name to download");
118             }
119 
120             File downloadedFile = new File(getConfig().getTempDirectory(), fileName);
121             if (!downloadedFile.createNewFile()) {
122                 throw new IOException(String.format("file %s already exists", downloadedFile.getAbsolutePath()));
123             }
124 
125             getModel().getProgressionModel().setMessage(t("quadrige2.synchro.progress.download"));
126 
127             // download the zip file
128             URI downloadUri = new URIBuilder(getAppendedPath(getUrlPath(), fileName)).build();
129             HttpGet downloadHttpGet = new HttpGet(downloadUri);
130 
131             try (CloseableHttpResponse response = httpClient.execute(downloadHttpGet);
132                  FileOutputStream fileOutputStream = new FileOutputStream(downloadedFile)) {
133 
134                 if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
135                     throw new HttpException(
136                             String.format("error while downloading file '%s'; server responds: %s", fileName, response.getStatusLine().getReasonPhrase()));
137                 }
138 
139                 downloadWithProgression(response.getEntity().getContent(), response.getEntity().getContentLength(), fileOutputStream);
140             }
141 
142             getModel().getProgressionModel().setMessage(t("quadrige2.synchro.progress.uncompress"));
143             getModel().getProgressionModel().setIndeterminate(true);
144 
145             // Compute the target directory for user
146             File userDir = getTargetDirectory();
147             FileUtils.forceMkdir(userDir);
148 
149             if (toUncompress && ZipUtil.isZipFile(downloadedFile)) {
150 
151                 // Unzip it
152                 resultDir = new File(userDir, FilenameUtils.getBaseName(fileName));
153                 ZipUtil.uncompress(downloadedFile, resultDir);
154                 downloadedFile.delete();
155             } else {
156 
157                 // move it
158                 resultDir = userDir;
159                 FileUtils.moveFileToDirectory(downloadedFile, resultDir, true);
160             }
161 
162             downloaded = true;
163 
164         }
165     }
166 
167     private void downloadWithProgression(InputStream input, long inputSize, OutputStream output) throws IOException {
168         if (input == null || output == null) {
169             return;
170         }
171 
172         try (BufferedInputStream bis = new BufferedInputStream(input);
173              BufferedOutputStream bos = new BufferedOutputStream(output);) {
174 
175             // initialize progression
176             getModel().getProgressionModel().setSize(inputSize);
177 
178             long count = 0L;
179             int bytesReaded;
180             byte[] bytes = new byte[4096];
181 
182             while ((bytesReaded = bis.read(bytes)) != -1) {
183 
184                 // copy
185                 bos.write(bytes, 0, bytesReaded);
186 
187                 // progresion increment
188                 count += bytesReaded;
189                 getModel().getProgressionModel().setCurrent(count);
190 
191             }
192 
193         }
194     }
195 
196     /** {@inheritDoc} */
197     @Override
198     public void doneAction() {
199         updateModel();
200     }
201 
202     /** {@inheritDoc} */
203     @Override
204     public void failedAction(Throwable ex) {
205         updateModel();
206         super.failedAction(ex);
207     }
208 
209     private void updateModel() {
210         getModel().setWorkingDirectory((downloaded && resultDir != null && resultDir.isDirectory()) ? resultDir : null);
211     }
212 
213 }