/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.web;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.ImageIcon;
import org.onecmdb.core.ICi;
import org.onecmdb.core.IOneCmdbContext;
import org.onecmdb.core.ISession;
import org.onecmdb.core.internal.model.ItemId;
import org.springframework.core.io.FileSystemResource;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.support.ServletContextResource;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
public class IconGenerator extends MultiActionController {
private static String[] exts = { ".gif", ".png", ".jpg", ".jpeg" };
private SiteController siteController;
/** location holding an image repository */
private String imageDirectory = "/WEB-INF/jsp/images";
// {{{ bean support
/**
* WARNING: Used to satisfy spring only
*/
public void setSiteController(SiteController site) {
this.siteController = site;
}
public SiteController getSiteController() {
return this.siteController;
}
public void init() {
if (getSiteController() == null) {
throw new IllegalStateException("No SiteController set!");
}
if (imageDirectory == null) {
throw new IllegalStateException("No image directory specified!");
}
if (!imageDirectory.endsWith("/")) {
imageDirectory += "/";
}
}
// }}}
public ModelAndView generateHandler(HttpServletRequest request,
HttpServletResponse respone, IconCommand iconCommand) throws MalformedURLException {
/*
ISession session = getSiteController().getSiteCommand(request).getSession();
ServletRequestDataBinder binder = new ServletRequestDataBinder(iconCommand);
binder.registerCustomEditor(ItemId.class, new ItemIdEditor());
binder.registerCustomEditor(ICi.class, new ItemEditor(session));
binder.registerCustomEditor(IconSize.class, new IconSizeEditor());
binder.bind(request);
*/
String base = iconCommand.getIconid();
if (base == null) {
base = iconCommand.getIconFile();
}
if (base == null || "".equals(base)) {
base = "unknown";
}
String iconSpec = null;
if (!ResourceUtils.isUrl(base)) {
ServletContext ctx = getServletContext();
int intSize = 16;
if (iconCommand.getSize() == null ||
iconCommand.getSize() == IconSize.SMALL ) {
intSize = 16;
} else if (iconCommand.getSize() == IconSize.MEDIUM) {
intSize = 32;
} else if (iconCommand.getSize() == IconSize.LARGE) {
intSize = 48;
}
URL res = null;
for (int i = 0; res == null && i < exts.length; i++) {
iconSpec = this.imageDirectory + base + intSize + exts[i];
res = ctx.getResource(iconSpec);
}
if (res == null) {
return null;
}
} else {
}
Map<String, String> data = new HashMap<String, String>();
data.put("file", iconSpec);
return new ModelAndView("image", "image", data);
}
private Map<String, List<Image>> getImageMap() throws IOException {
ServletContextResource imagesRes
= new ServletContextResource(getServletContext(), this.imageDirectory);
File imagesFile = imagesRes.getFile();
final Map<String, List<Image>> images = new TreeMap<String, List<Image>>();
File[] imageFiles = imagesFile.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
FileSystemResource file = new FileSystemResource(new File(dir, name));
for (String ext : exts) {
if (name.toLowerCase().endsWith(ext)) {
try {
BufferedImage img = ImageIO.read(file.getFile());
String key = name.substring(0, name.length() - ext.length());
key = name.substring(0, key.length() - 2);
List<Image> imageList = images.get(key);
if (imageList == null) {
imageList = new ArrayList<Image>(1);
images.put(key, imageList);
}
imageList.add(img);
return true;
} catch (IOException e) {
return false;
}
}
}
return false;
}});
return images;
}
public ModelAndView listHandler(HttpServletRequest request,
HttpServletResponse respone, IconCommand iconCommand) throws IOException {
Map<String, Object> data = new HashMap<String, Object>();
Map<String, List<Image>> images = getImageMap();
data.put("images", images);
return new ModelAndView("imageList", "data", data);
}
public ModelAndView optionsHandler(HttpServletRequest request,
HttpServletResponse respone, IconOptionsCommand optionsCommand) throws IOException {
ISession session = getSiteController().getSiteCommand(request).getSession();
ServletRequestDataBinder binder = new ServletRequestDataBinder(optionsCommand);
binder.registerCustomEditor(ItemId.class, new ItemIdEditor());
binder.registerCustomEditor(ICi.class, new ItemEditor(session));
binder.registerCustomEditor(IconSize.class, new IconSizeEditor());
binder.bind(request);
Map<String, Object> data = new HashMap<String, Object>();
Map<String, List<Image>> images = getImageMap();
data.put("images", images);
data.put("selected", optionsCommand.getSelected());
return new ModelAndView("imageOptions", "data", data);
}
@Override
protected void initBinder(ServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
}
public ModelAndView addHandler(HttpServletRequest request,
HttpServletResponse respone, IconOptionsCommand optionsCommand) throws IOException {
HashMap<String, Object> data = new HashMap<String, Object>();
ServletContextResource depot
= new ServletContextResource(getServletContext(), this.imageDirectory);
String imageid = optionsCommand.getIconid();
if (imageid != null) {
final ByteArrayInputStream in = new ByteArrayInputStream(optionsCommand.getIconData());
final BufferedImage image = ImageIO.read(in);
for (double f = 16.0; f <= 48.0; f += 16)
{
Image scaled = image.getScaledInstance((int) f, (int) f, java.awt.Image.SCALE_AREA_AVERAGING);
BufferedImage scaledImage = toBufferedImage(scaled);
final File file = new File(depot.getFile(), imageid + ((int) f) + ".png");
ImageIO.write(scaledImage, "png", file);
}
data.put("successful", true);
}
return new ModelAndView("imageAdd", "imageAdd", data);
}
// This method returns a buffered image with the contents of an image
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage)image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
// Determine if the image has transparent pixels; for this method's
// implementation, see e661 Determining If an Image Has Transparent Pixels
boolean hasAlpha = hasAlpha(image);
// Create a buffered image with a format that's compatible with the screen
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = Transparency.OPAQUE;
if (hasAlpha) {
transparency = Transparency.BITMASK;
}
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(
image.getWidth(null), image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
if (hasAlpha) {
type = BufferedImage.TYPE_INT_ARGB;
}
bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
// This method returns true if the specified image has transparent pixels
public static boolean hasAlpha(Image image) {
// If buffered image, the color model is readily available
if (image instanceof BufferedImage) {
BufferedImage bimage = (BufferedImage)image;
return bimage.getColorModel().hasAlpha();
}
// Use a pixel grabber to retrieve the image's color model;
// grabbing a single pixel is usually sufficient
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
// Get the image's color model
ColorModel cm = pg.getColorModel();
return cm.hasAlpha();
}
}