/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License * at: * * http://opensource.org/licenses/ecl2.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.opencastproject.coverimage.impl; import org.opencastproject.security.api.OrganizationDirectoryService; import org.opencastproject.security.api.SecurityService; import org.opencastproject.security.api.UserDirectoryService; import org.opencastproject.serviceregistry.api.ServiceRegistry; import org.opencastproject.workspace.api.Workspace; import org.apache.batik.ext.awt.image.GraphicsUtil; import org.apache.batik.ext.awt.image.codec.jpeg.JPEGRegistryEntry; import org.apache.batik.ext.awt.image.renderable.DeferRable; import org.apache.batik.ext.awt.image.renderable.Filter; import org.apache.batik.ext.awt.image.renderable.RedRable; import org.apache.batik.ext.awt.image.rendered.Any2sRGBRed; import org.apache.batik.ext.awt.image.rendered.CachableRed; import org.apache.batik.ext.awt.image.rendered.FormatRed; import org.apache.batik.ext.awt.image.spi.ImageTagRegistry; import org.apache.batik.util.ParsedURL; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; /** * Implementation of {@link AbstractCoverImageService} for use in OSGi environment */ public class CoverImageServiceOsgiImpl extends AbstractCoverImageService { /** The logging facility */ private static final Logger logger = LoggerFactory.getLogger(CoverImageServiceOsgiImpl.class); /** * OSGi activation callback * * @param cc * the OSGi component context */ @Override public void activate(ComponentContext cc) { super.activate(cc); // See // http://www.stichlberger.com/software/workaround-for-batiks-noclassdeffounderrorclassnotfoundexception-truncatedfileexception/ // --------------- // add this code before you use batik (make sure is runs only once) // via the lower priority this subclass is registered before JPEGRegistryEntry // and prevents JPEGRegistryEntry.handleStream from breaking when used on a non Sun/Oracle JDK JPEGRegistryEntry entry = new JPEGRegistryEntry() { @Override public float getPriority() { // higher than that of JPEGRegistryEntry (which is 1000) return 500; } /** * Decode the Stream into a RenderableImage * * @param inIS * The input stream that contains the image. * @param origURL * The original URL, if any, for documentation purposes only. This may be null. * @param needRawData * If true the image returned should not have any default color correction the file may specify applied. */ @Override public Filter handleStream(InputStream inIS, ParsedURL origURL, boolean needRawData) { // Code from org.apache.batik.ext.awt.image.codec.jpeg.JPEGRegistryEntry#handleStream // Reading image with ImageIO to prevent NoClassDefFoundError on OpenJDK final DeferRable dr = new DeferRable(); final InputStream is = inIS; final String errCode; final Object[] errParam; if (origURL != null) { errCode = ERR_URL_FORMAT_UNREADABLE; errParam = new Object[] { "JPEG", origURL }; } else { errCode = ERR_STREAM_FORMAT_UNREADABLE; errParam = new Object[] { "JPEG" }; } Thread t = new Thread() { @Override public void run() { Filter filt; try { BufferedImage image; image = ImageIO.read(is); dr.setBounds(new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight())); CachableRed cr; cr = GraphicsUtil.wrap(image); cr = new Any2sRGBRed(cr); cr = new FormatRed(cr, GraphicsUtil.sRGB_Unpre); WritableRaster wr = (WritableRaster) cr.getData(); ColorModel cm = cr.getColorModel(); image = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null); cr = GraphicsUtil.wrap(image); filt = new RedRable(cr); } catch (IOException ioe) { // Something bad happened here... filt = ImageTagRegistry.getBrokenLinkImage(this, errCode, errParam); } catch (ThreadDeath td) { filt = ImageTagRegistry.getBrokenLinkImage(this, errCode, errParam); dr.setSource(filt); throw td; } catch (Throwable t) { filt = ImageTagRegistry.getBrokenLinkImage(this, errCode, errParam); } dr.setSource(filt); } }; t.start(); return dr; } }; ImageTagRegistry.getRegistry().register(entry); logger.info("Cover image service activated"); } /** * OSGi callback to set the workspace service. * * @param workspace * the workspace service */ protected void setWorkspace(Workspace workspace) { this.workspace = workspace; } /** * OSGi callback to set the service registry service * * @param serviceRegistry * the service registry service */ protected void setServiceRegistry(ServiceRegistry serviceRegistry) { this.serviceRegistry = serviceRegistry; } /** * OSGi callback to set the security service * * @param securityService * the security service */ protected void setSecurityService(SecurityService securityService) { this.securityService = securityService; } /** * OSGi callback to set the user directory service * * @param userDirectoryService * the user directory service */ protected void setUserDirectoryService(UserDirectoryService userDirectoryService) { this.userDirectoryService = userDirectoryService; } /** * OSGi callback to set the organization directory service * * @param organizationDirectoryService * the organization directory service */ protected void setOrganizationDirectoryService(OrganizationDirectoryService organizationDirectoryService) { this.organizationDirectoryService = organizationDirectoryService; } @Override protected ServiceRegistry getServiceRegistry() { return serviceRegistry; } @Override protected SecurityService getSecurityService() { return securityService; } @Override protected UserDirectoryService getUserDirectoryService() { return userDirectoryService; } @Override protected OrganizationDirectoryService getOrganizationDirectoryService() { return organizationDirectoryService; } }