src/net/fortuna/ical4j/model/TimeZoneRegistryImpl.java

Tue, 10 Feb 2015 19:58:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 10 Feb 2015 19:58:00 +0100
changeset 4
45d57ecba757
parent 0
fb9019fb1bf7
child 5
e0e108e77052
permissions
-rw-r--r--

Upgrade the upgraded ical4j component to use org.apache.commons.lang3.

     1 /**
     2  * Copyright (c) 2012, Ben Fortuna
     3  * All rights reserved.
     4  *
     5  * Redistribution and use in source and binary forms, with or without
     6  * modification, are permitted provided that the following conditions
     7  * are met:
     8  *
     9  *  o Redistributions of source code must retain the above copyright
    10  * notice, this list of conditions and the following disclaimer.
    11  *
    12  *  o Redistributions in binary form must reproduce the above copyright
    13  * notice, this list of conditions and the following disclaimer in the
    14  * documentation and/or other materials provided with the distribution.
    15  *
    16  *  o Neither the name of Ben Fortuna nor the names of any other contributors
    17  * may be used to endorse or promote products derived from this software
    18  * without specific prior written permission.
    19  *
    20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  */
    32 package net.fortuna.ical4j.model;
    34 import java.io.IOException;
    35 import java.net.URL;
    36 import java.util.Map;
    37 import java.util.Properties;
    38 import java.util.regex.Matcher;
    39 import java.util.regex.Pattern;
    41 import net.fortuna.ical4j.data.CalendarBuilder;
    42 import net.fortuna.ical4j.data.ParserException;
    43 import net.fortuna.ical4j.model.component.VTimeZone;
    44 import net.fortuna.ical4j.model.property.TzUrl;
    45 import net.fortuna.ical4j.util.CompatibilityHints;
    46 import net.fortuna.ical4j.util.Configurator;
    47 import net.fortuna.ical4j.util.ResourceLoader;
    49 import org.apache.commons.logging.Log;
    50 import org.apache.commons.logging.LogFactory;
    52 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
    54 /**
    55  * $Id$
    56  *
    57  * Created on 18/09/2005
    58  *
    59  * The default implementation of a <code>TimeZoneRegistry</code>. This implementation will search the classpath for
    60  * applicable VTimeZone definitions used to back the provided TimeZone instances.
    61  * @author Ben Fortuna
    62  */
    63 public class TimeZoneRegistryImpl implements TimeZoneRegistry {
    65     private static final String DEFAULT_RESOURCE_PREFIX = "zoneinfo/";
    67     private static final Pattern TZ_ID_SUFFIX = Pattern.compile("(?<=/)[^/]*/[^/]*$");
    69     private static final String UPDATE_ENABLED = "net.fortuna.ical4j.timezone.update.enabled";
    71     private static final Map DEFAULT_TIMEZONES = new ConcurrentHashMap();
    73     private static final Properties ALIASES = new Properties();
    74     static {
    75         try {
    76             ALIASES.load(ResourceLoader.getResourceAsStream("net/fortuna/ical4j/model/tz.alias"));
    77         }
    78         catch (IOException ioe) {
    79             LogFactory.getLog(TimeZoneRegistryImpl.class).warn(
    80                     "Error loading timezone aliases: " + ioe.getMessage());
    81         }
    82         try {
    83         	ALIASES.load(ResourceLoader.getResourceAsStream("tz.alias"));
    84         }
    85         catch (Exception e) {
    86         	LogFactory.getLog(TimeZoneRegistryImpl.class).debug(
    87         			"Error loading custom timezone aliases: " + e.getMessage());
    88         }
    89     }
    91     private Map timezones;
    93     private String resourcePrefix;
    95     /**
    96      * Default constructor.
    97      */
    98     public TimeZoneRegistryImpl() {
    99         this(DEFAULT_RESOURCE_PREFIX);
   100     }
   102     /**
   103      * Creates a new instance using the specified resource prefix.
   104      * @param resourcePrefix a prefix prepended to classpath resource lookups for default timezones
   105      */
   106     public TimeZoneRegistryImpl(final String resourcePrefix) {
   107         this.resourcePrefix = resourcePrefix;
   108         timezones = new ConcurrentHashMap();
   109     }
   111     /**
   112      * {@inheritDoc}
   113      */
   114     public final void register(final TimeZone timezone) {
   115     	// for now we only apply updates to included definitions by default..
   116     	register(timezone, false);
   117     }
   119     /**
   120      * {@inheritDoc}
   121      */
   122     public final void register(final TimeZone timezone, boolean update) {
   123     	if (update) {
   124             // load any available updates for the timezone..
   125             timezones.put(timezone.getID(), new TimeZone(updateDefinition(timezone.getVTimeZone())));
   126     	}
   127     	else {
   128             timezones.put(timezone.getID(), timezone);
   129     	}
   130     }
   132     /**
   133      * {@inheritDoc}
   134      */
   135     public final void clear() {
   136         timezones.clear();
   137     }
   139     /**
   140      * {@inheritDoc}
   141      */
   142     public final TimeZone getTimeZone(final String id) {
   143         TimeZone timezone = (TimeZone) timezones.get(id);
   144         if (timezone == null) {
   145             timezone = (TimeZone) DEFAULT_TIMEZONES.get(id);
   146             if (timezone == null) {
   147                 // if timezone not found with identifier, try loading an alias..
   148                 final String alias = ALIASES.getProperty(id);
   149                 if (alias != null) {
   150                     return getTimeZone(alias);
   151                 }
   152                 else {
   153                     synchronized (DEFAULT_TIMEZONES) {
   154                     	// check again as it may be loaded now..
   155                     	timezone = (TimeZone) DEFAULT_TIMEZONES.get(id);
   156                     	if (timezone == null) {
   157                             try {
   158                                 final VTimeZone vTimeZone = loadVTimeZone(id);
   159                                 if (vTimeZone != null) {
   160                                     // XXX: temporary kludge..
   161                                     // ((TzId) vTimeZone.getProperties().getProperty(Property.TZID)).setValue(id);
   162                                     timezone = new TimeZone(vTimeZone);
   163                                     DEFAULT_TIMEZONES.put(timezone.getID(), timezone);
   164                                 }
   165                                 else if (CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING)) {
   166                                     // strip global part of id and match on default tz..
   167                                     Matcher matcher = TZ_ID_SUFFIX.matcher(id);
   168                                     if (matcher.find()) {
   169                                         return getTimeZone(matcher.group());
   170                                     }
   171                                 }
   172                             }
   173                             catch (Exception e) {
   174                                 Log log = LogFactory.getLog(TimeZoneRegistryImpl.class);
   175                                 log.warn("Error occurred loading VTimeZone", e);
   176                             }
   177                     	}
   178                     }
   179                 }
   180             }
   181         }
   182         return timezone;
   183     }
   185     /**
   186      * Loads an existing VTimeZone from the classpath corresponding to the specified Java timezone.
   187      */
   188     private VTimeZone loadVTimeZone(final String id) throws IOException, ParserException {
   189         final URL resource = ResourceLoader.getResource(resourcePrefix + id + ".ics");
   190         if (resource != null) {
   191             final CalendarBuilder builder = new CalendarBuilder();
   192             final Calendar calendar = builder.build(resource.openStream());
   193             final VTimeZone vTimeZone = (VTimeZone) calendar.getComponent(Component.VTIMEZONE);
   194             // load any available updates for the timezone.. can be explicility disabled via configuration
   195             if (!"false".equals(Configurator.getProperty(UPDATE_ENABLED))) {
   196                 return updateDefinition(vTimeZone);
   197             }
   198             return vTimeZone;
   199         }
   200         return null;
   201     }
   203     /**
   204      * @param vTimeZone
   205      * @return
   206      */
   207     private VTimeZone updateDefinition(VTimeZone vTimeZone) {
   208         final TzUrl tzUrl = vTimeZone.getTimeZoneUrl();
   209         if (tzUrl != null) {
   210             try {
   211                 final CalendarBuilder builder = new CalendarBuilder();
   212                 final Calendar calendar = builder.build(tzUrl.getUri().toURL().openStream());
   213                 final VTimeZone updatedVTimeZone = (VTimeZone) calendar.getComponent(Component.VTIMEZONE);
   214                 if (updatedVTimeZone != null) {
   215                     return updatedVTimeZone;
   216                 }
   217             }
   218             catch (Exception e) {
   219                 Log log = LogFactory.getLog(TimeZoneRegistryImpl.class);
   220                 log.warn("Unable to retrieve updates for timezone: " + vTimeZone.getTimeZoneId().getValue(), e);
   221             }
   222         }
   223         return vTimeZone;
   224     }
   225 }

mercurial