/* * #%L * ACS AEM Commons Bundle * %% * Copyright (C) 2013 - 2015 Adobe * %% * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * 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. * #L% */ package com.adobe.acs.commons.http.headers.impl; import org.apache.commons.lang3.StringUtils; import org.apache.sling.commons.osgi.PropertiesUtil; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.component.ComponentContext; import javax.servlet.http.HttpServletRequest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Dictionary; import java.util.Enumeration; import java.util.TimeZone; /** * Provides standard functionality to specify an Expires header for Dispatcher Cache rules. */ public abstract class AbstractExpiresHeaderFilter extends AbstractDispatcherCacheHeaderFilter { protected static final String EXPIRES_NAME = "Expires"; protected static final String EXPIRES_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z"; public static final String PROP_EXPIRES_TIME = "expires.time"; // Placeholder for the values needed. private Calendar expiresTime = Calendar.getInstance(); /** * Sublcass implementations will adjust the date of the specified calendar to the * next point at which content should expire. * * The calendar passed will be the set to the correct time the current day. * Concrete implementations are required to update the Calendar to the correct <i>next</i> expiration time. * * @param nextExpiration a {@link Calendar} to adjust to next expiration date. */ protected abstract void adjustExpires(Calendar nextExpiration); @Override protected String getHeaderName() { return EXPIRES_NAME; } @Override protected String getHeaderValue() { Calendar next = Calendar.getInstance(); next.set(Calendar.HOUR_OF_DAY, expiresTime.get(Calendar.HOUR_OF_DAY)); next.set(Calendar.MINUTE, expiresTime.get(Calendar.MINUTE)); next.set(Calendar.SECOND, 0); adjustExpires(next); SimpleDateFormat dateFormat = new SimpleDateFormat(EXPIRES_FORMAT); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); return dateFormat.format(next.getTime()); } @Override @SuppressWarnings("unchecked") protected boolean accepts(HttpServletRequest request) { if (super.accepts(request)) { Enumeration<String> expiresheaders = request.getHeaders(EXPIRES_NAME); return expiresheaders == null || !expiresheaders.hasMoreElements(); } return false; } @Override protected void doActivate(ComponentContext context) throws Exception { Dictionary<?, ?> properties = context.getProperties(); String time = PropertiesUtil.toString(properties.get(PROP_EXPIRES_TIME), null); if (StringUtils.isBlank(time)) { throw new ConfigurationException(PROP_EXPIRES_TIME, "Expires Time must be specified."); } SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); sdf.setLenient(false); try { Date date = sdf.parse(time); expiresTime.setTime(date); } catch (ParseException ex) { throw new ConfigurationException(PROP_EXPIRES_TIME, "Expires Time must be specified."); } } public String toString() { return this.getClass().getName() + "[" + getHeaderValue() + "]"; } }