/**
* This file is part of Faktotum.
*
*
* Faktotum is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Faktotum 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Faktotum.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
package de.romankreisel.faktotum.beans;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import de.romankreisel.faktotum.beans.CryptBean.AUTHENTICATION_SCHEME;
import de.romankreisel.faktotum.dao.BundesbruderDao;
import de.romankreisel.faktotum.datamodel.BundesbruderEntity;
import de.romankreisel.faktotum.exceptions.FaktotumRuntimeException;
import de.romankreisel.faktotum.exceptions.InvalidPasswordException;
/**
* @author Roman Kreisel <mail@romankreisel.de>
*
*/
@Stateless
public class BundesbruderBean extends FaktotumBean {
@EJB
private SettingBean settingBean;
@EJB
private CryptBean cryptBean;
@EJB
private BundesbruderDao bundesbruderDao;
/**
* Encrypts a password and stores it for a BundesbruderEntity.
*
* @param bundesbruderEntity
* The Bundesbruder to have the new password set
* @param password
* the password to be hashed and stored
* @throws InvalidPasswordException
* If the password is not valid and must not be used
*/
public void encryptAndSetPassword(BundesbruderEntity bundesbruderEntity, String password) throws InvalidPasswordException {
AUTHENTICATION_SCHEME authenticationScheme = (AUTHENTICATION_SCHEME) this.settingBean.getEnumSettingValue(SettingBean.SETTING_STRING_AUTH_SCHEME);
if (password.isEmpty()) {
throw new InvalidPasswordException("Empty password not allowed, reset user to disable access!");
}
String passwordToken = this.cryptBean.crypt(password, authenticationScheme);
if (StringUtils.isEmpty(passwordToken)) {
throw new FaktotumRuntimeException("Error generating token for password!");
}
bundesbruderEntity.setPassword(passwordToken);
}
/**
* @return
*/
public Long getBundesbruderCount() {
return this.bundesbruderDao.getCount(BundesbruderEntity.class);
}
public BufferedImage getImageFromByteArray(byte[] array) throws IOException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(array);
BufferedImage originalImage = ImageIO.read(byteArrayInputStream);
byteArrayInputStream.close();
return originalImage;
}
public BufferedImage getImageFromByteArray(Byte[] array) throws IOException {
byte[] primitiveArray = ArrayUtils.toPrimitive(array);
return this.getImageFromByteArray(primitiveArray);
}
/**
* Calculates the size of a downscaled image, keeping the aspect ratio
* http:/
* /stackoverflow.com/questions/10245220/java-image-resize-maintain-aspect
* -ratio
*
* @param imageSize
* @param boundary
* @return the scaled dimension
*/
private Dimension getScaledDimension(Dimension imageSize, Dimension boundary) {
int originalWidth = imageSize.width;
int originalHeight = imageSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int newWidth = originalWidth;
int newWeight = originalHeight;
// first check if we need to scale width
if (originalWidth > bound_width) {
// scale width to fit
newWidth = bound_width;
// scale height to maintain aspect ratio
newWeight = newWidth * originalHeight / originalWidth;
}
// then check if we need to scale even with the new height
if (newWeight > bound_height) {
// scale height to fit instead
newWeight = bound_height;
// scale width to maintain aspect ratio
newWidth = newWeight * originalWidth / originalHeight;
}
return new Dimension(newWidth, newWeight);
}
/**
* @param originalPicture
* @param pictureHeight
* @param pictureWidth
* @return
* @throws IOException
*/
public Byte[] resizeProfilePicture(Byte[] originalPicture, int width, int height) throws IOException {
BufferedImage originalImage = this.getImageFromByteArray(originalPicture);
Dimension newDimension = this.getScaledDimension(new Dimension(originalImage.getWidth(), originalImage.getHeight()), new Dimension(width, height));
Image scaledImage = originalImage.getScaledInstance(newDimension.width, newDimension.height, Image.SCALE_SMOOTH);
return this.storeImageToByteArray(scaledImage);
}
public void rotateProfilePictureClockwise(BundesbruderEntity bundesbruder, double angle) throws IOException {
BufferedImage image = this.getImageFromByteArray(bundesbruder.getPictureOriginal());
double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
int w = image.getWidth(), h = image.getHeight();
int neww = (int) Math.floor(w * cos + h * sin), newh = (int) Math.floor(h * cos + w * sin);
GraphicsConfiguration gc = image.createGraphics().getDeviceConfiguration();
BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT);
Graphics2D g = result.createGraphics();
g.translate((neww - w) / 2, (newh - h) / 2);
g.rotate(angle, w / 2, h / 2);
g.drawRenderedImage(image, null);
g.dispose();
this.setProfilePicture(bundesbruder, this.storeImageToByteArray(image));
}
public void setProfilePicture(BundesbruderEntity bundesbruder, Byte[] originalPicture) throws IOException {
// TODO: configurable?
int pictureHeight = 300;
int pictureWidth = 200;
int thumbnailHeight = 60;
int thumbnailWidth = 40;
Byte[] picture = this.resizeProfilePicture(originalPicture, pictureHeight, pictureWidth);
Byte[] thumbnail = this.resizeProfilePicture(originalPicture, thumbnailHeight, thumbnailWidth);
bundesbruder.setPictureOriginal(originalPicture);
bundesbruder.setPicture(picture);
bundesbruder.setPictureThumbnail(thumbnail);
}
private Byte[] storeImageToByteArray(Image image) throws IOException {
if (!(image instanceof RenderedImage)) {
BufferedImage newImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
newImage.getGraphics().drawImage(image, 0, 0, null);
image = newImage;
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write((RenderedImage) image, "jpg", byteArrayOutputStream);
byteArrayOutputStream.flush();
byte[] imageInByte = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return ArrayUtils.toObject(imageInByte);
}
}