001/*
002 * Copyright 2002-2013 the original author or authors.
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 *      https://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 */
016
017package org.springframework.mock.web.portlet;
018
019import java.io.File;
020import java.io.IOException;
021import java.io.InputStream;
022import java.net.MalformedURLException;
023import java.net.URL;
024import java.util.Collections;
025import java.util.Enumeration;
026import java.util.HashSet;
027import java.util.LinkedHashMap;
028import java.util.LinkedHashSet;
029import java.util.Map;
030import java.util.Set;
031import javax.activation.FileTypeMap;
032import javax.portlet.PortletContext;
033import javax.portlet.PortletRequestDispatcher;
034
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037
038import org.springframework.core.io.DefaultResourceLoader;
039import org.springframework.core.io.Resource;
040import org.springframework.core.io.ResourceLoader;
041import org.springframework.util.Assert;
042import org.springframework.web.util.WebUtils;
043
044/**
045 * Mock implementation of the {@link javax.portlet.PortletContext} interface.
046 *
047 * @author John A. Lewis
048 * @author Juergen Hoeller
049 * @since 2.0
050 */
051public class MockPortletContext implements PortletContext {
052
053        private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir";
054
055
056        private final Log logger = LogFactory.getLog(getClass());
057
058        private final String resourceBasePath;
059
060        private final ResourceLoader resourceLoader;
061
062        private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
063
064        private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
065
066        private String portletContextName = "MockPortletContext";
067
068        private Set<String> containerRuntimeOptions = new LinkedHashSet<String>();
069
070
071        /**
072         * Create a new MockPortletContext with no base path and a
073         * DefaultResourceLoader (i.e. the classpath root as WAR root).
074         * @see org.springframework.core.io.DefaultResourceLoader
075         */
076        public MockPortletContext() {
077                this("", null);
078        }
079
080        /**
081         * Create a new MockPortletContext using a DefaultResourceLoader.
082         * @param resourceBasePath the WAR root directory (should not end with a slash)
083         * @see org.springframework.core.io.DefaultResourceLoader
084         */
085        public MockPortletContext(String resourceBasePath) {
086                this(resourceBasePath, null);
087        }
088
089        /**
090         * Create a new MockPortletContext, using the specified ResourceLoader
091         * and no base path.
092         * @param resourceLoader the ResourceLoader to use (or null for the default)
093         */
094        public MockPortletContext(ResourceLoader resourceLoader) {
095                this("", resourceLoader);
096        }
097
098        /**
099         * Create a new MockPortletContext.
100         * @param resourceBasePath the WAR root directory (should not end with a slash)
101         * @param resourceLoader the ResourceLoader to use (or null for the default)
102         */
103        public MockPortletContext(String resourceBasePath, ResourceLoader resourceLoader) {
104                this.resourceBasePath = (resourceBasePath != null ? resourceBasePath : "");
105                this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
106
107                // Use JVM temp dir as PortletContext temp dir.
108                String tempDir = System.getProperty(TEMP_DIR_SYSTEM_PROPERTY);
109                if (tempDir != null) {
110                        this.attributes.put(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File(tempDir));
111                }
112        }
113
114        /**
115         * Build a full resource location for the given path,
116         * prepending the resource base path of this MockPortletContext.
117         * @param path the path as specified
118         * @return the full resource path
119         */
120        protected String getResourceLocation(String path) {
121                if (!path.startsWith("/")) {
122                        path = "/" + path;
123                }
124                return this.resourceBasePath + path;
125        }
126
127
128        @Override
129        public String getServerInfo() {
130                return "MockPortal/1.0";
131        }
132
133        @Override
134        public PortletRequestDispatcher getRequestDispatcher(String path) {
135                if (!path.startsWith("/")) {
136                        throw new IllegalArgumentException(
137                                        "PortletRequestDispatcher path at PortletContext level must start with '/'");
138                }
139                return new MockPortletRequestDispatcher(path);
140        }
141
142        @Override
143        public PortletRequestDispatcher getNamedDispatcher(String path) {
144                return null;
145        }
146
147        @Override
148        public InputStream getResourceAsStream(String path) {
149                Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
150                try {
151                        return resource.getInputStream();
152                }
153                catch (IOException ex) {
154                        logger.info("Couldn't open InputStream for " + resource, ex);
155                        return null;
156                }
157        }
158
159        @Override
160        public int getMajorVersion() {
161                return 2;
162        }
163
164        @Override
165        public int getMinorVersion() {
166                return 0;
167        }
168
169        @Override
170        public String getMimeType(String filePath) {
171                return MimeTypeResolver.getMimeType(filePath);
172        }
173
174        @Override
175        public String getRealPath(String path) {
176                Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
177                try {
178                        return resource.getFile().getAbsolutePath();
179                }
180                catch (IOException ex) {
181                        logger.info("Couldn't determine real path of resource " + resource, ex);
182                        return null;
183                }
184        }
185
186        @Override
187        public Set<String> getResourcePaths(String path) {
188                Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
189                try {
190                        File file = resource.getFile();
191                        String[] fileList = file.list();
192                        String prefix = (path.endsWith("/") ? path : path + "/");
193                        Set<String> resourcePaths = new HashSet<String>(fileList.length);
194                        for (String fileEntry : fileList) {
195                                resourcePaths.add(prefix + fileEntry);
196                        }
197                        return resourcePaths;
198                }
199                catch (IOException ex) {
200                        logger.info("Couldn't get resource paths for " + resource, ex);
201                        return null;
202                }
203        }
204
205        @Override
206        public URL getResource(String path) throws MalformedURLException {
207                Resource resource = this.resourceLoader.getResource(getResourceLocation(path));
208                try {
209                        return resource.getURL();
210                }
211                catch (IOException ex) {
212                        logger.info("Couldn't get URL for " + resource, ex);
213                        return null;
214                }
215        }
216
217        @Override
218        public Object getAttribute(String name) {
219                return this.attributes.get(name);
220        }
221
222        @Override
223        public Enumeration<String> getAttributeNames() {
224                return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
225        }
226
227        @Override
228        public void setAttribute(String name, Object value) {
229                if (value != null) {
230                        this.attributes.put(name, value);
231                }
232                else {
233                        this.attributes.remove(name);
234                }
235        }
236
237        @Override
238        public void removeAttribute(String name) {
239                this.attributes.remove(name);
240        }
241
242        public void addInitParameter(String name, String value) {
243                Assert.notNull(name, "Parameter name must not be null");
244                this.initParameters.put(name, value);
245        }
246
247        @Override
248        public String getInitParameter(String name) {
249                Assert.notNull(name, "Parameter name must not be null");
250                return this.initParameters.get(name);
251        }
252
253        @Override
254        public Enumeration<String> getInitParameterNames() {
255                return Collections.enumeration(this.initParameters.keySet());
256        }
257
258        @Override
259        public void log(String message) {
260                logger.info(message);
261        }
262
263        @Override
264        public void log(String message, Throwable t) {
265                logger.info(message, t);
266        }
267
268        public void setPortletContextName(String portletContextName) {
269                this.portletContextName = portletContextName;
270        }
271
272        @Override
273        public String getPortletContextName() {
274                return this.portletContextName;
275        }
276
277        public void addContainerRuntimeOption(String key) {
278                this.containerRuntimeOptions.add(key);
279        }
280
281        @Override
282        public Enumeration<String> getContainerRuntimeOptions() {
283                return Collections.enumeration(this.containerRuntimeOptions);
284        }
285
286
287        /**
288         * Inner factory class used to just introduce a Java Activation Framework
289         * dependency when actually asked to resolve a MIME type.
290         */
291        private static class MimeTypeResolver {
292
293                public static String getMimeType(String filePath) {
294                        return FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
295                }
296        }
297
298}