source: extensions/jiwigo-ws-api/src/main/java/fr/mael/jiwigo/dao/impl/ImageDaoImpl.java @ 10494

Last change on this file since 10494 was 10494, checked in by anthony43, 13 years ago

addSimple ws api method added, with unit tests
http://piwigo.org/doc/doku.php?id=en:dev:webapi:pwg.images.addsimple
pom upgraded to 0.3.0-SNAPSHOT since this is a minor change, and also a dependency was added (httpmime)
SessionManagerImpl was modified to make available its httpclient.

File size: 12.7 KB
Line 
1package fr.mael.jiwigo.dao.impl;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.IOException;
6import java.io.InputStreamReader;
7import java.net.HttpURLConnection;
8import java.security.NoSuchAlgorithmException;
9import java.util.ArrayList;
10import java.util.HashMap;
11import java.util.List;
12
13import org.apache.http.HttpEntity;
14import org.apache.http.HttpResponse;
15import org.apache.http.client.methods.HttpPost;
16import org.apache.http.entity.BufferedHttpEntity;
17import org.apache.http.entity.mime.MultipartEntity;
18import org.apache.http.entity.mime.content.FileBody;
19import org.apache.http.entity.mime.content.StringBody;
20import org.slf4j.Logger;
21import org.slf4j.LoggerFactory;
22import org.w3c.dom.Document;
23import org.w3c.dom.Element;
24import org.w3c.dom.Node;
25import org.w3c.dom.NodeList;
26
27import sun.misc.BASE64Encoder;
28import fr.mael.jiwigo.dao.ImageDao;
29import fr.mael.jiwigo.om.Image;
30import fr.mael.jiwigo.transverse.enumeration.MethodsEnum;
31import fr.mael.jiwigo.transverse.exception.FileAlreadyExistsException;
32import fr.mael.jiwigo.transverse.exception.ProxyAuthenticationException;
33import fr.mael.jiwigo.transverse.exception.WrongChunkSizeException;
34import fr.mael.jiwigo.transverse.session.SessionManager;
35import fr.mael.jiwigo.transverse.session.impl.SessionManagerImpl;
36import fr.mael.jiwigo.transverse.util.Tools;
37
38/*
39 *  jiwigo-ws-api Piwigo webservice access Api
40 *  Copyright (c) 2010-2011 Mael mael@le-guevel.com
41 *                All Rights Reserved
42 *
43 *  This library is free software. It comes without any warranty, to
44 *  the extent permitted by applicable law. You can redistribute it
45 *  and/or modify it under the terms of the Do What The Fuck You Want
46 *  To Public License, Version 2, as published by Sam Hocevar. See
47 *  http://sam.zoy.org/wtfpl/COPYING for more details.
48 */
49/**
50
51 * Dao of the images
52 * @author mael
53 *
54 */
55public class ImageDaoImpl implements ImageDao {
56
57    /**
58     * Logger
59     */
60    private final Logger LOG = LoggerFactory.getLogger(ImageDaoImpl.class);
61
62    /**
63     * cache to avoid downloading image for each access
64     */
65    private HashMap<Integer, List<Image>> cache;
66
67    /**
68     *
69     */
70    private Integer firstCatInCache;
71
72    private SessionManager sessionManager;
73
74    private ArrayList<File> filesToSend;
75
76    public ImageDaoImpl() {
77        cache = new HashMap<Integer, List<Image>>();
78    }
79
80    /**
81     * Lists all images
82     * @return the list of images
83     * @throws IOException
84     * @throws ProxyAuthenticationException
85     */
86    public List<Image> list(boolean refresh) throws IOException, ProxyAuthenticationException {
87        return listByCategory(null, refresh);
88    }
89
90    /**
91     * Listing of the images for a category
92     * @param categoryId the id of the category
93     * @return the list of images
94     * @throws IOException
95     * @throws ProxyAuthenticationException
96     */
97    public List<Image> listByCategory(Integer categoryId, boolean refresh) throws IOException,
98            ProxyAuthenticationException {
99        if (refresh || cache.get(categoryId) == null) {
100            Document doc = null;
101            if (categoryId != null) {
102                doc = sessionManager.executeReturnDocument(MethodsEnum.LISTER_IMAGES.getLabel(), "cat_id",
103                        String.valueOf(categoryId));
104            } else {
105                doc = sessionManager.executeReturnDocument(MethodsEnum.LISTER_IMAGES.getLabel());
106            }
107            Element element = (Element) doc.getDocumentElement().getElementsByTagName("images").item(0);
108            List<Image> images = getImagesFromElement(element);
109            cache.remove(categoryId);
110            cache.put(categoryId, images);
111            if (firstCatInCache == null) {
112                firstCatInCache = categoryId;
113            }
114            return images;
115        } else {
116            return cache.get(categoryId);
117        }
118    }
119
120    /**
121     * Creation of an image<br/>
122     * Sequence : <br/>
123     * <li>
124     * <ul>sending of the thumbnail in base64, thanks to the method addchunk.</ul>
125     * <ul>sending of the image in base64, thanks to the method addchunk</ul>
126     * <ul>using of the add method to add the image to the database<ul>
127     * </li>
128     * Finally, the response of the webservice is checked
129     *
130     * @param image the image to create
131     * @return true if the creation of the image was the successful
132     * @throws IOException
133     * @throws NoSuchAlgorithmException
134     * @throws WrongChunkSizeException
135     * @throws Exception
136     */
137    //TODO ne pas continuer si une des reponses precedentes est negative
138    public boolean create(Image image, Double chunkSize) throws FileAlreadyExistsException, IOException,
139            ProxyAuthenticationException, NoSuchAlgorithmException, WrongChunkSizeException {
140        //thumbnail converted to base64
141        BASE64Encoder base64 = new BASE64Encoder();
142
143        String thumbnailBase64 = base64.encode(Tools.getBytesFromFile(image.getThumbnail()));
144        //sends the thumbnail and gets the result
145        Document reponseThumb = (sessionManager.executeReturnDocument("pwg.images.addChunk", "data", thumbnailBase64,
146                "type", "thumb", "position", "1", "original_sum",
147                Tools.getMD5Checksum(image.getOriginale().getAbsolutePath())));
148
149        //begin feature:0001827
150        int chunk = chunkSize.intValue();
151        if (chunk == 0) {
152            throw new WrongChunkSizeException("Error : the chunk size cannot be 0");
153        }
154        filesToSend = Tools.splitFile(image.getOriginale(), chunk);
155        boolean echec = false;
156        for (int i = 0; i < filesToSend.size(); i++) {
157            File fichierAEnvoyer = filesToSend.get(i);
158            String originaleBase64 = base64.encode(Tools.getBytesFromFile(fichierAEnvoyer));
159            Document reponseOriginale = (sessionManager.executeReturnDocument("pwg.images.addChunk", "data",
160                    originaleBase64, "type", "file", "position", String.valueOf(i), "original_sum",
161                    Tools.getMD5Checksum(image.getOriginale().getAbsolutePath())));
162            if (!Tools.checkOk(reponseOriginale)) {
163                echec = true;
164                break;
165            }
166        }
167        //end
168
169        //add the image in the database and get the result of the webservice
170        Document reponseAjout = (sessionManager.executeReturnDocument("pwg.images.add", "file_sum",
171                Tools.getMD5Checksum(image.getOriginale().getAbsolutePath()), "thumbnail_sum",
172                Tools.getMD5Checksum(image.getThumbnail().getCanonicalPath()), "position", "1", "original_sum",
173                Tools.getMD5Checksum(image.getOriginale().getAbsolutePath()), "categories",
174                String.valueOf(image.getIdCategory()), "name", image.getName(), "author", sessionManager.getLogin(),
175                "level", image.getPrivacyLevel()));
176        LOG.debug("Response add : " + Tools.documentToString(reponseAjout));
177        //      System.out.println(Main.sessionManager.executerReturnString("pwg.images.add", "file_sum", Outil
178        //              .getMD5Checksum(image.getOriginale().getAbsolutePath()), "thumbnail_sum", Outil.getMD5Checksum(image
179        //              .getThumbnail().getCanonicalPath()), "position", "1", "original_sum", Outil.getMD5Checksum(image
180        //              .getOriginale().getAbsolutePath()), "categories", String.valueOf(image.getIdCategory()), "name", image
181        //              .getName(), "author", Main.sessionManager.getLogin()));
182        //      Document reponsePrivacy = null;
183        //      if (Outil.checkOk(reponseAjout)) {
184        //          reponsePrivacy = Main.sessionManager.executerReturnDocument(MethodsEnum.SET_PRIVACY_LEVEL.getLabel());
185        //      }
186        boolean reussite = true;
187        if (!Tools.checkOk(reponseThumb) || echec || !Tools.checkOk(reponseAjout)) {
188            reussite = false;
189        }
190        deleteTempFiles();
191        return reussite;
192
193    }
194
195    /**
196     * Add tags to an image
197     * @param imageId id of the image
198     * @param tagId ids of the tags
199     * @throws IOException
200     * @throws ProxyAuthenticationException
201     */
202    public boolean addTags(Integer imageId, String tagId) throws IOException, ProxyAuthenticationException {
203        Document doc = sessionManager.executeReturnDocument(MethodsEnum.SET_INFO.getLabel(), "image_id",
204                String.valueOf(imageId), "tag_ids", tagId);
205        try {
206            return Tools.checkOk(doc);
207        } catch (FileAlreadyExistsException e) {
208            LOG.error(Tools.getStackTrace(e));
209            return false;
210        }
211
212    }
213
214    /**
215     * parse an element to find images
216     * @param element the element to parse
217     * @return the list of images
218     */
219    private List<Image> getImagesFromElement(Element element) {
220        //      List<Element> listElement = (List<Element>) element.getChildren("image");
221        NodeList listImages = element.getElementsByTagName("image");
222        ArrayList<Image> images = new ArrayList<Image>();
223        for (int i = 0; i < listImages.getLength(); i++) {
224            Node nodeImage = listImages.item(i);
225            if (nodeImage.getNodeType() == Node.ELEMENT_NODE) {
226                Element im = (Element) nodeImage;
227                Image myImage = new Image();
228                myImage.setThumbnailUrl(im.getAttribute("tn_url"));
229                myImage.setUrl(im.getAttribute("element_url"));
230                myImage.setWidth(Integer.valueOf(im.getAttribute("width")));
231                myImage.setHeight(Integer.valueOf(im.getAttribute("height")));
232                myImage.setFile(im.getAttribute("file"));
233                myImage.setSeen(Integer.valueOf(im.getAttribute("hit")));
234                myImage.setIdentifier(Integer.valueOf(im.getAttribute("id")));
235                myImage.setName(Tools.getStringValueDom(im, "name"));
236                Element elementCategories = (Element) im.getElementsByTagName("categories").item(0);
237                Element elementCategory = (Element) elementCategories.getElementsByTagName("category").item(0);
238                myImage.setIdCategory(Integer.valueOf(elementCategory.getAttribute("id")));
239                if (myImage.getName() == null) {
240                    myImage.setName(myImage.getFile());
241                }
242                images.add(myImage);
243            }
244        }
245        return images;
246    }
247
248    /**
249     * Search images
250     * @param searchString the string to search
251     * @return the list of images matching the string
252     * @throws IOException
253     * @throws ProxyAuthenticationException
254     */
255    public List<Image> search(String searchString) throws IOException, ProxyAuthenticationException {
256        Document doc = sessionManager.executeReturnDocument(MethodsEnum.SEARCH.getLabel(), "query", searchString);
257        LOG.debug(Tools.documentToString(doc));
258        Element element = (Element) doc.getDocumentElement().getElementsByTagName("images").item(0);
259        return getImagesFromElement(element);
260
261    }
262
263    private void deleteTempFiles() {
264        File file = new File(System.getProperty("java.io.tmpdir") + "/originale.jpg");
265        file.delete();
266        file = new File(System.getProperty("java.io.tmpdir") + "/thumb.jpg");
267        file.delete();
268        for (File tempCut : filesToSend) {
269            tempCut.delete();
270        }
271
272    }
273
274    public void addSimple(File file, Integer category, String title) throws IOException {
275        HttpPost httpMethod = new HttpPost(((SessionManagerImpl) sessionManager).getUrl());
276
277        //      nameValuePairs.add(new BasicNameValuePair("method", "pwg.images.addSimple"));
278        //      for (int i = 0; i < parametres.length; i += 2) {
279        //          nameValuePairs.add(new BasicNameValuePair(parametres[i], parametres[i + 1]));
280        //      }
281        //      method.setEntity(new UrlEncodedFormEntity(nameValuePairs));
282
283        if (file != null) {
284            MultipartEntity multipartEntity = new MultipartEntity();
285
286            //          String string = nameValuePairs.toString();
287            // dirty fix to remove the enclosing entity{}
288            //          String substring = string.substring(string.indexOf("{"),
289            //                          string.lastIndexOf("}") + 1);
290            multipartEntity.addPart("method", new StringBody("pwg.images.addSimple"));
291            multipartEntity.addPart("category", new StringBody(category.toString()));
292            multipartEntity.addPart("name", new StringBody(title));
293
294            //          StringBody contentBody = new StringBody(substring,
295            //                          Charset.forName("UTF-8"));
296            //          multipartEntity.addPart("entity", contentBody);
297            FileBody fileBody = new FileBody(file);
298            multipartEntity.addPart("image", fileBody);
299            ((HttpPost) httpMethod).setEntity(multipartEntity);
300        }
301
302        //      httpMethod.setHeader(X_GALLERY_REQUEST_METHOD, requestMethod);
303        HttpResponse response = ((SessionManagerImpl) sessionManager).getClient().execute(httpMethod);
304        int responseStatusCode = response.getStatusLine().getStatusCode();
305
306        switch (responseStatusCode) {
307        case HttpURLConnection.HTTP_CREATED:
308            break;
309        case HttpURLConnection.HTTP_OK:
310            break;
311        case HttpURLConnection.HTTP_BAD_REQUEST:
312            throw new IOException("status code was : " + responseStatusCode);
313        case HttpURLConnection.HTTP_FORBIDDEN:
314            throw new IOException("status code was : " + responseStatusCode);
315        case HttpURLConnection.HTTP_NOT_FOUND:
316            throw new IOException("status code was : " + responseStatusCode);
317        default:
318            throw new IOException("status code was : " + responseStatusCode);
319        }
320
321        HttpEntity resultEntity = response.getEntity();
322        BufferedHttpEntity responseEntity = new BufferedHttpEntity(resultEntity);
323
324        BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent()));
325        String line;
326        StringBuilder sb = new StringBuilder();
327        try {
328            while ((line = reader.readLine()) != null) {
329                sb.append(line);
330                sb.append("\n");
331            }
332        } finally {
333            reader.close();
334        }
335        String stringResult = sb.toString();
336
337    }
338
339    public SessionManager getSessionManager() {
340        return sessionManager;
341    }
342
343    public void setSessionManager(SessionManager sessionManager) {
344        this.sessionManager = sessionManager;
345    }
346}
Note: See TracBrowser for help on using the repository browser.