001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution, if
019: * any, must include the following acknowlegement:
020: * "This product includes software developed by the
021: * Caucho Technology (http://www.caucho.com/)."
022: * Alternately, this acknowlegement may appear in the software itself,
023: * if and wherever such third-party acknowlegements normally appear.
024: *
025: * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
026: * endorse or promote products derived from this software without prior
027: * written permission. For written permission, please contact
028: * info@caucho.com.
029: *
030: * 5. Products derived from this software may not be called "Resin"
031: * nor may "Resin" appear in their names without prior written
032: * permission of Caucho Technology.
033: *
034: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037: * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045: *
046: * @author Sam
047: */
048:
049: package com.caucho.portal.generic;
050:
051: import javax.portlet.PortletException;
052: import javax.servlet.ServletConfig;
053: import javax.servlet.ServletException;
054: import javax.servlet.http.HttpServlet;
055: import javax.servlet.http.HttpServletRequest;
056: import javax.servlet.http.HttpServletResponse;
057: import java.io.IOException;
058: import java.lang.reflect.Constructor;
059: import java.lang.reflect.Modifier;
060: import java.util.logging.Logger;
061:
062: /**
063: * This servlet supports the following configuration items.
064: * Items marked with a * can be set as init-param.
065: *
066: * <dl>
067: * <dd>portal
068: * <dt>an instance of {@link Portal}, default is an instance of
069: * {@link GenericPortal}.
070: * <dt>portal-class*
071: * <dd>a class name, an alternative to <code>portal</code>
072: * <dd>layout
073: * <dt>an instance of {@link GenericLayoutWindow}, required
074: * <dt>layout-class*
075: * <dd>a class name, an alternative to <code>layout</code>
076: *
077: * </dl>
078: * </pre>
079: */
080: public class GenericPortalServlet extends HttpServlet {
081: static protected final Logger log = Logger
082: .getLogger(GenericPortalServlet.class.getName());
083:
084: private Portal _portal;
085: private HttpPortletContext _portletContext;
086:
087: private GenericLayoutWindow _layout;
088:
089: /**
090: * Default is an instance of {@link GenericPortal}.
091: */
092: public void setPortal(Portal portal) {
093: if (_portal != null)
094: throw new IllegalArgumentException("`portal' already set");
095:
096: _portal = portal;
097: }
098:
099: /**
100: * An alternative to {@link #setPortal(Portal)}, specify the class
101: * name of an object to instantiate
102: */
103: public void setPortalClass(String className) {
104: setPortal((Portal) newInstance(Portal.class, className));
105: }
106:
107: /**
108: * The layout, required. This method can be called in derived classes,
109: * or through the use of dependency injection on containers that support it,
110: * or indirectly using the init param `layout-class'.
111: */
112: public void setLayout(GenericLayoutWindow layout) {
113: if (_layout != null)
114: throw new IllegalArgumentException(
115: "`layout' is already set");
116:
117: _layout = layout;
118: }
119:
120: /**
121: * An alternative to {@link #setLayout(GenericLayoutWindow)}, specify the
122: * class name of an object to instantiate
123: */
124: public void setLayoutClass(String className) {
125: setLayout((GenericLayoutWindow) newInstance(
126: GenericLayoutWindow.class, className));
127: }
128:
129: public void init(ServletConfig servletConfig)
130: throws ServletException {
131: super .init(servletConfig);
132:
133: String p;
134:
135: p = super .getInitParameter("portal-class");
136: if (p != null)
137: setPortalClass(p);
138:
139: if (_portal == null)
140: _portal = new GenericPortal();
141:
142: p = super .getInitParameter("layout-class");
143: if (p != null)
144: setLayoutClass(p);
145:
146: if (_layout == null)
147: throw new ServletException("`layout' is required");
148:
149: _portletContext = new HttpPortletContext(getServletContext());
150:
151: try {
152: _layout.init(_portletContext);
153: } catch (PortletException ex) {
154: throw new ServletException(ex);
155: }
156: }
157:
158: protected Object newInstance(Class targetClass, String className)
159: throws IllegalArgumentException {
160: Class cl = null;
161:
162: ClassLoader loader = Thread.currentThread()
163: .getContextClassLoader();
164:
165: try {
166: cl = Class.forName(className, false, loader);
167: } catch (ClassNotFoundException e) {
168: }
169:
170: if (cl == null)
171: throw new IllegalArgumentException("`" + className
172: + "' is not a known class");
173:
174: if (!targetClass.isAssignableFrom(cl))
175: throw new IllegalArgumentException("'" + className
176: + "' must implement " + targetClass.getName());
177:
178: if (Modifier.isAbstract(cl.getModifiers()))
179: throw new IllegalArgumentException("'" + className
180: + "' must not be abstract.");
181:
182: if (!Modifier.isPublic(cl.getModifiers()))
183: throw new IllegalArgumentException("'" + className
184: + "' must be public.");
185:
186: Constructor[] constructors = cl.getDeclaredConstructors();
187:
188: Constructor zeroArg = null;
189: for (int i = 0; i < constructors.length; i++) {
190: if (constructors[i].getParameterTypes().length == 0) {
191: zeroArg = constructors[i];
192: break;
193: }
194: }
195:
196: if (zeroArg == null
197: || !Modifier.isPublic(zeroArg.getModifiers()))
198: throw new IllegalArgumentException("'" + className
199: + "' must have a public zero arg constructor");
200:
201: Object obj = null;
202:
203: try {
204: obj = cl.newInstance();
205: } catch (Exception ex) {
206: throw new IllegalArgumentException("error instantiating `"
207: + className + "': " + ex.toString(), ex);
208: }
209:
210: return obj;
211: }
212:
213: protected void doGet(HttpServletRequest req, HttpServletResponse res)
214: throws ServletException, IOException {
215: doRequest(req, res);
216: }
217:
218: protected void doPost(HttpServletRequest req,
219: HttpServletResponse res) throws ServletException,
220: IOException {
221: doRequest(req, res);
222: }
223:
224: protected void doRequest(HttpServletRequest httpRequest,
225: HttpServletResponse httpResponse) throws ServletException,
226: IOException {
227: HttpPortletConnection connection = new HttpPortletConnection();
228: connection.start(_portal, _portletContext, httpRequest,
229: httpResponse, true);
230:
231: try {
232: _layout.processAction(connection);
233: _layout.render(connection);
234: connection.checkForFailure();
235: } catch (PortletException ex) {
236: throw new ServletException(ex);
237: } finally {
238: connection.finish();
239: }
240: }
241:
242: protected void doRequest(PortletConnection connection)
243: throws PortletException, IOException {
244: }
245:
246: public void destroy() {
247: if (_layout != null)
248: _layout.destroy();
249: }
250: }
|