001package biweekly.io; 002 003import java.io.FileNotFoundException; 004import java.io.IOException; 005import java.net.URI; 006import java.net.URISyntaxException; 007import java.util.Collections; 008import java.util.HashMap; 009import java.util.Map; 010import java.util.NoSuchElementException; 011import java.util.TimeZone; 012 013import biweekly.component.VTimezone; 014import biweekly.io.text.ICalReader; 015import biweekly.util.IOUtils; 016 017/* 018 Copyright (c) 2013-2015, Michael Angstadt 019 All rights reserved. 020 021 Redistribution and use in source and binary forms, with or without 022 modification, are permitted provided that the following conditions are met: 023 024 1. Redistributions of source code must retain the above copyright notice, this 025 list of conditions and the following disclaimer. 026 2. Redistributions in binary form must reproduce the above copyright notice, 027 this list of conditions and the following disclaimer in the documentation 028 and/or other materials provided with the distribution. 029 030 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 031 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 032 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 033 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 034 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 035 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 036 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 037 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 038 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 039 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 040 */ 041 042/** 043 * Downloads {@link VTimezone} components from <a 044 * href="http://www.tzurl.org">tzurl.org</a>. 045 * @author Michael Angstadt 046 */ 047public class TzUrlDotOrgGenerator implements VTimezoneGenerator { 048 private static final Map<URI, VTimezone> cache = Collections.synchronizedMap(new HashMap<URI, VTimezone>()); 049 private final String baseUrl; 050 051 /** 052 * Creates a new tzurl.org translator. 053 * @param outlook true to generate Outlook-compatible {@link VTimezone} 054 * components, false to use standards-based ones 055 */ 056 public TzUrlDotOrgGenerator(boolean outlook) { 057 baseUrl = "http://www.tzurl.org/zoneinfo" + (outlook ? "-outlook" : "") + "/"; 058 } 059 060 public VTimezone generate(TimeZone timezone) throws IllegalArgumentException { 061 URI uri; 062 try { 063 uri = new URI(baseUrl + timezone.getID()); 064 } catch (URISyntaxException e) { 065 throw new IllegalArgumentException(e); 066 } 067 068 VTimezone component = cache.get(uri); 069 if (component != null) { 070 return component; 071 } 072 073 ICalReader reader = null; 074 try { 075 reader = new ICalReader(uri.toURL().openStream()); 076 reader.readNext(); 077 078 TimezoneInfo tzinfo = reader.getTimezoneInfo(); 079 component = tzinfo.getComponents().iterator().next(); 080 cache.put(uri, component); 081 return component; 082 } catch (FileNotFoundException e) { 083 throw notFound(e); 084 } catch (NoSuchElementException e) { 085 throw notFound(e); 086 } catch (IOException e) { 087 throw new RuntimeException(e); 088 } finally { 089 IOUtils.closeQuietly(reader); 090 } 091 } 092 093 private IllegalArgumentException notFound(Exception e) { 094 return new IllegalArgumentException("Timezone ID not recognized.", e); 095 } 096}