f821483dac4b2fbe5469f57edeb343c8807a39bf
[mir.git] / source / mircoders / entity / EntityImages.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 package mircoders.entity;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.sql.Connection;
37 import java.sql.PreparedStatement;
38 import java.sql.ResultSet;
39 import java.sql.SQLException;
40 import java.sql.Statement;
41
42 import mir.config.MirPropertiesConfiguration;
43 import mir.log.LoggerWrapper;
44 import mir.misc.FileUtil;
45 import mir.storage.StorageObject;
46 import mir.storage.StorageObjectFailure;
47 import mircoders.media.ImageProcessor;
48
49 import org.postgresql.largeobject.BlobInputStream;
50 import org.postgresql.largeobject.LargeObject;
51 import org.postgresql.largeobject.LargeObjectManager;
52
53 /**
54  *
55  * @author RK, mh, mir-coders
56  * @version $Id: EntityImages.java,v 1.21.2.3 2003/12/14 16:37:07 zapata Exp $
57  */
58
59
60 public class EntityImages extends EntityUploadedMedia
61 {
62   private int maxImageSize = configuration.getInt("Producer.Image.MaxSize");
63   private int maxIconSize = configuration.getInt("Producer.Image.MaxIconSize");
64   private float minDescaleRatio = configuration.getFloat("Producer.Image.MinDescalePercentage")/100;
65   private int minDescaleReduction = configuration.getInt("Producer.Image.MinDescaleReduction");
66
67
68   public EntityImages()
69   {
70     super();
71
72     logger = new LoggerWrapper("Entity.UploadedMedia.Images");
73   }
74
75   public EntityImages(StorageObject theStorage) {
76     this();
77     setStorage(theStorage);
78   }
79
80   //
81   // methods
82
83
84   public InputStream getImage() throws StorageObjectFailure {
85     logger.debug("EntityImages.getimage started");
86     java.sql.Connection con=null;
87     Statement stmt=null;
88     BlobInputStream in;
89     InputStream img_in = null;
90     try {
91       con = theStorageObject.getPooledCon();
92       con.setAutoCommit(false);
93       LargeObjectManager lom;
94       java.sql.Connection jCon;
95       stmt = con.createStatement();
96       ResultSet rs = theStorageObject.executeSql(stmt,
97           "select image_data from images where id="+getId());
98       jCon = ((com.codestudio.sql.PoolManConnectionHandle)con)
99            .getNativeConnection();
100       lom = ((org.postgresql.Connection)jCon).getLargeObjectAPI();
101       if(rs!=null) {
102         if (rs.next()) {
103           LargeObject lob = lom.open(rs.getInt(1));
104           in = (BlobInputStream)lob.getInputStream();
105           img_in = new ImageInputStream(in, con, stmt);
106         }
107         rs.close();
108       }
109     }
110     catch (Throwable t) {
111       logger.error("EntityImages.getImage failed: " + t.toString());
112       t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
113
114       try {
115         con.setAutoCommit(true);
116       }
117       catch (Throwable e) {
118         logger.error("EntityImages.getImage resetting transaction mode failed: " + e.toString());
119         e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
120       }
121
122       try {
123         theStorageObject.freeConnection(con, stmt);
124       }
125       catch (Throwable e) {
126         logger.error("EntityImages.getImage freeing connection failed: " +e.toString());
127       }
128
129       throwStorageObjectFailure(t, "EntityImages -- getImage failed: ");
130     }
131     return img_in;
132   }
133
134   public void setImage(InputStream in, String type) throws StorageObjectFailure {
135
136     if (in != null) {
137
138       Connection con = null;
139       PreparedStatement pstmt = null;
140       File f = null;
141       try {
142         logger.debug("EntityImages.settimage :: making internal representation of image");
143
144         f = File.createTempFile("mir", ".tmp",
145                 new File(MirPropertiesConfiguration.instance().getString("TempDir")));
146         FileUtil.write(f, in);
147         ImageProcessor processor = new ImageProcessor(f);
148
149         con = theStorageObject.getPooledCon();
150         con.setAutoCommit(false);
151         LargeObjectManager lom;
152         java.sql.Connection connection;
153         connection = ((com.codestudio.sql.PoolManConnectionHandle)con).getNativeConnection();
154
155         lom = ((org.postgresql.Connection) connection).getLargeObjectAPI();
156
157         int oidImage = lom.create();
158         LargeObject lobImage = lom.open(oidImage);
159         processor.descaleImage(maxImageSize, minDescaleRatio, minDescaleReduction);
160         processor.writeScaledData(lobImage.getOutputStream(), type);
161         lobImage.close();
162         setValueForProperty("img_height", new Integer(processor.getScaledHeight()).toString());
163         setValueForProperty("img_width", new Integer(processor.getScaledWidth()).toString());
164
165         int oidIcon = lom.create();
166         LargeObject lobIcon = lom.open(oidIcon);
167         processor.descaleImage(maxIconSize, minDescaleRatio, minDescaleReduction);
168         processor.writeScaledData(lobIcon.getOutputStream(), type);
169         lobIcon.close();
170
171         setValueForProperty("icon_height", new Integer(processor.getScaledHeight()).toString());
172         setValueForProperty("icon_width", new Integer(processor.getScaledWidth()).toString());
173
174         setValueForProperty("image_data", new Integer(oidImage).toString());
175         setValueForProperty("icon_data", new Integer(oidIcon).toString());
176         update();
177       }
178       catch (Exception e) {
179         throwStorageObjectFailure(e, "settimage :: setImage failed: ");
180       }
181       finally {
182         try {
183           if (con!=null)
184             con.setAutoCommit(true);
185           // get rid of the temp. file
186           f.delete();
187         } catch (SQLException e) {
188           throwStorageObjectFailure(e,"Resetting transaction-mode failed");
189         }
190         if (con!=null)
191           theStorageObject.freeConnection(con,pstmt);
192       }
193     }
194   }
195
196   /**
197    * Takes an OutputStream as an argument and reads in the data
198    * from the DB and writes it to the OutputStream.
199    *
200    * It will also take care of closing the OutputStream.
201    */
202   public InputStream getIcon() throws StorageObjectFailure {
203     Connection con=null;
204     Statement stmt=null;
205     BlobInputStream in=null;
206     ImageInputStream img_in=null;
207
208     try {
209       con = theStorageObject.getPooledCon();
210       con.setAutoCommit(false);
211       LargeObjectManager lom;
212       java.sql.Connection jCon;
213       stmt = con.createStatement();
214       ResultSet rs = theStorageObject.executeSql(stmt, "select icon_data from images where id="+getId());
215       jCon = ((com.codestudio.sql.PoolManConnectionHandle)con)
216            .getNativeConnection();
217       lom = ((org.postgresql.Connection)jCon).getLargeObjectAPI();
218       if(rs!=null) {
219         if (rs.next()) {
220           LargeObject lob = lom.open(rs.getInt(1));
221           in = (BlobInputStream)lob.getInputStream();
222           img_in = new ImageInputStream( in, con ,stmt);
223           //img_data = rs.getBytes(1);
224         }
225         rs.close();
226       }
227     }
228     catch (Throwable t) {
229       logger.error("EntityImages.getIcon failed: "+t.toString());
230       t.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
231
232       try {
233         con.setAutoCommit(true);
234       }
235       catch (SQLException e) {
236         logger.error("EntityImages.getIcon resetting transaction mode failed: " + e.toString());
237         e.printStackTrace(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
238       }
239       try {
240         theStorageObject.freeConnection(con, stmt);
241       }
242       catch (Throwable e) {
243        logger.error("EntityImages -- freeing connection failed: " + e.getMessage());
244       }
245
246       throwStorageObjectFailure(t, "EntityImages -- getIcon failed:");
247     }
248
249     return img_in;
250   }
251
252   /**
253    * a small wrapper class that allows us to store the DB connection resources
254    * that the BlobInputStream is using and free them upon closing of the stream
255    */
256   private class ImageInputStream extends InputStream {
257
258     InputStream _in;
259     Connection _con;
260     Statement _stmt;
261
262     public ImageInputStream(BlobInputStream in, Connection con,
263                             Statement stmt ) {
264       _in = in;
265       _con = con;
266       _stmt = stmt;
267     }
268
269     public void close () throws IOException {
270       _in.close();
271       try {
272         _con.setAutoCommit(true);
273         theStorageObject.freeConnection(_con,_stmt);
274       }
275       catch (Exception e) {
276         throw new IOException("close(): "+e.toString());
277       }
278     }
279
280     public int read() throws IOException {
281       return _in.read();
282     }
283   }
284 }