| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| EncoderProvider |
|
| 2.2;2.2 |
| 1 | /* | |
| 2 | * Copyright (C) 1998-2000 Semiotek Inc. All Rights Reserved. | |
| 3 | * | |
| 4 | * Redistribution and use in source and binary forms, with or without | |
| 5 | * modification, are permitted under the terms of either of the following | |
| 6 | * Open Source licenses: | |
| 7 | * | |
| 8 | * The GNU General Public License, version 2, or any later version, as | |
| 9 | * published by the Free Software Foundation | |
| 10 | * (http://www.fsf.org/copyleft/gpl.html); | |
| 11 | * | |
| 12 | * or | |
| 13 | * | |
| 14 | * The Semiotek Public License (http://webmacro.org/LICENSE.) | |
| 15 | * | |
| 16 | * This software is provided "as is", with NO WARRANTY, not even the | |
| 17 | * implied warranties of fitness to purpose, or merchantability. You | |
| 18 | * assume all risks and liabilities associated with its use. | |
| 19 | * | |
| 20 | * See www.webmacro.org for more information on the WebMacro project. | |
| 21 | */ | |
| 22 | ||
| 23 | package org.webmacro.util; | |
| 24 | ||
| 25 | import java.io.UnsupportedEncodingException; | |
| 26 | import java.util.HashMap; | |
| 27 | import java.util.Map; | |
| 28 | ||
| 29 | import org.webmacro.Broker; | |
| 30 | import org.webmacro.InitException; | |
| 31 | import org.webmacro.NotFoundException; | |
| 32 | import org.webmacro.Provider; | |
| 33 | import org.webmacro.ResourceException; | |
| 34 | ||
| 35 | /** | |
| 36 | * A provider which dispenses Encoders, which are used for encoding | |
| 37 | * Strings and caching the results. | |
| 38 | * @since 0.96 | |
| 39 | * @author Michael Bayne | |
| 40 | */ | |
| 41 | ||
| 42 | 6 | public class EncoderProvider implements Provider |
| 43 | { | |
| 44 | ||
| 45 | 6 | private Map _encoders = new HashMap(); |
| 46 | private Broker _broker; | |
| 47 | private Settings _config; | |
| 48 | ||
| 49 | /** | |
| 50 | * The provider type for this provider. Use this when calling | |
| 51 | * <code>Broker.getProvider()</code>. | |
| 52 | */ | |
| 53 | public static final String TYPE = "encoder"; | |
| 54 | ||
| 55 | /** | |
| 56 | * Return an array representing the types this provider serves up | |
| 57 | */ | |
| 58 | public String getType () | |
| 59 | { | |
| 60 | 6 | return TYPE; |
| 61 | } | |
| 62 | ||
| 63 | /** | |
| 64 | * Initialize this provider based on the specified config. Derived | |
| 65 | * encoder provider implementations may override this method to obtain | |
| 66 | * initialization parameters of their own devising, but they must be | |
| 67 | * sure to call super.init() in their overridden methods. | |
| 68 | */ | |
| 69 | public void init (Broker b, Settings config) throws InitException | |
| 70 | { | |
| 71 | 6 | _broker = b; |
| 72 | 6 | _config = config; |
| 73 | 6 | } |
| 74 | ||
| 75 | // Implementation note: the flush(), destroy() and get() methods are | |
| 76 | // instance synchronized to ensure that if _encoders is cleared via the | |
| 77 | // destroy() method and get() is called subsequently, we properly avoid | |
| 78 | // referencing the null variable. We can't synchronize on _encoders | |
| 79 | // because that becomes null and code that does this: | |
| 80 | // | |
| 81 | // if (_encoders != null) { | |
| 82 | // synchronized (_encoders) { | |
| 83 | // | |
| 84 | // is not valid because the _encoders reference could become null | |
| 85 | // in between those two statements. | |
| 86 | // | |
| 87 | // Additionally, the EncoderProvider is not invoked frequently enough | |
| 88 | // to merit a more sophisticated synchronization approach (it is only | |
| 89 | // called once per request when creating a FastWriter with which to | |
| 90 | // output the response and not even that often because FastWriter | |
| 91 | // instances are cached). Thus, we choose simplicity and robustness in | |
| 92 | // this situation. | |
| 93 | ||
| 94 | /** | |
| 95 | * Clear any cache this provider may be maintaining. | |
| 96 | */ | |
| 97 | public synchronized void flush () | |
| 98 | { | |
| 99 | // clean out the encoder cache | |
| 100 | 0 | _encoders.clear(); |
| 101 | 0 | } |
| 102 | ||
| 103 | /** | |
| 104 | * Close down this provider, freeing any allocated resources. | |
| 105 | */ | |
| 106 | public synchronized void destroy () | |
| 107 | { | |
| 108 | // clear out our reference to the encoder cache to allow it to be | |
| 109 | // garbage collected | |
| 110 | 0 | _encoders = null; |
| 111 | 0 | } |
| 112 | ||
| 113 | /** | |
| 114 | * Get the object associated with the specified query. | |
| 115 | */ | |
| 116 | public synchronized Object get (String encoding) throws ResourceException | |
| 117 | { | |
| 118 | 1734 | Encoder encoder = null; |
| 119 | ||
| 120 | // make sure we're not inadvertently being called after we've | |
| 121 | // already been destroy()ed | |
| 122 | 1734 | if (_encoders != null) |
| 123 | { | |
| 124 | 1734 | encoder = (Encoder) _encoders.get(encoding); |
| 125 | ||
| 126 | 1734 | if (encoder == null) |
| 127 | { | |
| 128 | try | |
| 129 | { | |
| 130 | // create and cache a new encoder instance for this | |
| 131 | // encoding if one doesn't already exist in the cache | |
| 132 | 12 | encoder = new Encoder(encoding); |
| 133 | 12 | encoder.init(_broker, _config); |
| 134 | 12 | _encoders.put(encoding, encoder); |
| 135 | } | |
| 136 | 0 | catch (InitException e) |
| 137 | { | |
| 138 | 0 | throw new ResourceException("Unable to initialize Encoder for " |
| 139 | + encoding + "; " + e); | |
| 140 | } | |
| 141 | 0 | catch (UnsupportedEncodingException uee) |
| 142 | { | |
| 143 | 0 | throw new NotFoundException("Unsupported encoding: " + |
| 144 | uee.getMessage()); | |
| 145 | 12 | } |
| 146 | } | |
| 147 | } | |
| 148 | 1734 | return encoder; |
| 149 | } | |
| 150 | } |