001/*
002 * Shredzone Commons
003 *
004 * Copyright (C) 2012 Richard "Shred" Körber
005 *   http://commons.shredzone.org
006 *
007 * This program is free software: you can redistribute it and/or modify
008 * it under the terms of the GNU Library General Public License as
009 * published by the Free Software Foundation, either version 3 of the
010 * License, or (at your option) any later version.
011 *
012 * This program is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU Library General Public License
018 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
019 */
020
021package org.shredzone.commons.view.impl;
022
023import java.io.BufferedReader;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.OutputStream;
027import java.io.PrintWriter;
028import java.util.Collections;
029import java.util.HashMap;
030import java.util.Locale;
031import java.util.Map;
032
033import javax.annotation.ParametersAreNonnullByDefault;
034import javax.annotation.PostConstruct;
035import javax.annotation.Resource;
036import javax.servlet.http.HttpServletRequest;
037import javax.servlet.http.HttpServletResponse;
038import javax.servlet.http.HttpSession;
039
040import org.shredzone.commons.view.ViewContext;
041import org.shredzone.commons.view.exception.ViewContextException;
042import org.springframework.context.annotation.Scope;
043import org.springframework.stereotype.Component;
044
045/**
046 * Default implementation of {@link ViewContext}.
047 * <p>
048 * This bean is request scoped.
049 *
050 * @author Richard "Shred" Körber
051 */
052@Component("viewContext")
053@Scope("request")
054@ParametersAreNonnullByDefault
055public class ViewContextImpl implements ViewContext {
056
057    @Resource private HttpServletRequest req;
058
059    private String requestServerUrl;
060    private String requestServletName;
061
062    private Map<Class<?>, Object> typedValueMap = new HashMap<>();
063    private Map<String, String> pathParts;
064    private String qualifier;
065
066    /**
067     * Sets up this bean's contents.
068     */
069    @PostConstruct
070    protected void setup() {
071        StringBuilder sb = new StringBuilder();
072        String scheme = req.getScheme();
073        int serverPort = req.getServerPort();
074        sb.append(scheme).append("://").append(req.getServerName());
075        if (! (("http".equals(scheme) && serverPort == 80)
076            || ("https".equals(scheme) && serverPort == 443))) {
077            sb.append(':').append(serverPort);
078        }
079
080        requestServerUrl = sb.toString();
081        requestServletName = req.getServletPath();
082    }
083
084    @Override
085    public String getRequestServerUrl() {
086        return requestServerUrl;
087    }
088
089    @Override
090    public String getRequestServletName() {
091        return requestServletName;
092    }
093
094    @Override
095    public String getParameter(String name) {
096        return req.getParameter(name);
097    }
098
099    @Override
100    public <T> void putTypedArgument(Class<T> type, T value) {
101        if (value != null && !type.isAssignableFrom(value.getClass())) {
102            throw new IllegalArgumentException("value must be an instance of "
103                            + type.getName() + ", but is " + value.getClass().getName());
104        }
105        typedValueMap.put(type, value);
106    }
107
108    @Override
109    @SuppressWarnings("unchecked")
110    public <T> T getValueOfType(Class<T> type) throws ViewContextException {
111        if (typedValueMap.containsKey(type)) {
112            return (T) typedValueMap.get(type);
113        }
114
115        if (type.isAssignableFrom(HttpServletRequest.class)) {
116            return (T) req;
117        }
118
119        if (type.isAssignableFrom(HttpSession.class)) {
120            return (T) req.getSession();
121        }
122
123        if (type.isAssignableFrom(Locale.class)) {
124            return (T) req.getLocale();
125        }
126
127        if (type.isAssignableFrom(OutputStream.class)) {
128            try {
129                HttpServletResponse resp = getValueOfType(HttpServletResponse.class);
130                return (T) resp.getOutputStream();
131            } catch (IOException ex) {
132                throw new ViewContextException("Could not get OutputStream", ex);
133            }
134        }
135
136        if (type.isAssignableFrom(PrintWriter.class)) {
137            try {
138                HttpServletResponse resp = getValueOfType(HttpServletResponse.class);
139                return (T) resp.getWriter();
140            } catch (IOException ex) {
141                throw new ViewContextException("Could not get Writer", ex);
142            }
143        }
144
145        if (type.isAssignableFrom(InputStream.class)) {
146            try {
147                return (T) req.getInputStream();
148            } catch (IOException ex) {
149                throw new ViewContextException("Could not get InputStream", ex);
150            }
151        }
152
153        if (type.isAssignableFrom(BufferedReader.class)) {
154            try {
155                return (T) req.getReader();
156            } catch (IOException ex) {
157                throw new ViewContextException("Could not get Reader", ex);
158            }
159        }
160
161        throw new ViewContextException("No value for type " + type.getName());
162    }
163
164    @Override
165    public void setPathParts(Map<String, String> pathParts) {
166        this.pathParts = Collections.unmodifiableMap(pathParts);
167    }
168
169    @Override
170    public Map<String, String> getPathParts() {
171        return pathParts;
172    }
173
174    @Override
175    public void setQualifier(String qualifier) {
176        this.qualifier = qualifier;
177    }
178
179    @Override
180    public String getQualifier() {
181        return qualifier;
182    }
183
184}