001/*
002 * Copyright 2023 Web-Legacy
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.apache.tiles.request.jakarta.servlet;
017
018import java.net.MalformedURLException;
019import java.net.URL;
020import java.util.ArrayList;
021import java.util.Collection;
022import java.util.Locale;
023import java.util.Map;
024
025import org.apache.tiles.request.ApplicationContext;
026import org.apache.tiles.request.ApplicationResource;
027import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
028import org.apache.tiles.request.collection.ScopeMap;
029import org.apache.tiles.request.jakarta.servlet.extractor.ApplicationScopeExtractor;
030import org.apache.tiles.request.jakarta.servlet.extractor.InitParameterExtractor;
031import org.apache.tiles.request.locale.URLApplicationResource;
032
033import jakarta.servlet.ServletContext;
034
035/**
036 * Servlet-based implementation of the TilesApplicationContext interface.
037 *
038 * <p>Copied from Apache tiles-request-servlet 1.0.7 and adapted for
039 * Jakarta EE 9.</p>
040 */
041public class ServletApplicationContext implements ApplicationContext {
042
043    /**
044     * The servlet context to use.
045     */
046    private ServletContext servletContext;
047
048    /**
049     * The lazily instantiated {@code Map} of application scope attributes.
050     */
051    private Map<String, Object> applicationScope = null;
052
053    /**
054     * The lazily instantiated {@code Map} of context initialization parameters.
055     */
056    private Map<String, String> initParam = null;
057
058    /**
059     * Creates a new instance of ServletTilesApplicationContext.
060     *
061     * @param servletContext The servlet context to use.
062     */
063    public ServletApplicationContext(ServletContext servletContext) {
064        this.servletContext = servletContext;
065    }
066
067    /**
068     * Returns the servlet context to use.
069     *
070     * @return the servlet context to use
071     */
072    public Object getContext() {
073        return servletContext;
074    }
075
076    /**
077     * Returns the context map from application scope.
078     *
079     * @return the context map from application scope
080     */
081    public Map<String, Object> getApplicationScope() {
082        if (applicationScope == null && servletContext != null) {
083            applicationScope = new ScopeMap(
084                    new ApplicationScopeExtractor(servletContext));
085        }
086
087        return applicationScope;
088    }
089
090    /**
091     * Return an immutable Map that maps context application initialization
092     * parameters to their values.
093     *
094     * @return initialization parameters
095     */
096    public Map<String, String> getInitParams() {
097        if (initParam == null && servletContext != null) {
098            initParam = new ReadOnlyEnumerationMap<String>(
099                    new InitParameterExtractor(servletContext));
100        }
101
102        return initParam;
103    }
104
105    /**
106     * Return the application resource mapped to the specified path.
107     *
108     * @param localePath path to the desired resource, including the Locale
109     *                   suffix.
110     *
111     * @return the first located resource which matches the given path or null
112     *         if no such resource exists.
113     */
114    public ApplicationResource getResource(String localePath) {
115        try {
116            URL url = servletContext.getResource(localePath);
117            if (url != null) {
118                return new URLApplicationResource(localePath, url);
119            } else {
120                return null;
121            }
122        } catch (MalformedURLException e) {
123            return null;
124        }
125    }
126
127    /**
128     * Return a localized version of an ApplicationResource.
129     *
130     * @param base   the ApplicationResource.
131     * @param locale the desired Locale.
132     *
133     * @return the first located resource which matches the given path or null
134     *         if no such resource exists.
135     */
136    public ApplicationResource getResource(ApplicationResource base, Locale locale) {
137        try {
138            URL url = servletContext.getResource(base.getLocalePath(locale));
139            if (url != null) {
140                return new URLApplicationResource(base.getPath(), locale, url);
141            } else {
142                return null;
143            }
144        } catch (MalformedURLException e) {
145            return null;
146        }
147    }
148
149    /**
150     * Return the application resources mapped to the specified path.
151     *
152     * @param path to the desired resource.
153     *
154     * @return all resources which match the given path.
155     */
156    public Collection<ApplicationResource> getResources(String path) {
157        ArrayList<ApplicationResource> resources = new ArrayList<ApplicationResource>();
158        resources.add(getResource(path));
159        return resources;
160    }
161}