1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.css;
  27 
  28 import com.sun.javafx.scene.layout.region.CornerRadiiConverter;
  29 import com.sun.javafx.util.Logging;
  30 import javafx.css.CssMetaData;
  31 import javafx.css.ParsedValue;
  32 import javafx.css.StyleConverter;
  33 import javafx.css.Styleable;
  34 import sun.util.logging.PlatformLogger;
  35 import sun.util.logging.PlatformLogger.Level;
  36 
  37 import java.io.DataInputStream;
  38 import java.io.DataOutputStream;
  39 import java.io.IOException;
  40 import java.util.HashMap;
  41 import java.util.Map;
  42 import java.util.WeakHashMap;
  43 
  44 /**
  45  * Converter converts ParsedValueImpl<F,T> from type F to type T.
  46  * F is the type of the parsed value, T is the converted type of
  47  * the ParsedValueImpl. For example, a converter from String to Color would
  48  * be declared
  49  * <p>&nbsp;&nbsp;&nbsp;&nbsp;
  50  * <code>public Color convert(ParsedValueImpl&lt;String,Color&gt; value, Font font)</code>
  51  * </p>
  52  */
  53 public class StyleConverterImpl<F, T> extends StyleConverter<F, T> {
  54 
  55     /**
  56      * Convert from the constituent values to the target property type.
  57      * Implemented by Types that have Keys with subKeys.
  58      */
  59     public T convert(Map<CssMetaData<? extends Styleable, ?>,Object> convertedValues) {
  60         return null;
  61     }
  62 
  63     protected StyleConverterImpl() {
  64         super();
  65     }
  66 
  67     public void writeBinary(DataOutputStream os, StringStore sstore)
  68             throws IOException {
  69 
  70         String cname = getClass().getName();
  71         int index = sstore.addString(cname);
  72         os.writeShort(index);
  73     }
  74 
  75     private static Map<ParsedValue, Object> cache;
  76 
  77     static void clearCache() { if (cache != null) cache.clear(); }
  78 
  79     protected T getCachedValue(ParsedValue key) {
  80         if (cache != null) {
  81             return (T)cache.get(key);
  82         }
  83         return null;
  84     }
  85 
  86     protected void cacheValue(ParsedValue key, Object value) {
  87         if (cache == null) cache = new WeakHashMap<>();
  88         cache.put(key, value);
  89     }
  90 
  91     // map of StyleConverter class name to StyleConverter
  92     private static Map<String,StyleConverter<?, ?>> tmap;
  93 
  94     @SuppressWarnings("rawtypes")
  95     public static StyleConverter<?,?> readBinary(DataInputStream is, String[] strings)
  96             throws IOException {
  97 
  98         int index = is.readShort();
  99         String cname = strings[index];
 100 
 101         if (cname == null || cname.isEmpty()) return null;
 102 
 103         if (cname.startsWith("com.sun.javafx.css.converters.EnumConverter")) {
 104             return (StyleConverter)com.sun.javafx.css.converters.EnumConverter.readBinary(is, strings);
 105         }
 106 
 107         // Make a new entry in tmap, if necessary
 108         if (tmap == null || !tmap.containsKey(cname)) {
 109             StyleConverter<?,?> converter = getInstance(cname);
 110             if (converter == null) {
 111                 final PlatformLogger logger = Logging.getCSSLogger();
 112                 if (logger.isLoggable(Level.SEVERE)) {
 113                     logger.severe("could not deserialize " + cname);
 114                 }
 115             }
 116             if (converter == null) {
 117                 System.err.println("could not deserialize " + cname);
 118             }
 119             if (tmap == null) tmap = new HashMap<String,StyleConverter<?,?>>();
 120             tmap.put(cname, converter);
 121             return converter;
 122         }
 123         return tmap.get(cname);
 124     }
 125 
 126     // package for unit test purposes
 127     static StyleConverter<?,?> getInstance(final String converterClass) {
 128 
 129         StyleConverter<?,?> styleConverter = null;
 130 
 131         switch(converterClass) {
 132         case "com.sun.javafx.css.converters.BooleanConverter" :
 133             styleConverter = com.sun.javafx.css.converters.BooleanConverter.getInstance();
 134             break;
 135         case "com.sun.javafx.css.converters.ColorConverter" :
 136             styleConverter = com.sun.javafx.css.converters.ColorConverter.getInstance();
 137             break;
 138         case "com.sun.javafx.css.converters.CursorConverter" :
 139             styleConverter = com.sun.javafx.css.converters.CursorConverter.getInstance();
 140             break;
 141         case "com.sun.javafx.css.converters.EffectConverter" :
 142             styleConverter = com.sun.javafx.css.converters.EffectConverter.getInstance();
 143             break;
 144         case "com.sun.javafx.css.converters.EffectConverter$DropShadowConverter" :
 145             styleConverter = com.sun.javafx.css.converters.EffectConverter.DropShadowConverter.getInstance();
 146             break;
 147         case "com.sun.javafx.css.converters.EffectConverter$InnerShadowConverter" :
 148             styleConverter = com.sun.javafx.css.converters.EffectConverter.InnerShadowConverter.getInstance();
 149             break;
 150         case "com.sun.javafx.css.converters.FontConverter" :
 151             styleConverter = com.sun.javafx.css.converters.FontConverter.getInstance();
 152             break;
 153         case "com.sun.javafx.css.converters.FontConverter$FontStyleConverter" :
 154         case "com.sun.javafx.css.converters.FontConverter$StyleConverter" :
 155             styleConverter = com.sun.javafx.css.converters.FontConverter.FontStyleConverter.getInstance();
 156             break;
 157         case "com.sun.javafx.css.converters.FontConverter$FontWeightConverter" :
 158         case "com.sun.javafx.css.converters.FontConverter$WeightConverter" :
 159             styleConverter = com.sun.javafx.css.converters.FontConverter.FontWeightConverter.getInstance();
 160             break;
 161         case "com.sun.javafx.css.converters.FontConverter$FontSizeConverter" :
 162         case "com.sun.javafx.css.converters.FontConverter$SizeConverter" :
 163             styleConverter = com.sun.javafx.css.converters.FontConverter.FontSizeConverter.getInstance();
 164             break;
 165 
 166         case "com.sun.javafx.css.converters.InsetsConverter" :
 167             styleConverter = com.sun.javafx.css.converters.InsetsConverter.getInstance();
 168             break;
 169         case "com.sun.javafx.css.converters.InsetsConverter$SequenceConverter" :
 170             styleConverter = com.sun.javafx.css.converters.InsetsConverter.SequenceConverter.getInstance();
 171             break;
 172 
 173         case "com.sun.javafx.css.converters.PaintConverter" :
 174             styleConverter = com.sun.javafx.css.converters.PaintConverter.getInstance();
 175             break;
 176         case "com.sun.javafx.css.converters.PaintConverter$SequenceConverter" :
 177             styleConverter = com.sun.javafx.css.converters.PaintConverter.SequenceConverter.getInstance();
 178             break;
 179         case "com.sun.javafx.css.converters.PaintConverter$LinearGradientConverter" :
 180             styleConverter = com.sun.javafx.css.converters.PaintConverter.LinearGradientConverter.getInstance();
 181             break;
 182         case "com.sun.javafx.css.converters.PaintConverter$RadialGradientConverter" :
 183             styleConverter = com.sun.javafx.css.converters.PaintConverter.RadialGradientConverter.getInstance();
 184             break;
 185 
 186         case "com.sun.javafx.css.converters.SizeConverter" :
 187             styleConverter = com.sun.javafx.css.converters.SizeConverter.getInstance();
 188             break;
 189         case "com.sun.javafx.css.converters.SizeConverter$SequenceConverter" :
 190             styleConverter = com.sun.javafx.css.converters.SizeConverter.SequenceConverter.getInstance();
 191             break;
 192 
 193         case "com.sun.javafx.css.converters.StringConverter" :
 194             styleConverter = com.sun.javafx.css.converters.StringConverter.getInstance();
 195             break;
 196         case "com.sun.javafx.css.converters.StringConverter$SequenceConverter" :
 197             styleConverter = com.sun.javafx.css.converters.StringConverter.SequenceConverter.getInstance();
 198             break;
 199         case "com.sun.javafx.css.converters.URLConverter" :
 200             styleConverter = com.sun.javafx.css.converters.URLConverter.getInstance();
 201             break;
 202         case "com.sun.javafx.css.converters.URLConverter$SequenceConverter" :
 203             styleConverter = com.sun.javafx.css.converters.URLConverter.SequenceConverter.getInstance();
 204             break;
 205 
 206         // Region stuff  - including 2.x class names
 207         case "com.sun.javafx.scene.layout.region.BackgroundPositionConverter" :
 208         case "com.sun.javafx.scene.layout.region.BackgroundImage$BackgroundPositionConverter" :
 209             styleConverter = com.sun.javafx.scene.layout.region.BackgroundPositionConverter.getInstance();
 210             break;
 211         case "com.sun.javafx.scene.layout.region.BackgroundSizeConverter" :
 212         case "com.sun.javafx.scene.layout.region.BackgroundImage$BackgroundSizeConverter" :
 213             styleConverter = com.sun.javafx.scene.layout.region.BackgroundSizeConverter.getInstance();
 214             break;
 215         case "com.sun.javafx.scene.layout.region.BorderImageSliceConverter" :
 216         case "com.sun.javafx.scene.layout.region.BorderImage$SliceConverter" :
 217             styleConverter = com.sun.javafx.scene.layout.region.BorderImageSliceConverter.getInstance();
 218             break;
 219         case "com.sun.javafx.scene.layout.region.BorderImageWidthConverter" :
 220             styleConverter = com.sun.javafx.scene.layout.region.BorderImageWidthConverter.getInstance();
 221             break;
 222         case "com.sun.javafx.scene.layout.region.BorderImageWidthsSequenceConverter" :
 223             styleConverter = com.sun.javafx.scene.layout.region.BorderImageWidthsSequenceConverter.getInstance();
 224             break;
 225         case "com.sun.javafx.scene.layout.region.BorderStrokeStyleSequenceConverter" :
 226         case "com.sun.javafx.scene.layout.region.StrokeBorder$BorderStyleSequenceConverter" :
 227             styleConverter = com.sun.javafx.scene.layout.region.BorderStrokeStyleSequenceConverter.getInstance();
 228             break;
 229         case "com.sun.javafx.scene.layout.region.BorderStyleConverter" :
 230         case "com.sun.javafx.scene.layout.region.StrokeBorder$BorderStyleConverter" :
 231             styleConverter = com.sun.javafx.scene.layout.region.BorderStyleConverter.getInstance();
 232             break;
 233         case "com.sun.javafx.scene.layout.region.LayeredBackgroundPositionConverter" :
 234         case "com.sun.javafx.scene.layout.region.BackgroundImage$LayeredBackgroundPositionConverter" :
 235             styleConverter = com.sun.javafx.scene.layout.region.LayeredBackgroundPositionConverter.getInstance();
 236             break;
 237         case "com.sun.javafx.scene.layout.region.LayeredBackgroundSizeConverter" :
 238         case "com.sun.javafx.scene.layout.region.BackgroundImage$LayeredBackgroundSizeConverter" :
 239             styleConverter = com.sun.javafx.scene.layout.region.LayeredBackgroundSizeConverter.getInstance();
 240             break;
 241         case "com.sun.javafx.scene.layout.region.LayeredBorderPaintConverter" :
 242         case "com.sun.javafx.scene.layout.region.StrokeBorder$LayeredBorderPaintConverter" :
 243            styleConverter = com.sun.javafx.scene.layout.region.LayeredBorderPaintConverter.getInstance();
 244             break;
 245         case "com.sun.javafx.scene.layout.region.LayeredBorderStyleConverter" :
 246         case "com.sun.javafx.scene.layout.region.StrokeBorder$LayeredBorderStyleConverter" :
 247             styleConverter = com.sun.javafx.scene.layout.region.LayeredBorderStyleConverter.getInstance();
 248             break;
 249         case "com.sun.javafx.scene.layout.region.RepeatStructConverter" :
 250         case "com.sun.javafx.scene.layout.region.BackgroundImage$BackgroundRepeatConverter" :
 251         case "com.sun.javafx.scene.layout.region.BorderImage$RepeatConverter" :
 252             styleConverter = com.sun.javafx.scene.layout.region.RepeatStructConverter.getInstance();
 253             break;
 254         case "com.sun.javafx.scene.layout.region.SliceSequenceConverter" :
 255         case "com.sun.javafx.scene.layout.region.BorderImage$SliceSequenceConverter" :
 256             styleConverter = com.sun.javafx.scene.layout.region.SliceSequenceConverter.getInstance();
 257             break;
 258         case "com.sun.javafx.scene.layout.region.StrokeBorderPaintConverter" :
 259         case "com.sun.javafx.scene.layout.region.StrokeBorder$BorderPaintConverter" :
 260             styleConverter = com.sun.javafx.scene.layout.region.StrokeBorderPaintConverter.getInstance();
 261             break;
 262         case "com.sun.javafx.scene.layout.region.Margins$Converter" :
 263             styleConverter = com.sun.javafx.scene.layout.region.Margins.Converter.getInstance();
 264             break;
 265         case "com.sun.javafx.scene.layout.region.Margins$SequenceConverter" :
 266             styleConverter = com.sun.javafx.scene.layout.region.Margins.SequenceConverter.getInstance();
 267             break;
 268         case "javafx.scene.layout.CornerRadiiConverter" :  // Fix for RT-39665
 269         case "com.sun.javafx.scene.layout.region.CornerRadiiConverter" :
 270             styleConverter = CornerRadiiConverter.getInstance();
 271             break;
 272 
 273         // parser stuff
 274         case "com.sun.javafx.css.parser.DeriveColorConverter" :
 275             styleConverter = com.sun.javafx.css.parser.DeriveColorConverter.getInstance();
 276             break;
 277         case "com.sun.javafx.css.parser.DeriveSizeConverter" :
 278             styleConverter = com.sun.javafx.css.parser.DeriveSizeConverter.getInstance();
 279             break;
 280         case "com.sun.javafx.css.parser.LadderConverter" :
 281             styleConverter = com.sun.javafx.css.parser.LadderConverter.getInstance();
 282             break;
 283         case "com.sun.javafx.css.parser.StopConverter" :
 284             styleConverter = com.sun.javafx.css.parser.StopConverter.getInstance();
 285             break;
 286 
 287             default :
 288             final PlatformLogger logger = Logging.getCSSLogger();
 289             if (logger.isLoggable(Level.SEVERE)) {
 290                 logger.severe("StyleConverterImpl : converter Class is null for : "+converterClass);
 291             }
 292             break;
 293         }
 294 
 295         return styleConverter;
 296     }
 297 }