001: //=============================================================================
002: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
003: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
004: //=== and United Nations Environment Programme (UNEP)
005: //===
006: //=== This program is free software; you can redistribute it and/or modify
007: //=== it under the terms of the GNU General Public License as published by
008: //=== the Free Software Foundation; either version 2 of the License, or (at
009: //=== your option) any later version.
010: //===
011: //=== This program is distributed in the hope that it will be useful, but
012: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
013: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: //=== General Public License for more details.
015: //===
016: //=== You should have received a copy of the GNU General Public License
017: //=== along with this program; if not, write to the Free Software
018: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
019: //===
020: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
021: //=== Rome - Italy. email: geonetwork@osgeo.org
022: //==============================================================================
023:
024: package org.fao.geonet.services.thumbnail;
025:
026: import java.awt.Graphics2D;
027: import java.awt.Image;
028: import java.awt.image.BufferedImage;
029: import java.io.File;
030: import java.io.FileInputStream;
031: import java.io.IOException;
032: import javax.imageio.ImageIO;
033: import jeeves.interfaces.Service;
034: import jeeves.resources.dbms.Dbms;
035: import jeeves.server.ServiceConfig;
036: import jeeves.server.context.ServiceContext;
037: import jeeves.utils.Util;
038: import lizard.tiff.Tiff;
039: import org.fao.geonet.GeonetContext;
040: import org.fao.geonet.constants.Geonet;
041: import org.fao.geonet.constants.Params;
042: import org.fao.geonet.exceptions.ConcurrentUpdateEx;
043: import org.fao.geonet.kernel.DataManager;
044: import org.fao.geonet.lib.Lib;
045: import org.jdom.Element;
046:
047: //=============================================================================
048:
049: public class Set implements Service {
050: //--------------------------------------------------------------------------
051: //---
052: //--- Init
053: //---
054: //--------------------------------------------------------------------------
055:
056: public void init(String appPath, ServiceConfig params)
057: throws Exception {
058: }
059:
060: //--------------------------------------------------------------------------
061: //---
062: //--- Service
063: //---
064: //--------------------------------------------------------------------------
065:
066: public Element exec(Element params, ServiceContext context)
067: throws Exception {
068: String id = Util.getParam(params, Params.ID);
069: String type = Util.getParam(params, Params.TYPE);
070: String version = Util.getParam(params, Params.VERSION);
071: String file = Util.getParam(params, Params.FNAME);
072: String scalingDir = Util.getParam(params, Params.SCALING_DIR);
073: boolean scaling = Util.getParam(params, Params.SCALING, false);
074: int scalingFactor = Util.getParamAsInt(params,
075: Params.SCALING_FACTOR);
076:
077: boolean createSmall = Util.getParam(params,
078: Params.CREATE_SMALL, false);
079: String smallScalingDir = Util.getParam(params,
080: Params.SMALL_SCALING_DIR, "");
081: int smallScalingFactor = Util.getParam(params,
082: Params.SMALL_SCALING_FACTOR, 0);
083:
084: Lib.resource.checkEditPrivilege(context, id);
085:
086: //-----------------------------------------------------------------------
087: //--- environment vars
088:
089: GeonetContext gc = (GeonetContext) context
090: .getHandlerContext(Geonet.CONTEXT_NAME);
091:
092: DataManager dataMan = gc.getDataManager();
093:
094: Dbms dbms = (Dbms) context.getResourceManager().open(
095: Geonet.Res.MAIN_DB);
096:
097: //--- check if the metadata has been modified from last time
098:
099: if (version != null && !dataMan.getVersion(id).equals(version))
100: throw new ConcurrentUpdateEx(id);
101:
102: //-----------------------------------------------------------------------
103: //--- create destination directory
104:
105: String dataDir = Lib.resource.getDir(context,
106: Params.Access.PUBLIC, id);
107:
108: new File(dataDir).mkdirs();
109:
110: //-----------------------------------------------------------------------
111: //--- create the small thumbnail, removing the old one
112:
113: if (createSmall) {
114: String smallFile = getFileName(file, true);
115: String inFile = context.getUploadDir() + file;
116: String outFile = dataDir + smallFile;
117:
118: removeOldThumbnail(context, id, "small");
119: createThumbnail(inFile, outFile, smallScalingFactor,
120: smallScalingDir);
121: dataMan.setThumbnail(dbms, id, true, smallFile);
122: }
123:
124: //-----------------------------------------------------------------------
125: //--- create the requested thumbnail, removing the old one
126:
127: removeOldThumbnail(context, id, type);
128:
129: if (scaling) {
130: String newFile = getFileName(file, type.equals("small"));
131: String inFile = context.getUploadDir() + file;
132: String outFile = dataDir + newFile;
133:
134: createThumbnail(inFile, outFile, scalingFactor, scalingDir);
135:
136: if (!new File(inFile).delete())
137: context.error("Error while deleting thumbnail : "
138: + inFile);
139:
140: dataMan.setThumbnail(dbms, id, type.equals("small"),
141: newFile);
142: } else {
143: //--- move uploaded file to destination directory
144:
145: File inFile = new File(context.getUploadDir(), file);
146: File outFile = new File(dataDir, file);
147:
148: if (!inFile.renameTo(outFile)) {
149: inFile.delete();
150: throw new Exception(
151: "unable to move uploaded thumbnail to destination directory");
152: }
153:
154: dataMan.setThumbnail(dbms, id, type.equals("small"), file);
155: }
156:
157: //-----------------------------------------------------------------------
158:
159: Element response = new Element("a");
160: response.addContent(new Element("id").setText(id));
161: response.addContent(new Element("version").setText(dataMan
162: .getNewVersion(id)));
163:
164: return response;
165: }
166:
167: //--------------------------------------------------------------------------
168: //---
169: //--- Private methods
170: //---
171: //--------------------------------------------------------------------------
172:
173: private void removeOldThumbnail(ServiceContext context, String id,
174: String type) throws Exception {
175: GeonetContext gc = (GeonetContext) context
176: .getHandlerContext(Geonet.CONTEXT_NAME);
177:
178: DataManager dataMan = gc.getDataManager();
179:
180: Dbms dbms = (Dbms) context.getResourceManager().open(
181: Geonet.Res.MAIN_DB);
182:
183: Element result = dataMan.getThumbnails(dbms, id);
184:
185: if (result == null)
186: throw new IllegalArgumentException(
187: "Metadata not found --> " + id);
188:
189: result = result.getChild(type);
190:
191: //--- if there is no thumbnail, we return
192:
193: if (result == null)
194: return;
195:
196: //-----------------------------------------------------------------------
197: //--- remove thumbnail
198:
199: dataMan.unsetThumbnail(dbms, id, type.equals("small"));
200:
201: //--- remove file
202:
203: String file = Lib.resource.getDir(context,
204: Params.Access.PUBLIC, id)
205: + result.getText();
206:
207: if (!new File(file).delete())
208: context.error("Error while deleting thumbnail : " + file);
209: }
210:
211: //--------------------------------------------------------------------------
212:
213: private void createThumbnail(String inFile, String outFile,
214: int scalingFactor, String scalingDir) throws IOException {
215: BufferedImage origImg = getImage(inFile);
216:
217: int imgWidth = origImg.getWidth();
218: int imgHeight = origImg.getHeight();
219:
220: int width;
221: int height;
222:
223: if (scalingDir.equals("width")) {
224: width = scalingFactor;
225: height = width * imgHeight / imgWidth;
226: } else {
227: height = scalingFactor;
228: width = height * imgWidth / imgHeight;
229: }
230:
231: Image thumb = origImg.getScaledInstance(width, height,
232: BufferedImage.SCALE_SMOOTH);
233:
234: BufferedImage bimg = new BufferedImage(width, height,
235: BufferedImage.TYPE_3BYTE_BGR);
236:
237: Graphics2D g = bimg.createGraphics();
238: g.drawImage(thumb, 0, 0, null);
239: g.dispose();
240:
241: ImageIO.write(bimg, IMAGE_TYPE, new File(outFile));
242: }
243:
244: //--------------------------------------------------------------------------
245:
246: private String getFileName(String file, boolean small) {
247: int pos = file.lastIndexOf(".");
248:
249: if (pos != -1)
250: file = file.substring(0, pos);
251:
252: return small ? file + SMALL_SUFFIX + "." + IMAGE_TYPE : file
253: + "." + IMAGE_TYPE;
254: }
255:
256: //--------------------------------------------------------------------------
257:
258: public BufferedImage getImage(String inFile) throws IOException {
259: String lcFile = inFile.toLowerCase();
260:
261: if (lcFile.endsWith(".tif") || lcFile.endsWith(".tiff")) {
262: //--- load the TIFF/GEOTIFF file format
263:
264: Image image = getTiffImage(inFile);
265:
266: int width = image.getWidth(null);
267: int height = image.getHeight(null);
268:
269: BufferedImage bimg = new BufferedImage(width, height,
270: BufferedImage.TYPE_3BYTE_BGR);
271: Graphics2D g = bimg.createGraphics();
272: g.drawImage(image, 0, 0, null);
273: g.dispose();
274:
275: return bimg;
276: }
277:
278: return ImageIO.read(new File(inFile));
279: }
280:
281: //--------------------------------------------------------------------------
282:
283: private Image getTiffImage(String inFile) throws IOException {
284: Tiff t = new Tiff();
285: t.readInputStream(new FileInputStream(inFile));
286:
287: if (t.getPageCount() == 0)
288: throw new IOException("No images inside TIFF file");
289:
290: return t.getImage(0);
291: }
292:
293: //--------------------------------------------------------------------------
294: //---
295: //--- Variables
296: //---
297: //--------------------------------------------------------------------------
298:
299: private static final String IMAGE_TYPE = "png";
300: private static final String SMALL_SUFFIX = "_s";
301:
302: }
303:
304: //=============================================================================
|