001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.scheduler.jobs; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsPropertyDefinition; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.file.types.CmsResourceTypeImage; 037import org.opencms.loader.CmsImageLoader; 038import org.opencms.loader.CmsImageScaler; 039import org.opencms.lock.CmsLock; 040import org.opencms.main.CmsException; 041import org.opencms.main.OpenCms; 042import org.opencms.report.CmsLogReport; 043import org.opencms.report.I_CmsReport; 044import org.opencms.scheduler.I_CmsScheduledJob; 045 046import java.util.Collections; 047import java.util.List; 048import java.util.Map; 049 050/** 051 * A schedulable OpenCms job to calculate image size information.<p> 052 * 053 * Image size information is stored in the <code>{@link CmsPropertyDefinition#PROPERTY_IMAGE_SIZE}</code> property 054 * of an image file must have the format "h:x,w:y" with x and y being positive Integer vaulues.<p> 055 * 056 * Job parameters:<p> 057 * <dl> 058 * <dt><code>downscale=true|false</code></dt> 059 * <dd>Controls if images are automatically downscaled according to the configured image 060 * downscale settings, by default this is <code>false</code>.</dd> 061 * </dl> 062 * 063 * @since 6.0.2 064 */ 065public class CmsCreateImageSizeJob implements I_CmsScheduledJob { 066 067 /** 068 * This job parameter controls if images are automatically downscaled according to the configured image 069 * downscale settings, by default this is <code>false</code>. 070 * 071 * Possible values are <code>true</code> or <code>false</code> (default). 072 * If this is set to <code>true</code>, then all images are checked against the 073 * configured image downscale settings (see {@link CmsImageLoader#CONFIGURATION_DOWNSCALE}). 074 * If the image is too large, it is automatically downscaled.<p> 075 */ 076 public static final String PARAM_DOWNSCALE = "downscale"; 077 078 /** 079 * @see org.opencms.scheduler.I_CmsScheduledJob#launch(CmsObject, Map) 080 */ 081 public String launch(CmsObject cms, Map<String, String> parameters) throws Exception { 082 083 if (!CmsImageLoader.isEnabled()) { 084 // scaling functions are not available 085 return Messages.get().getBundle().key(Messages.LOG_IMAGE_SCALING_DISABLED_0); 086 } 087 088 // read the downscale parameter 089 boolean downscale = Boolean.valueOf(parameters.get(PARAM_DOWNSCALE)).booleanValue(); 090 091 I_CmsReport report = new CmsLogReport(cms.getRequestContext().getLocale(), CmsCreateImageSizeJob.class); 092 report.println(Messages.get().container(Messages.RPT_IMAGE_SIZE_START_0), I_CmsReport.FORMAT_HEADLINE); 093 094 List<CmsResource> resources = Collections.emptyList(); 095 try { 096 // get all image resources 097 resources = cms.readResources( 098 "/", 099 CmsResourceFilter.IGNORE_EXPIRATION.addRequireType( 100 OpenCms.getResourceManager().getResourceType( 101 CmsResourceTypeImage.getStaticTypeName()).getTypeId())); 102 } catch (CmsException e) { 103 report.println(e); 104 } 105 106 int count = 0; 107 // now iterate through all resources 108 for (int i = 0; i < resources.size(); i++) { 109 110 try { 111 112 CmsResource res = resources.get(i); 113 report.print( 114 Messages.get().container( 115 Messages.RPT_IMAGE_SIZE_PROCESS_3, 116 String.valueOf(i + 1), 117 String.valueOf(resources.size()), 118 res.getRootPath()), 119 I_CmsReport.FORMAT_HEADLINE); 120 121 report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 122 123 // check if the resource is locked by another user 124 // we cannot process resources that are locked by someone else 125 CmsLock lock = cms.getLock(res); 126 if (lock.isNullLock() || lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { 127 128 // read the file content 129 CmsFile file = cms.readFile(res); 130 // get the image size information 131 CmsImageScaler scaler = new CmsImageScaler(file.getContents(), file.getRootPath()); 132 133 if (scaler.isValid()) { 134 // the image can be scaled, width and height are known 135 boolean updated = false; 136 137 // check if the image must be downscaled 138 CmsImageScaler downScaler = null; 139 if (downscale) { 140 // scheduled job parameter is set for downscaling 141 downScaler = CmsResourceTypeImage.getDownScaler(cms, res.getRootPath()); 142 } 143 144 if (scaler.isDownScaleRequired(downScaler)) { 145 // downscaling is required - just write the file again, in this case everything is updated 146 lockResource(cms, lock, res); 147 cms.writeFile(file); 148 // calculate the downscaled image size (only used for the output report) 149 scaler = scaler.getDownScaler(downScaler); 150 // the resource was updated 151 updated = true; 152 } else { 153 // check if the "image.size" property must be updated 154 CmsProperty prop = cms.readPropertyObject( 155 res, 156 CmsPropertyDefinition.PROPERTY_IMAGE_SIZE, 157 false); 158 // update the property if it does not exist or it is different than the newly calculated one 159 if (prop.isNullProperty() || !prop.getValue().equals(scaler.toString())) { 160 // lock resource 161 lockResource(cms, lock, res); 162 // set the shared value of the property or create a new one if required 163 if (prop.isNullProperty()) { 164 prop = new CmsProperty( 165 CmsPropertyDefinition.PROPERTY_IMAGE_SIZE, 166 null, 167 scaler.toString()); 168 } else { 169 // delete any individual proprety value (just in case) 170 prop.setStructureValue(CmsProperty.DELETE_VALUE); 171 // set the calculated value as shared property 172 prop.setResourceValue(scaler.toString()); 173 } 174 // write the property 175 cms.writePropertyObject(res.getRootPath(), prop); 176 // the resource was updated 177 updated = true; 178 } 179 } 180 181 if (updated) { 182 // the resource was updated 183 unlockResource(cms, lock, res); 184 // increase counter 185 count++; 186 // write report information 187 report.println( 188 Messages.get().container(Messages.RPT_IMAGE_SIZE_UPDATE_1, scaler.toString()), 189 I_CmsReport.FORMAT_DEFAULT); 190 191 } else { 192 // no changes have been made to the resource 193 report.println( 194 Messages.get().container(Messages.RPT_IMAGE_SIZE_SKIP_1, scaler.toString()), 195 I_CmsReport.FORMAT_DEFAULT); 196 } 197 } else { 198 // no valid image scaler 199 report.println( 200 Messages.get().container(Messages.RPT_IMAGE_SIZE_UNABLE_TO_CALCULATE_0), 201 I_CmsReport.FORMAT_DEFAULT); 202 } 203 } else { 204 // the resource is locked by someone else 205 report.println( 206 Messages.get().container(Messages.RPT_IMAGE_SIZE_LOCKED_0), 207 I_CmsReport.FORMAT_DEFAULT); 208 } 209 } catch (CmsException e) { 210 report.println(e); 211 } 212 } 213 214 report.println(Messages.get().container(Messages.RPT_IMAGE_SIZE_END_0), I_CmsReport.FORMAT_HEADLINE); 215 216 return Messages.get().getBundle().key(Messages.LOG_IMAGE_SIZE_UPDATE_COUNT_1, Integer.valueOf(count)); 217 } 218 219 /** 220 * Locks the given resource (if required).<p> 221 * 222 * @param cms the OpenCms user context 223 * @param lock the previous lock status of the resource 224 * @param res the resource to lock 225 * 226 * @throws CmsException in case something goes wrong 227 */ 228 private void lockResource(CmsObject cms, CmsLock lock, CmsResource res) throws CmsException { 229 230 if (lock.isNullLock()) { 231 cms.lockResource(res.getRootPath()); 232 } 233 } 234 235 /** 236 * Unlocks the given resource (if required).<p> 237 * 238 * @param cms the OpenCms user context 239 * @param lock the lock of the resource 240 * @param res the resource to lock 241 * 242 * @throws CmsException in case something goes wrong 243 */ 244 private void unlockResource(CmsObject cms, CmsLock lock, CmsResource res) throws CmsException { 245 246 if (lock.isNullLock()) { 247 cms.unlockResource(res.getRootPath()); 248 } 249 } 250}