View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.application;
23  
24  import java.io.ByteArrayInputStream;
25  import java.io.ByteArrayOutputStream;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.nio.charset.StandardCharsets;
29  import java.util.Arrays;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Map;
33  
34  import javax.faces.application.Resource;
35  import javax.faces.application.ResourceWrapper;
36  import javax.faces.context.FacesContext;
37  
38  import org.primefaces.util.Constants;
39  import org.primefaces.util.LangUtils;
40  
41  /**
42   * @author Jasper de Vries <jepsar@gmail.com>
43   * @since 10.0.1
44   */
45  public class ThemeAccentColorResource extends ResourceWrapper {
46  
47      private static final Map<String, String> CACHE = new HashMap<>();
48      private static final Map<String, List<String>> ACCENT_COLORS = new HashMap<>();
49  
50      static {
51          // @formatter:off
52          // colors ? 0: main, 1: hover, 2: active, 3: focus outline, 4: text
53          ACCENT_COLORS.put("primefaces-arya", Arrays.asList("#90caf9", "#6bb8f7", "#45a6f5", "#b1dafb", "rgba(255,255,255,.87)"));
54          ACCENT_COLORS.put("primefaces-saga", Arrays.asList("#2196f3", "#0d89ec", "#0b7ad1", "#a6d5fa", "#495057"));
55          ACCENT_COLORS.put("primefaces-vela", Arrays.asList("#90caf9", "#6bb8f7", "#45a6f5", "#b1dafb", "rgba(255,255,255,.87)"));
56          // @formatter:on
57      }
58  
59      private final String charEncoding;
60  
61      public ThemeAccentColorResource(final Resource wrapped) {
62          super(wrapped);
63          String encoding = FacesContext.getCurrentInstance().getExternalContext().getRequestCharacterEncoding();
64          if (LangUtils.isBlank(encoding)) {
65              encoding = StandardCharsets.UTF_8.name();
66          }
67          this.charEncoding = encoding;
68      }
69  
70      @Override
71      public InputStream getInputStream() throws IOException {
72          final String library = getWrapped().getLibraryName();
73          final List<String> accentColors = ACCENT_COLORS.get(library);
74          if (accentColors == null || accentColors.isEmpty()) {
75              return getWrapped().getInputStream();
76          }
77  
78          if (CACHE.containsKey(library)) {
79              return new ByteArrayInputStream(CACHE.get(library).getBytes(charEncoding));
80          }
81  
82          final String accentColor = "var(--"
83                      + library.replace(ThemeAccentColorResourceHandler.LIBRARY_PREFIX, Constants.EMPTY_STRING)
84                      + "%d)";
85          String css = getContent();
86          for (int i = 0; i < accentColors.size(); i++) {
87              css = css.replace(accentColors.get(i), String.format(accentColor, i));
88          }
89          CACHE.put(library, css);
90  
91          return new ByteArrayInputStream(css.getBytes(charEncoding));
92      }
93  
94      protected String getContent() throws IOException {
95          final ByteArrayOutputStream result = new ByteArrayOutputStream();
96          final byte[] buffer = new byte[1024];
97          final InputStream inputStream = getWrapped().getInputStream();
98          for (int length; (length = inputStream.read(buffer)) != -1;) {
99              result.write(buffer, 0, length);
100         }
101         return result.toString(charEncoding);
102     }
103 }