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: */
017: package org.apache.portals.gems.flash;
018:
019: import java.io.IOException;
020: import java.io.StringWriter;
021: import java.util.HashMap;
022: import java.util.Map;
023: import java.util.StringTokenizer;
024: import java.util.Collections;
025: import java.util.Properties;
026:
027: import javax.portlet.ActionRequest;
028: import javax.portlet.ActionResponse;
029: import javax.portlet.PortletException;
030: import javax.portlet.PortletPreferences;
031: import javax.portlet.PortletRequest;
032: import javax.portlet.RenderRequest;
033: import javax.portlet.RenderResponse;
034: import javax.portlet.WindowState;
035: import javax.portlet.PortletConfig;
036:
037: import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
038:
039: import org.apache.velocity.context.Context;
040: import org.apache.velocity.app.VelocityEngine;
041: import org.apache.velocity.Template;
042: import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
043:
044: import org.apache.commons.logging.Log;
045: import org.apache.commons.logging.LogFactory;
046:
047: import org.apache.jetspeed.PortalReservedParameters;
048: import org.apache.jetspeed.desktop.JetspeedDesktop;
049: import org.apache.jetspeed.headerresource.HeaderResourceLib;
050: import org.apache.jetspeed.request.RequestContext;
051:
052: public class FlashPortlet extends GenericVelocityPortlet {
053: public static final String HEIGHT_PREF = "HEIGHT";
054: public static final String WIDTH_PREF = "WIDTH";
055: public static final String SRC_PREF = "SRC";
056: public static final String MAX_SRC_PREF = "MAX-SRC";
057: public static final String MAX_HEIGHT_PREF = "MAX-HEIGHT";
058: public static final String MAX_WIDTH_PREF = "MAX-WIDTH";
059:
060: public static final String OBJECT_PARAMS_INITPARAM = "object-params";
061: public static final String OBJECT_ATTRIBUTES_INITPARAM = "object-attributes";
062: public static final String FLASHVARS_INITPARAM = "flashvars";
063: public static final String VIEW_PAGE_INITPARAM = "ViewPage";
064:
065: public static final String PARAM_VIEW_PAGE = "ViewPage";
066: public static final String PARAM_EDIT_PAGE = "EditPage";
067: public static final String PARAM_VIEW_PAGE_DEFAULT = "org/apache/portals/gems/flash/templates/flash-demo.vm";
068: public static final String PARAM_EDIT_PAGE_DEFAULT = "org/apache/portals/gems/flash/templates/edit-prefs.vm";
069:
070: public static final String CODEBASE = "codebase";
071: public static final String CLASSID = "classid";
072: public static final String NODEID = "id";
073:
074: public static final String SRC = "SRC";
075: public static final String WIDTH = "WIDTH";
076: public static final String HEIGHT = "HEIGHT";
077:
078: public static final String WIDTH_ACTUAL = "widthActual";
079: public static final String HEIGHT_ACTUAL = "heightActual";
080: public static final String HEIGHT_PERCENT = "heightPercent";
081:
082: public static final String OBJECT_PARAMS = "PARAMS";
083: public static final String OBJECT_ATTRIBUTES = "ATTRIBUTES";
084: public static final String FLASHVARS = "FLASHVARS";
085: public static final String EXTRA_SIZE_INFO = "EXTRA_SIZE_INFO";
086:
087: public static final String WINDOW_STATE = "windowState";
088: public static final String NAMESPACE = "NAMESPACE";
089: public static final String REPLACECONTENT_NODEID = "REPLACECONTENT_NODEID";
090: public static final String SWF_VERSION = "SWF_VERSION";
091: public static final String SWF_VERSION_DEFAULT = "9.0.0";
092:
093: public static final String SWFOBJECTS_LIB_URL = "SWFOBJECTS_URL";
094: public static final String EXPRESS_INSTALL_URL = "EXPRESS_INSTALL_URL";
095:
096: public static final String IS_DESKTOP = "IS_DESKTOP";
097:
098: protected Log log = LogFactory.getLog(FlashPortlet.class);
099:
100: protected String viewPage = null;
101: protected String editPage = null;
102:
103: private Map object_parameters = null;
104: private Map object_attributes = null;
105: private Map flash_vars = null;
106:
107: private VelocityEngine engine;
108:
109: public void init(PortletConfig config) throws PortletException {
110: super .init(config);
111:
112: String viewPage = config.getInitParameter(PARAM_VIEW_PAGE);
113: if (viewPage == null || viewPage.length() == 0)
114: viewPage = null;
115: this .viewPage = viewPage;
116:
117: String editPage = config.getInitParameter(PARAM_EDIT_PAGE);
118: if (editPage == null || editPage.length() == 0)
119: editPage = null;
120: this .editPage = editPage;
121:
122: Map objParams = parseSemicolonEqualsDelimitedProps(config
123: .getInitParameter(OBJECT_PARAMS_INITPARAM));
124: Map objAttrs = parseSemicolonEqualsDelimitedProps(config
125: .getInitParameter(OBJECT_ATTRIBUTES_INITPARAM));
126: Map flashVars = parseSemicolonEqualsDelimitedProps(config
127: .getInitParameter(FLASHVARS_INITPARAM));
128:
129: if (objAttrs != null) {
130: objAttrs.remove(CODEBASE);
131: objAttrs.remove(CLASSID);
132: objAttrs.remove(NODEID);
133: this .object_attributes = Collections
134: .unmodifiableMap(objAttrs);
135: }
136:
137: if (objParams != null) {
138: objParams.remove(CODEBASE);
139: objParams.remove(CLASSID);
140: objParams.remove(NODEID);
141: this .object_parameters = Collections
142: .unmodifiableMap(new HashMap(objParams));
143: }
144:
145: if (flashVars != null)
146: this .flash_vars = Collections.unmodifiableMap(flashVars);
147: }
148:
149: protected final Map getDefaultObjectParameters() {
150: return this .object_parameters;
151: }
152:
153: protected final Map getDefaultObjectAttributes() {
154: return this .object_attributes;
155: }
156:
157: protected final Map getDefaultFlashVars() {
158: return this .flash_vars;
159: }
160:
161: protected String getDefaultSwfVersion() {
162: return SWF_VERSION_DEFAULT;
163: }
164:
165: protected Map getObjectParameters(RenderRequest request,
166: RenderResponse response, SWFContext swfContext) {
167: return this .object_parameters;
168: }
169:
170: protected Map getObjectAttributes(RenderRequest request,
171: RenderResponse response, SWFContext swfContext) {
172: return this .object_attributes;
173: }
174:
175: protected Map getFlashVars(RenderRequest request,
176: RenderResponse response, SWFContext swfContext) {
177: return this .flash_vars;
178: }
179:
180: protected void setContextVars(RenderRequest request,
181: RenderResponse response, Context context,
182: SWFContext swfContext) {
183: setParameterContextVars(request, response, context, swfContext);
184: readSwfFileInfo(request, response, context, swfContext);
185: setSizeContextVars(request, response, context, swfContext);
186: setFinalContextVars(request, response, context, swfContext);
187: }
188:
189: protected void setFinalContextVars(RenderRequest request,
190: RenderResponse response, Context context,
191: SWFContext swfContext) {
192: String namespace = response.getNamespace();
193: context.put(NAMESPACE, namespace);
194: context
195: .put(REPLACECONTENT_NODEID, namespace
196: + "_flash_replace");
197:
198: RequestContext requestContext = (RequestContext) request
199: .getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
200:
201: String portalBaseUrl = HeaderResourceLib
202: .getPortalBaseUrl(requestContext);
203: context.put(SWFOBJECTS_LIB_URL, portalBaseUrl
204: + "/javascript/swfobject/swfobject.js");
205: context.put(EXPRESS_INSTALL_URL, portalBaseUrl
206: + "/javascript/swfobject/expressInstall.swf");
207:
208: Boolean desktopEnabled = (Boolean) requestContext
209: .getAttribute(JetspeedDesktop.DESKTOP_ENABLED_REQUEST_ATTRIBUTE);
210: context.put(IS_DESKTOP,
211: ((desktopEnabled == null) ? Boolean.FALSE
212: : desktopEnabled));
213:
214: int swfVersion = (swfContext.getHeader() != null ? swfContext
215: .getHeader().getVersion() : -1);
216: if (swfVersion > 0) {
217: context.put(SWF_VERSION, new Integer(swfVersion).toString()
218: + ".0.0");
219: } else {
220: context.put(SWF_VERSION, getDefaultSwfVersion());
221: }
222: context.put(SRC, swfContext.getSrc());
223: }
224:
225: protected void setParameterContextVars(RenderRequest request,
226: RenderResponse response, Context context,
227: SWFContext swfContext) {
228: context.put(OBJECT_PARAMS, HeaderResourceLib.makeJSONObject(
229: getObjectParameters(request, response, swfContext),
230: true).toString());
231:
232: Map objNodeIdMap = new HashMap();
233: objNodeIdMap.put("id", response.getNamespace() + "_objnode");
234: Map[] attrMaps = new Map[] {
235: getObjectAttributes(request, response, swfContext),
236: objNodeIdMap };
237: context.put(OBJECT_ATTRIBUTES, HeaderResourceLib
238: .makeJSONObject(attrMaps, true).toString());
239:
240: context.put(FLASHVARS, HeaderResourceLib.makeJSONObject(
241: getFlashVars(request, response, swfContext), true)
242: .toString());
243: }
244:
245: protected void readSwfFileInfo(RenderRequest request,
246: RenderResponse response, Context context,
247: SWFContext swfContext) {
248: String swfSrc = swfContext.getSrc();
249: int swfSrcLen = (swfSrc != null ? swfSrc.length() : 0);
250: if (swfSrcLen > 0) {
251: SWFHeader swfH = new SWFHeader();
252: String contextPath = request.getContextPath();
253: int contextPathLen = (contextPath != null ? contextPath
254: .length() : 0);
255: if (contextPathLen > 0 && swfSrcLen > contextPathLen
256: && swfSrc.startsWith(contextPath)) {
257: swfSrc = swfSrc.substring(contextPathLen);
258: }
259: if (swfH.parseHeader(this .getPortletContext()
260: .getResourceAsStream(swfSrc))) {
261: swfContext.setHeader(swfH);
262: }
263: }
264: }
265:
266: protected void setSizeContextVars(RenderRequest request,
267: RenderResponse response, Context context,
268: SWFContext swfContext) {
269: String swfHeight = swfContext.getHeight();
270: String swfWidth = swfContext.getWidth();
271: String swfHeightActual = null;
272: String swfWidthActual = null;
273: SWFHeader header = swfContext.getHeader();
274: if (header != null) {
275: if (header.getHeight() > 0)
276: swfHeightActual = new Integer(header.getHeight())
277: .toString();
278: if (header.getWidth() > 0)
279: swfWidthActual = new Integer(header.getWidth())
280: .toString();
281: }
282:
283: boolean isMaximized = swfContext.isMaximized();
284: if (swfHeight == null) {
285: if (swfHeightActual != null)
286: swfHeight = swfHeightActual;
287: else
288: swfHeight = (isMaximized ? "800" : "250");
289: swfContext.setHeight(swfHeight);
290: }
291: if (swfWidth == null) {
292: swfWidth = "100%"; // ( isMaximized ? "600" : "250" );
293: swfContext.setWidth(swfWidth);
294: }
295: context.put(HEIGHT, swfHeight);
296: context.put(WIDTH, swfWidth);
297:
298: Map extraSizeVars = new HashMap();
299: if (swfHeightActual != null)
300: extraSizeVars.put(HEIGHT_ACTUAL, swfHeightActual);
301: if (swfWidthActual != null)
302: extraSizeVars.put(WIDTH_ACTUAL, swfWidthActual);
303:
304: String heightPercent = swfContext.getHeightPercentage();
305: if (heightPercent != null)
306: extraSizeVars.put(HEIGHT_PERCENT, heightPercent);
307:
308: context.put(EXTRA_SIZE_INFO, HeaderResourceLib.makeJSONObject(
309: extraSizeVars, true).toString());
310: }
311:
312: public void doView(RenderRequest request, RenderResponse response)
313: throws PortletException, IOException {
314: Context context = super .getContext(request);
315: PortletPreferences prefs = request.getPreferences();
316:
317: String swfSrc = null;
318: String swfHeight = null;
319: String swfWidth = null;
320: boolean isMaximized = false;
321:
322: if (request.getWindowState().toString().equals(
323: WindowState.MAXIMIZED.toString())) {
324: isMaximized = true;
325: swfHeight = prefs.getValue(MAX_HEIGHT_PREF, null);
326: swfWidth = prefs.getValue(MAX_WIDTH_PREF, null);
327: swfSrc = prefs.getValue(MAX_SRC_PREF, null);
328: }
329:
330: if (swfHeight == null || swfHeight.length() == 0)
331: swfHeight = prefs.getValue(HEIGHT_PREF, null);
332:
333: if (swfWidth == null || swfWidth.length() == 0)
334: swfWidth = prefs.getValue(WIDTH_PREF, null);
335:
336: if (swfSrc == null || swfSrc.length() == 0)
337: swfSrc = prefs.getValue(SRC_PREF, null);
338:
339: context.put(WINDOW_STATE, ((!isMaximized) ? "normal" : "max"));
340:
341: SWFContext swfContext = new SWFContext(swfSrc, swfHeight,
342: swfWidth, isMaximized);
343: setContextVars(request, response, context, swfContext);
344:
345: if (this .viewPage != null) {
346: super .doView(request, response);
347: } else {
348: processClasspathTemplate(PARAM_VIEW_PAGE_DEFAULT, context,
349: response);
350: }
351: }
352:
353: public void doEdit(RenderRequest request, RenderResponse response)
354: throws PortletException, IOException {
355: if (this .editPage != null) {
356: response.setContentType("text/html");
357: doPreferencesEdit(request, response);
358: } else {
359: setupPreferencesEdit(request, response);
360: processClasspathTemplate(PARAM_EDIT_PAGE_DEFAULT,
361: getContext(request), response);
362: }
363: }
364:
365: protected void processClasspathTemplate(String classpathTemplate,
366: Context context, RenderResponse response)
367: throws PortletException {
368: response.setContentType("text/html");
369: VelocityEngine vEngine = null;
370: synchronized (this ) {
371: vEngine = this .engine;
372: if (vEngine == null) {
373: vEngine = new VelocityEngine();
374: configureClasspathVelocityEngine(vEngine);
375: this .engine = vEngine;
376: }
377: }
378:
379: try {
380: Template template = vEngine.getTemplate(classpathTemplate);
381:
382: StringWriter writer = new StringWriter();
383: template.merge(context, writer);
384: writer.close();
385:
386: response.getPortletOutputStream().write(
387: writer.getBuffer().toString().getBytes());
388: response.getPortletOutputStream().flush();
389: } catch (Exception ex) {
390: String errMsg = "Failed to generate content with classpath based VelocityEngine for "
391: + this .getClass().getName()
392: + " due to "
393: + ex.getClass().getName() + " " + ex.getMessage();
394: log.error(errMsg);
395: throw new PortletException(errMsg);
396: }
397: }
398:
399: protected void configureClasspathVelocityEngine(
400: VelocityEngine vEngine) throws PortletException {
401: try {
402: Properties props = new Properties();
403: props.setProperty(VelocityEngine.RESOURCE_LOADER,
404: "classpath");
405: props.setProperty("classpath."
406: + VelocityEngine.RESOURCE_LOADER + ".class",
407: ClasspathResourceLoader.class.getName());
408: vEngine.init(props);
409: } catch (Exception ex) {
410: String errMsg = "Failed to configure classpath based VelocityEngine for "
411: + this .getClass().getName()
412: + " due to "
413: + ex.getClass().getName() + " " + ex.getMessage();
414: log.error(errMsg);
415: throw new PortletException(errMsg);
416: }
417: }
418:
419: /* (non-Javadoc)
420: * @see org.apache.portals.bridges.velocity.GenericVelocityPortlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
421: */
422: public void processAction(ActionRequest request,
423: ActionResponse response) throws PortletException,
424: IOException {
425: String source = request.getParameter(SRC_PREF);
426: String height = request.getParameter(HEIGHT_PREF);
427: String width = request.getParameter(WIDTH_PREF);
428: String maxSource = request.getParameter(MAX_SRC_PREF);
429: String maxHeight = request.getParameter(MAX_HEIGHT_PREF);
430: String maxWidth = request.getParameter(MAX_WIDTH_PREF);
431:
432: PortletPreferences prefs = request.getPreferences();
433: prefs.setValue(SRC_PREF, source);
434: prefs.setValue(HEIGHT_PREF, height);
435: prefs.setValue(WIDTH_PREF, width);
436: prefs.setValue(MAX_SRC_PREF, maxSource);
437: prefs.setValue(MAX_HEIGHT_PREF, maxHeight);
438: prefs.setValue(MAX_WIDTH_PREF, maxWidth);
439: prefs.store();
440: super .processAction(request, response);
441: }
442:
443: public Map parseSemicolonEqualsDelimitedProps(String propsStr) {
444: if (propsStr == null || propsStr.length() == 0)
445: return null;
446: Map props = new HashMap();
447: StringTokenizer parser = new StringTokenizer(propsStr, ";");
448: String token, propNm, propVal;
449: int eqPos;
450: while (parser.hasMoreTokens()) {
451: token = parser.nextToken();
452: eqPos = token.indexOf('=');
453: if (eqPos > 0) {
454: propNm = token.substring(0, eqPos);
455: if (eqPos < (token.length() - 1)) {
456: propVal = token.substring(eqPos + 1);
457: props.put(propNm.toLowerCase(), propVal);
458: }
459: }
460: }
461: return props;
462: }
463:
464: protected class SWFContext {
465: private String src;
466: private SWFHeader header;
467: private String height;
468: private String height_percentage;
469: private String width;
470: private boolean is_maximized;
471:
472: public SWFContext(String swfSrc, String swfHeight,
473: String swfWidth, boolean isMaximized) {
474: setSrc(swfSrc);
475: setHeight(swfHeight);
476: setWidth(swfWidth);
477: this .is_maximized = isMaximized;
478: }
479:
480: public String getSrc() {
481: return src;
482: }
483:
484: public void setSrc(String src) {
485: if (src == null || src.length() == 0)
486: src = null;
487: this .src = src;
488: }
489:
490: public SWFHeader getHeader() {
491: return header;
492: }
493:
494: public void setHeader(SWFHeader swfHeader) {
495: this .header = swfHeader;
496: }
497:
498: public String getHeight() {
499: return height;
500: }
501:
502: public void setHeight(String height) {
503: if (height == null || height.length() == 0)
504: height = null;
505: else {
506: height = height.trim();
507: if (height.endsWith("%")) {
508: if (height.length() > 1) {
509: this .height_percentage = height;
510: }
511: height = null;
512: }
513: }
514: this .height = height;
515: }
516:
517: public String getHeightPercentage() {
518: return height_percentage;
519: }
520:
521: public String getWidth() {
522: return width;
523: }
524:
525: public void setWidth(String width) {
526: if (width == null || width.length() == 0)
527: width = null;
528: this .width = width;
529: }
530:
531: public boolean isMaximized() {
532: return is_maximized;
533: }
534: }
535: }
|