001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal;
007:
008: import java.io.File;
009: import java.util.Enumeration;
010: import java.util.Hashtable;
011:
012: import javax.servlet.http.HttpServletRequest;
013: import javax.servlet.http.HttpServletResponse;
014: import javax.xml.transform.sax.SAXResult;
015: import javax.xml.transform.sax.TransformerHandler;
016:
017: import org.jasig.portal.channels.BaseChannel;
018: import org.jasig.portal.i18n.LocaleManager;
019: import org.jasig.portal.security.IPerson;
020: import org.jasig.portal.serialize.BaseMarkupSerializer;
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023: import org.jasig.portal.utils.ResourceLoader;
024: import org.jasig.portal.utils.XSLT;
025:
026: import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
027:
028: /**
029: * StandaloneChannelRenderer is meant to be used as a base class for channels
030: * that might be rendered outside of the standard user-layout driven scheme.
031: * (for example CSelectSystemProfile).
032: * @author Peter Kharchenko {@link <a href="mailto:pkharchenko@interactivebusiness.com"">pkharchenko@interactivebusiness.com"</a>}
033: * @version $Revision: 42516 $
034: */
035:
036: public class StandaloneChannelRenderer extends BaseChannel {
037:
038: private static final Log log = LogFactory
039: .getLog(StandaloneChannelRenderer.class);
040:
041: private StylesheetSet set;
042: private MediaManager mediaM;
043: private String channelName;
044: private PortalControlStructures pcs;
045: private BrowserInfo binfo;
046: private LocaleManager lm;
047: private boolean hasEdit = false;
048: private boolean hasAbout = false;
049: private boolean hasHelp = false;
050: private long timeOut; // 10 seconds is the default timeout value
051: private boolean dataIsSet = false;
052: private static final String chanID = "singleton";
053: private static final String fs = File.separator;
054: private static final String relativeSSLLocation = "/org/jasig/portal/tools/ChannelServlet/ChannelServlet.ssl";
055:
056: // Metrics
057: public static final AtomicLong activeRenderers = new AtomicLong();
058: public static AtomicLong maxRenderThreads = new AtomicLong();
059:
060: private static final IChannelRendererFactory cChannelRendererFactory = ChannelRendererFactory
061: .newInstance(StandaloneChannelRenderer.class.getName(),
062: activeRenderers, maxRenderThreads);
063:
064: /**
065: * Initializes the channel and calls setStaticData() on the channel.
066: * @param params a hastable of channel publish/subscribe parameters (<parameter> elements
067: * @param channelName channel name
068: * @param hasHelp determines if the channel supports "help" layout event
069: * @param hasAbout determines if the channel supports "about" layout event
070: * @param hasEdit determines if the channel supports "edit" layout event
071: * @param timeOut channel timeout value in milliseconds
072: * @param person a user IPerson object
073: */
074: public void initialize(Hashtable params, String channelName,
075: boolean hasHelp, boolean hasAbout, boolean hasEdit,
076: long timeOut, IPerson person) throws PortalException {
077: this .set = new StylesheetSet(ResourceLoader
078: .getResourceAsURLString(this .getClass(),
079: relativeSSLLocation));
080: String mediaPropsUrl = ResourceLoader.getResourceAsURLString(
081: this .getClass(), "/properties/media.properties");
082: this .set.setMediaProps(mediaPropsUrl);
083: this .mediaM = MediaManager.getMediaManager();
084: this .channelName = channelName;
085: this .hasHelp = hasHelp;
086: this .hasAbout = hasAbout;
087: this .hasEdit = hasEdit;
088: this .timeOut = timeOut;
089:
090: ChannelStaticData sd = new ChannelStaticData();
091: sd.setChannelSubscribeId(chanID);
092: sd.setTimeout(timeOut);
093: sd.setParameters(params);
094: // get person object from UsreLayoutManager
095: sd.setPerson(person);
096: this .setStaticData(sd);
097: }
098:
099: /**
100: * This request will cause setRuntimeData() method called on the channel. If this method is invoked,
101: * the render() method, which usually invokes setRuntimeData() method will omit the call.
102: * @param req http request
103: */
104: public void prepare(HttpServletRequest req) throws Exception {
105: if (this instanceof IPrivilegedChannel) {
106: ((IPrivilegedChannel) this ).setPortalControlStructures(pcs);
107: }
108: this .setRuntimeData(getRuntimeData(req));
109: dataIsSet = true;
110: }
111:
112: /**
113: * This method will output channel content into the HttpServletResponse's
114: * out stream. Note that setRuntimeData() method is called only if there was
115: * no prior call to prepare() method.
116: * @param req http request
117: * @param res http response
118: */
119: public void render(HttpServletRequest req, HttpServletResponse res)
120: throws Throwable {
121: ChannelRuntimeData rd = null;
122: if (!dataIsSet) {
123: if (this instanceof IPrivilegedChannel) {
124: ((IPrivilegedChannel) this )
125: .setPortalControlStructures(pcs);
126: }
127: rd = getRuntimeData(req);
128: } else {
129: dataIsSet = false;
130: }
131:
132: // start rendering
133: IChannelRenderer cr = cChannelRendererFactory.newInstance(this ,
134: rd, pcs);
135: cr.setTimeout(timeOut);
136: cr.startRendering();
137:
138: // set the output mime type
139: res.setContentType(mediaM.getReturnMimeType(req));
140: // set up the serializer
141: BaseMarkupSerializer ser = mediaM.getSerializer(mediaM
142: .getMedia(req), res.getWriter());
143: ser.asContentHandler();
144: // get the framing stylesheet
145: String xslURI = ResourceLoader.getResourceAsURLString(this
146: .getClass(), set.getStylesheetURI(req));
147: try {
148: TransformerHandler th = XSLT.getTransformerHandler(xslURI);
149: th.setResult(new SAXResult(ser));
150: org.xml.sax.helpers.AttributesImpl atl = new org.xml.sax.helpers.AttributesImpl();
151: atl.addAttribute("", "name", "name", "CDATA", channelName);
152: // add other attributes: hasHelp, hasAbout, hasEdit
153: th.startDocument();
154: th.startElement("", "channel", "channel", atl);
155: ChannelSAXStreamFilter custodian = new ChannelSAXStreamFilter(
156: th);
157: int out = cr.outputRendering(custodian);
158: if (out == IChannelRenderer.RENDERING_TIMED_OUT) {
159: throw new InternalTimeoutException(
160: "The channel has timed out");
161: }
162: th.endElement("", "channel", "channel");
163: th.endDocument();
164: } catch (InternalPortalException ipe) {
165: throw ipe.getCause();
166: }
167: }
168:
169: private ChannelRuntimeData getRuntimeData(HttpServletRequest req) {
170: // construct runtime data
171: this .binfo = new BrowserInfo(req);
172: String acceptLanguage = req.getHeader("Accept-Language");
173: String requestLocalesString = req.getParameter("locale");
174: this .lm = new LocaleManager(this .staticData.getPerson(),
175: acceptLanguage);
176: this .lm.setSessionLocales(LocaleManager
177: .parseLocales(requestLocalesString));
178:
179: Hashtable targetParams = new Hashtable();
180: UPFileSpec upfs = new UPFileSpec(req);
181: String channelTarget = upfs.getTargetNodeId();
182:
183: if (log.isDebugEnabled())
184: log.debug("StandaloneRenderer::render() : channelTarget=\""
185: + channelTarget + "\".");
186: Enumeration en = req.getParameterNames();
187: if (en != null) {
188: while (en.hasMoreElements()) {
189: String pName = (String) en.nextElement();
190: Object[] val = (Object[]) req.getParameterValues(pName);
191: if (val == null) {
192: val = ((IRequestParamWrapper) req)
193: .getObjectParameterValues(pName);
194: }
195: targetParams.put(pName, val);
196: }
197: }
198:
199: ChannelRuntimeData rd = new ChannelRuntimeData();
200: rd.setBrowserInfo(binfo);
201: rd.setLocales(lm.getLocales());
202: rd.setHttpRequestMethod(req.getMethod());
203: rd.setRemoteAddress(req.getRemoteAddr());
204: if (channelTarget != null && chanID.equals(channelTarget)) {
205: rd.setParameters(targetParams);
206: }
207:
208: try {
209: rd.setUPFile(new UPFileSpec(
210: PortalSessionManager.INTERNAL_TAG_VALUE,
211: UPFileSpec.RENDER_METHOD, "servletRoot", chanID,
212: null));
213: } catch (Exception e) {
214: if (log.isDebugEnabled())
215: log
216: .debug("StandaloneRenderer::render() : unable to generate baseActionURL. "
217: + e);
218: }
219:
220: return rd;
221:
222: }
223: }
|