001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.head;
018
019import java.util.Objects;
020
021import org.apache.wicket.core.util.string.CssUtils;
022import org.apache.wicket.markup.html.CrossOrigin;
023import org.apache.wicket.request.Response;
024import org.apache.wicket.util.lang.Args;
025import org.apache.wicket.util.value.AttributeMap;
026
027/**
028 * A {@link org.apache.wicket.markup.head.HeaderItem} that renders a CSS reference.
029 */
030public abstract class AbstractCssReferenceHeaderItem extends CssHeaderItem implements ISubresourceHeaderItem
031{
032        private final String media;
033        private final String rel;
034        private CrossOrigin crossOrigin;
035        private String integrity;
036
037        public AbstractCssReferenceHeaderItem(String media, String rel)
038        {
039                this.media = media;
040                this.rel = rel;
041        }
042
043        @Override
044        public CrossOrigin getCrossOrigin()
045        {
046                return crossOrigin;
047        }
048
049        @Override
050        public AbstractCssReferenceHeaderItem setCrossOrigin(CrossOrigin crossOrigin)
051        {
052                this.crossOrigin = crossOrigin;
053                return this;
054        }
055
056        /**
057         * @return the media type for this CSS ("print", "screen", etc.)
058         */
059        public String getMedia()
060        {
061                return media;
062        }
063
064        /**
065         * @return the rel attribute content
066         */
067        public String getRel()
068        {
069                return rel;
070        }
071
072        @Override
073        public String getIntegrity()
074        {
075                return integrity;
076        }
077
078        @Override
079        public AbstractCssReferenceHeaderItem setIntegrity(String integrity)
080        {
081                this.integrity = integrity;
082                return this;
083        }
084
085        protected final void internalRenderCSSReference(Response response, String url)
086        {
087                Args.notEmpty(url, "url");
088
089                AttributeMap attributes = new AttributeMap();
090                attributes.putAttribute(CssUtils.ATTR_LINK_REL, getRel() == null ? "stylesheet" : getRel());
091                attributes.putAttribute(CssUtils.ATTR_TYPE, "text/css");
092                attributes.putAttribute(CssUtils.ATTR_LINK_HREF, url);
093                attributes.putAttribute(CssUtils.ATTR_ID, getId());
094                attributes.putAttribute(CssUtils.ATTR_LINK_MEDIA, getMedia());
095                attributes.putAttribute(CssUtils.ATTR_CROSS_ORIGIN,
096                        crossOrigin == null ? null : crossOrigin.getRealName());
097                attributes.putAttribute(CssUtils.ATTR_INTEGRITY, integrity);
098                attributes.putAttribute(CssUtils.ATTR_CSP_NONCE, getNonce());
099                CssUtils.writeLink(response, attributes);
100
101                response.write("\n");
102        }
103
104        @Override
105        public boolean equals(Object o)
106        {
107                if (this == o)
108                        return true;
109                if (o == null || getClass() != o.getClass())
110                        return false;
111                if (!super.equals(o))
112                        return false;
113                AbstractCssReferenceHeaderItem that = (AbstractCssReferenceHeaderItem)o;
114                return Objects.equals(integrity, that.integrity)
115                        && Objects.equals(crossOrigin, that.crossOrigin);
116        }
117
118        @Override
119        public int hashCode()
120        {
121                // Not using `Objects.hash` for performance reasons
122                int result = super.hashCode();
123                result = 31 * result + (crossOrigin != null ? crossOrigin.hashCode() : 0);
124                result = 31 * result + (integrity != null ? integrity.hashCode() : 0);
125                return result;
126        }
127}