1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.portals.gems.flash;
18
19 import java.io.IOException;
20 import java.io.StringWriter;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.StringTokenizer;
24 import java.util.Collections;
25 import java.util.Properties;
26
27 import javax.portlet.ActionRequest;
28 import javax.portlet.ActionResponse;
29 import javax.portlet.PortletException;
30 import javax.portlet.PortletPreferences;
31 import javax.portlet.PortletRequest;
32 import javax.portlet.RenderRequest;
33 import javax.portlet.RenderResponse;
34 import javax.portlet.WindowState;
35 import javax.portlet.PortletConfig;
36
37 import org.apache.portals.bridges.velocity.GenericVelocityPortlet;
38
39 import org.apache.velocity.context.Context;
40 import org.apache.velocity.app.VelocityEngine;
41 import org.apache.velocity.Template;
42 import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
43
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46
47 import org.apache.jetspeed.PortalReservedParameters;
48 import org.apache.jetspeed.desktop.JetspeedDesktop;
49 import org.apache.jetspeed.headerresource.HeaderResourceLib;
50 import org.apache.jetspeed.request.RequestContext;
51
52 public class FlashPortlet extends GenericVelocityPortlet
53 {
54 public static final String HEIGHT_PREF = "HEIGHT";
55 public static final String WIDTH_PREF = "WIDTH";
56 public static final String SRC_PREF = "SRC";
57 public static final String MAX_SRC_PREF = "MAX-SRC";
58 public static final String MAX_HEIGHT_PREF = "MAX-HEIGHT";
59 public static final String MAX_WIDTH_PREF = "MAX-WIDTH";
60
61 public static final String OBJECT_PARAMS_INITPARAM = "object-params";
62 public static final String OBJECT_ATTRIBUTES_INITPARAM = "object-attributes";
63 public static final String FLASHVARS_INITPARAM = "flashvars";
64 public static final String VIEW_PAGE_INITPARAM = "ViewPage";
65
66 public static final String PARAM_VIEW_PAGE = "ViewPage";
67 public static final String PARAM_EDIT_PAGE = "EditPage";
68 public static final String PARAM_VIEW_PAGE_DEFAULT = "org/apache/portals/gems/flash/templates/flash-demo.vm";
69 public static final String PARAM_EDIT_PAGE_DEFAULT = "org/apache/portals/gems/flash/templates/edit-prefs.vm";
70
71 public static final String CODEBASE = "codebase";
72 public static final String CLASSID = "classid";
73 public static final String NODEID = "id";
74
75 public static final String SRC = "SRC";
76 public static final String WIDTH = "WIDTH";
77 public static final String HEIGHT = "HEIGHT";
78
79 public static final String WIDTH_ACTUAL = "widthActual";
80 public static final String HEIGHT_ACTUAL = "heightActual";
81 public static final String HEIGHT_PERCENT = "heightPercent";
82
83 public static final String OBJECT_PARAMS = "PARAMS";
84 public static final String OBJECT_ATTRIBUTES = "ATTRIBUTES";
85 public static final String FLASHVARS = "FLASHVARS";
86 public static final String EXTRA_SIZE_INFO = "EXTRA_SIZE_INFO";
87
88 public static final String WINDOW_STATE = "windowState";
89 public static final String NAMESPACE = "NAMESPACE";
90 public static final String REPLACECONTENT_NODEID = "REPLACECONTENT_NODEID";
91 public static final String SWF_VERSION = "SWF_VERSION";
92 public static final String SWF_VERSION_DEFAULT = "9.0.0";
93
94 public static final String SWFOBJECTS_LIB_URL = "SWFOBJECTS_URL";
95 public static final String EXPRESS_INSTALL_URL = "EXPRESS_INSTALL_URL";
96
97 public static final String IS_DESKTOP = "IS_DESKTOP";
98
99 protected Log log = LogFactory.getLog( FlashPortlet.class );
100
101 protected String viewPage = null;
102 protected String editPage = null;
103
104 private Map object_parameters = null;
105 private Map object_attributes = null;
106 private Map flash_vars = null;
107
108 private VelocityEngine engine;
109
110
111 public void init( PortletConfig config ) throws PortletException
112 {
113 super.init(config);
114
115 String viewPage = config.getInitParameter( PARAM_VIEW_PAGE );
116 if ( viewPage == null || viewPage.length() == 0 )
117 viewPage = null;
118 this.viewPage = viewPage;
119
120 String editPage = config.getInitParameter( PARAM_EDIT_PAGE );
121 if ( editPage == null || editPage.length() == 0 )
122 editPage = null;
123 this.editPage = editPage;
124
125 Map objParams = parseSemicolonEqualsDelimitedProps( config.getInitParameter( OBJECT_PARAMS_INITPARAM ) );
126 Map objAttrs = parseSemicolonEqualsDelimitedProps( config.getInitParameter( OBJECT_ATTRIBUTES_INITPARAM ) );
127 Map flashVars = parseSemicolonEqualsDelimitedProps( config.getInitParameter( FLASHVARS_INITPARAM ) );
128
129 if ( objAttrs != null )
130 {
131 objAttrs.remove( CODEBASE );
132 objAttrs.remove( CLASSID );
133 objAttrs.remove( NODEID );
134 this.object_attributes = Collections.unmodifiableMap( objAttrs );
135 }
136
137 if ( objParams != null )
138 {
139 objParams.remove( CODEBASE );
140 objParams.remove( CLASSID );
141 objParams.remove( NODEID );
142 this.object_parameters = Collections.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 {
151 return this.object_parameters;
152 }
153 protected final Map getDefaultObjectAttributes()
154 {
155 return this.object_attributes;
156 }
157 protected final Map getDefaultFlashVars()
158 {
159 return this.flash_vars;
160 }
161 protected String getDefaultSwfVersion()
162 {
163 return SWF_VERSION_DEFAULT;
164 }
165
166 protected Map getObjectParameters( RenderRequest request, RenderResponse response, SWFContext swfContext )
167 {
168 return this.object_parameters;
169 }
170 protected Map getObjectAttributes( RenderRequest request, RenderResponse response, SWFContext swfContext )
171 {
172 return this.object_attributes;
173 }
174 protected Map getFlashVars( RenderRequest request, RenderResponse response, SWFContext swfContext )
175 {
176 return this.flash_vars;
177 }
178
179 protected void setContextVars( RenderRequest request, RenderResponse response, Context context, SWFContext swfContext )
180 {
181 setParameterContextVars( request, response, context, swfContext );
182 readSwfFileInfo( request, response, context, swfContext );
183 setSizeContextVars( request, response, context, swfContext );
184 setFinalContextVars( request, response, context, swfContext );
185 }
186
187 protected void setFinalContextVars( RenderRequest request, RenderResponse response, Context context, SWFContext swfContext )
188 {
189 String namespace = response.getNamespace();
190 context.put( NAMESPACE, namespace );
191 context.put( REPLACECONTENT_NODEID, namespace + "_flash_replace" );
192
193 RequestContext requestContext = (RequestContext)request.getAttribute( PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE );
194
195 String portalBaseUrl = HeaderResourceLib.getPortalBaseUrl( requestContext );
196 context.put( SWFOBJECTS_LIB_URL, portalBaseUrl + "/javascript/swfobject/swfobject.js" );
197 context.put( EXPRESS_INSTALL_URL, portalBaseUrl + "/javascript/swfobject/expressInstall.swf" );
198
199 Boolean desktopEnabled = (Boolean)requestContext.getAttribute( JetspeedDesktop.DESKTOP_ENABLED_REQUEST_ATTRIBUTE );
200 context.put( IS_DESKTOP, ( (desktopEnabled == null) ? Boolean.FALSE : desktopEnabled ) );
201
202 int swfVersion = ( swfContext.getHeader() != null ? swfContext.getHeader().getVersion() : -1 );
203 if ( swfVersion > 0 )
204 {
205 context.put( SWF_VERSION, new Integer( swfVersion ).toString() + ".0.0" );
206 }
207 else
208 {
209 context.put( SWF_VERSION, getDefaultSwfVersion() );
210 }
211 context.put( SRC, swfContext.getSrc() );
212 }
213
214 protected void setParameterContextVars( RenderRequest request, RenderResponse response, Context context, SWFContext swfContext )
215 {
216 context.put( OBJECT_PARAMS, HeaderResourceLib.makeJSONObject( getObjectParameters( request, response, swfContext ), true ).toString() );
217
218 Map objNodeIdMap = new HashMap();
219 objNodeIdMap.put( "id", response.getNamespace() + "_objnode" );
220 Map[] attrMaps = new Map[] { getObjectAttributes( request, response, swfContext ), objNodeIdMap };
221 context.put( OBJECT_ATTRIBUTES, HeaderResourceLib.makeJSONObject( attrMaps, true ).toString() );
222
223 context.put( FLASHVARS, HeaderResourceLib.makeJSONObject( getFlashVars( request, response, swfContext ), true ).toString() );
224 }
225
226 protected void readSwfFileInfo( RenderRequest request, RenderResponse response, Context context, SWFContext swfContext )
227 {
228 String swfSrc = swfContext.getSrc();
229 int swfSrcLen = ( swfSrc != null ? swfSrc.length() : 0 );
230 if ( swfSrcLen > 0 )
231 {
232 SWFHeader swfH = new SWFHeader();
233 String contextPath = request.getContextPath();
234 int contextPathLen = ( contextPath != null ? contextPath.length() : 0 );
235 if ( contextPathLen > 0 && swfSrcLen > contextPathLen && swfSrc.startsWith( contextPath ) )
236 {
237 swfSrc = swfSrc.substring( contextPathLen );
238 }
239 if ( swfH.parseHeader( this.getPortletContext().getResourceAsStream( swfSrc ) ) )
240 {
241 swfContext.setHeader( swfH );
242 }
243 }
244 }
245
246 protected void setSizeContextVars( RenderRequest request, RenderResponse response, Context context, SWFContext swfContext )
247 {
248 String swfHeight = swfContext.getHeight();
249 String swfWidth = swfContext.getWidth();
250 String swfHeightActual = null;
251 String swfWidthActual = null;
252 SWFHeader header = swfContext.getHeader();
253 if ( header != null )
254 {
255 if ( header.getHeight() > 0 )
256 swfHeightActual = new Integer( header.getHeight() ).toString();
257 if ( header.getWidth() > 0 )
258 swfWidthActual = new Integer( header.getWidth() ).toString();
259 }
260
261 boolean isMaximized = swfContext.isMaximized();
262 if ( swfHeight == null )
263 {
264 if ( swfHeightActual != null )
265 swfHeight = swfHeightActual;
266 else
267 swfHeight = ( isMaximized ? "800" : "250" );
268 swfContext.setHeight( swfHeight );
269 }
270 if ( swfWidth == null )
271 {
272 swfWidth = "100%";
273 swfContext.setWidth( swfWidth );
274 }
275 context.put( HEIGHT, swfHeight );
276 context.put( WIDTH, swfWidth );
277
278 Map extraSizeVars = new HashMap();
279 if ( swfHeightActual != null )
280 extraSizeVars.put( HEIGHT_ACTUAL, swfHeightActual );
281 if ( swfWidthActual != null )
282 extraSizeVars.put( WIDTH_ACTUAL, swfWidthActual );
283
284 String heightPercent = swfContext.getHeightPercentage();
285 if ( heightPercent != null )
286 extraSizeVars.put( HEIGHT_PERCENT, heightPercent );
287
288 context.put( EXTRA_SIZE_INFO, HeaderResourceLib.makeJSONObject( extraSizeVars, true ).toString() );
289 }
290
291 public void doView(RenderRequest request, RenderResponse response)
292 throws PortletException, IOException
293 {
294 Context context = super.getContext(request);
295 PortletPreferences prefs = request.getPreferences();
296
297 String swfSrc = null;
298 String swfHeight = null;
299 String swfWidth = null;
300 boolean isMaximized = false;
301
302 if ( request.getWindowState().toString().equals( WindowState.MAXIMIZED.toString() ) )
303 {
304 isMaximized = true;
305 swfHeight = prefs.getValue( MAX_HEIGHT_PREF, null );
306 swfWidth = prefs.getValue( MAX_WIDTH_PREF, null );
307 swfSrc = prefs.getValue( MAX_SRC_PREF, null );
308 }
309
310 if ( swfHeight == null || swfHeight.length() == 0 )
311 swfHeight = prefs.getValue( HEIGHT_PREF, null );
312
313 if ( swfWidth == null || swfWidth.length() == 0 )
314 swfWidth = prefs.getValue( WIDTH_PREF, null );
315
316 if ( swfSrc == null || swfSrc.length() == 0 )
317 swfSrc = prefs.getValue( SRC_PREF, null );
318
319 context.put( WINDOW_STATE, ( (! isMaximized) ? "normal" : "max" ) );
320
321 SWFContext swfContext = new SWFContext( swfSrc, swfHeight, swfWidth, isMaximized );
322 setContextVars( request, response, context, swfContext );
323
324 if ( this.viewPage != null )
325 {
326 super.doView( request, response );
327 }
328 else
329 {
330 processClasspathTemplate( PARAM_VIEW_PAGE_DEFAULT, context, response );
331 }
332 }
333
334 public void doEdit( RenderRequest request, RenderResponse response ) throws PortletException, IOException
335 {
336 if ( this.editPage != null )
337 {
338 response.setContentType("text/html");
339 doPreferencesEdit(request, response);
340 }
341 else
342 {
343 setupPreferencesEdit( request, response );
344 processClasspathTemplate( PARAM_EDIT_PAGE_DEFAULT, getContext( request ), response );
345 }
346 }
347
348 protected void processClasspathTemplate( String classpathTemplate, Context context, RenderResponse response ) throws PortletException
349 {
350 response.setContentType("text/html");
351 VelocityEngine vEngine = null;
352 synchronized ( this )
353 {
354 vEngine = this.engine;
355 if ( vEngine == null )
356 {
357 vEngine = new VelocityEngine();
358 configureClasspathVelocityEngine( vEngine );
359 this.engine = vEngine;
360 }
361 }
362
363 try
364 {
365 Template template = vEngine.getTemplate( classpathTemplate );
366
367 StringWriter writer = new StringWriter();
368 template.merge( context, writer );
369 writer.close();
370
371 response.getPortletOutputStream().write( writer.getBuffer().toString().getBytes() );
372 response.getPortletOutputStream().flush();
373 }
374 catch ( Exception ex )
375 {
376 String errMsg = "Failed to generate content with classpath based VelocityEngine for " + this.getClass().getName() + " due to " + ex.getClass().getName() + " " + ex.getMessage();
377 log.error( errMsg );
378 throw new PortletException( errMsg );
379 }
380 }
381
382 protected void configureClasspathVelocityEngine( VelocityEngine vEngine ) throws PortletException
383 {
384 try
385 {
386 Properties props = new Properties();
387 props.setProperty( VelocityEngine.RESOURCE_LOADER, "classpath" );
388 props.setProperty( "classpath." + VelocityEngine.RESOURCE_LOADER + ".class", ClasspathResourceLoader.class.getName() );
389 vEngine.init( props );
390 }
391 catch ( Exception ex )
392 {
393 String errMsg = "Failed to configure classpath based VelocityEngine for " + this.getClass().getName() + " due to " + ex.getClass().getName() + " " + ex.getMessage();
394 log.error( errMsg );
395 throw new PortletException( errMsg );
396 }
397 }
398
399
400
401
402
403 public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException
404 {
405 String source = request.getParameter(SRC_PREF);
406 String height = request.getParameter(HEIGHT_PREF);
407 String width = request.getParameter(WIDTH_PREF);
408 String maxSource = request.getParameter(MAX_SRC_PREF);
409 String maxHeight = request.getParameter(MAX_HEIGHT_PREF);
410 String maxWidth = request.getParameter(MAX_WIDTH_PREF);
411
412 PortletPreferences prefs = request.getPreferences();
413 prefs.setValue(SRC_PREF, source);
414 prefs.setValue(HEIGHT_PREF, height);
415 prefs.setValue(WIDTH_PREF, width);
416 prefs.setValue(MAX_SRC_PREF, maxSource);
417 prefs.setValue(MAX_HEIGHT_PREF, maxHeight);
418 prefs.setValue(MAX_WIDTH_PREF, maxWidth);
419 prefs.store();
420 super.processAction(request, response);
421 }
422
423 public Map parseSemicolonEqualsDelimitedProps( String propsStr )
424 {
425 if ( propsStr == null || propsStr.length() == 0 )
426 return null;
427 Map props = new HashMap();
428 StringTokenizer parser = new StringTokenizer( propsStr, ";" );
429 String token, propNm, propVal;
430 int eqPos;
431 while ( parser.hasMoreTokens() )
432 {
433 token = parser.nextToken();
434 eqPos = token.indexOf( '=' );
435 if ( eqPos > 0 )
436 {
437 propNm = token.substring( 0, eqPos );
438 if ( eqPos < (token.length() -1) )
439 {
440 propVal = token.substring( eqPos + 1 );
441 props.put( propNm.toLowerCase(), propVal );
442 }
443 }
444 }
445 return props;
446 }
447
448 protected class SWFContext
449 {
450 private String src;
451 private SWFHeader header;
452 private String height;
453 private String height_percentage;
454 private String width;
455 private boolean is_maximized;
456 public SWFContext( String swfSrc, String swfHeight, String swfWidth, boolean isMaximized )
457 {
458 setSrc( swfSrc );
459 setHeight( swfHeight );
460 setWidth( swfWidth );
461 this.is_maximized = isMaximized;
462 }
463 public String getSrc()
464 {
465 return src;
466 }
467 public void setSrc( String src )
468 {
469 if ( src == null || src.length() == 0 )
470 src = null;
471 this.src = src;
472 }
473 public SWFHeader getHeader()
474 {
475 return header;
476 }
477 public void setHeader( SWFHeader swfHeader )
478 {
479 this.header = swfHeader;
480 }
481 public String getHeight()
482 {
483 return height;
484 }
485 public void setHeight( String height )
486 {
487 if ( height == null || height.length() == 0 )
488 height = null;
489 else
490 {
491 height = height.trim();
492 if ( height.endsWith("%") )
493 {
494 if ( height.length() > 1 )
495 {
496 this.height_percentage = height;
497 }
498 height = null;
499 }
500 }
501 this.height = height;
502 }
503 public String getHeightPercentage()
504 {
505 return height_percentage;
506 }
507 public String getWidth()
508 {
509 return width;
510 }
511 public void setWidth( String width )
512 {
513 if ( width == null || width.length() == 0 )
514 width = null;
515 this.width = width;
516 }
517 public boolean isMaximized()
518 {
519 return is_maximized;
520 }
521 }
522 }