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: */package org.apache.geronimo.console.servlet;
017:
018: import org.apache.commons.logging.Log;
019: import org.apache.commons.logging.LogFactory;
020: import org.apache.geronimo.console.gbean.ContextForward;
021: import org.apache.geronimo.gbean.AbstractName;
022: import org.apache.geronimo.gbean.AbstractNameQuery;
023: import org.apache.geronimo.kernel.Kernel;
024: import org.apache.geronimo.kernel.KernelRegistry;
025: import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter;
026: import org.apache.geronimo.kernel.lifecycle.LifecycleListener;
027:
028: import javax.servlet.RequestDispatcher;
029: import javax.servlet.ServletConfig;
030: import javax.servlet.ServletContext;
031: import javax.servlet.ServletException;
032: import javax.servlet.http.HttpServlet;
033: import javax.servlet.http.HttpServletRequest;
034: import javax.servlet.http.HttpServletResponse;
035: import java.io.IOException;
036: import java.util.HashMap;
037: import java.util.Iterator;
038: import java.util.Map;
039: import java.util.Set;
040:
041: /**
042: * Servlet that forwards GET and POST requests to a servlet in an alternate
043: * context. The servlet path and alternate context are defined in GBeans of
044: * type ContextForward, and this one servlet handles the forwarding for all
045: * those different paths.
046: *
047: * NOTE: This does not work for DWR, because it changes the request path info
048: * while forwarding, and DWR requires the exact initial request info in order
049: * to construct URLs in the data that it returns. It should work to forward
050: * to most typical servlets, JSPs, and static content.
051: */
052: public class GenericForwardServlet extends HttpServlet {
053: private final static Log log = LogFactory
054: .getLog(GenericForwardServlet.class);
055: private Map forwards = new HashMap(); // Maps a prefix String to ForwardData
056: private Kernel kernel;
057: private LifecycleListener listener;
058:
059: public void init(ServletConfig config) throws ServletException {
060: super .init(config);
061:
062: kernel = KernelRegistry.getSingleKernel();
063: AbstractNameQuery query = new AbstractNameQuery(
064: ContextForward.class.getName());
065: Set set = kernel.listGBeans(query);
066: for (Iterator it = set.iterator(); it.hasNext();) {
067: AbstractName name = (AbstractName) it.next();
068: addGBean(name);
069: }
070: kernel.getLifecycleMonitor().addLifecycleListener(
071: listener = new LifecycleAdapter() {
072: public void running(AbstractName abstractName) {
073: addGBean(abstractName);
074: }
075:
076: public void stopping(AbstractName abstractName) {
077: removeGBean(abstractName);
078: }
079:
080: public void stopped(AbstractName abstractName) {
081: removeGBean(abstractName);
082: }
083:
084: public void failed(AbstractName abstractName) {
085: removeGBean(abstractName);
086: }
087:
088: public void unloaded(AbstractName abstractName) {
089: removeGBean(abstractName);
090: }
091: }, query);
092: }
093:
094: public void destroy() {
095: if (listener != null) {
096: kernel.getLifecycleMonitor().removeLifecycleListener(
097: listener);
098: listener = null;
099: }
100: }
101:
102: private void addGBean(AbstractName name) {
103: ContextForward forward = (ContextForward) kernel
104: .getProxyManager().createProxy(name,
105: ContextForward.class);
106: forwards.put(forward.getPortalPathPrefix(), new ForwardData(
107: getServletContext().getContext(
108: forward.getPortletContextPath()), forward
109: .getPortletServletPath(), name));
110: }
111:
112: private void removeGBean(AbstractName name) {
113: for (Iterator it = forwards.entrySet().iterator(); it.hasNext();) {
114: Map.Entry entry = (Map.Entry) it.next();
115: ForwardData data = (ForwardData) entry.getValue();
116: if (data.getGbean().equals(name)) {
117: it.remove();
118: break;
119: }
120: }
121: }
122:
123: public void doGet(HttpServletRequest req, HttpServletResponse resp)
124: throws ServletException, IOException {
125: doPost(req, resp);
126: }
127:
128: public void doPost(HttpServletRequest req, HttpServletResponse resp)
129: throws ServletException, IOException {
130: String path = req.getPathInfo();
131: if (path == null) {
132: log
133: .error("Unable to forward request; no path information provided. Path is used to identify where to forward to.");
134: return;
135: }
136: ForwardData forward = null;
137: for (Iterator it = forwards.keySet().iterator(); it.hasNext();) {
138: String prefix = (String) it.next();
139: if (path.startsWith(prefix)) {
140: forward = (ForwardData) forwards.get(prefix);
141: path = path.substring(prefix.length());
142: }
143: }
144: if (forward == null) {
145: log
146: .error("Unable to forward URL "
147: + path
148: + "; does not match any known ContextForward definitions.");
149: return;
150: }
151: if (!path.equals("") && !path.startsWith("/"))
152: path = "/" + path;
153: String queryString = req.getQueryString();
154: if (queryString != null) {
155: path += "?" + queryString;
156: }
157: path = forward.getServletPath() + path;
158: RequestDispatcher dispatcher = forward.getForwardContext()
159: .getRequestDispatcher(path);
160: dispatcher.forward(req, resp);
161: }
162:
163: private static class ForwardData {
164: private ServletContext forwardContext;
165: private String servletPath;
166: private AbstractName gbean;
167:
168: public ForwardData(ServletContext forwardContext,
169: String servletPath, AbstractName gbean) {
170: this .forwardContext = forwardContext;
171: this .servletPath = servletPath;
172: this .gbean = gbean;
173: }
174:
175: public ServletContext getForwardContext() {
176: return forwardContext;
177: }
178:
179: public String getServletPath() {
180: return servletPath;
181: }
182:
183: public AbstractName getGbean() {
184: return gbean;
185: }
186: }
187: }
|