1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.desktop.impl;
18
19 import java.io.IOException;
20 import java.util.Iterator;
21 import java.util.ResourceBundle;
22
23
24 import javax.servlet.RequestDispatcher;
25 import javax.servlet.ServletContext;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.jetspeed.Jetspeed;
30 import org.apache.jetspeed.container.url.BasePortalURL;
31 import org.apache.jetspeed.decoration.DecorationFactory;
32 import org.apache.jetspeed.decoration.Theme;
33 import org.apache.jetspeed.desktop.JetspeedDesktop;
34 import org.apache.jetspeed.desktop.JetspeedDesktopContext;
35 import org.apache.jetspeed.headerresource.HeaderResource;
36 import org.apache.jetspeed.headerresource.HeaderResourceFactory;
37 import org.apache.jetspeed.headerresource.HeaderResourceLib;
38 import org.apache.jetspeed.om.page.Page;
39 import org.apache.jetspeed.request.RequestContext;
40 import org.springframework.web.context.ServletContextAware;
41
42 /***
43 * Desktop Valve
44 *
45 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
46 * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
47 * @version $Id: JetspeedDesktopImpl.java $
48 */
49 public class JetspeedDesktopImpl implements JetspeedDesktop, ServletContextAware
50 {
51 private final static String EOL = "\r\n";
52 private final static String DOJO_CONFIG_LAYOUT_DECORATION_PATH_VAR_NAME = HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME + ".layoutDecorationPath";
53 private final static String DOJO_CONFIG_LAYOUT_VAR_NAME = HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME + ".layoutName";
54 private final static String DOJO_CONFIG_PORTLET_DECORATIONS_PATH_VAR_NAME = HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME + ".portletDecorationsPath";
55 private final static String DOJO_CONFIG_PORTLET_DECORATIONS_ALLOWED_VAR_NAME = HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME + ".portletDecorationsAllowed";
56 private final static String DOJO_CONFIG_ACTION_LABELS_NAME = HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME + ".desktopActionLabels";
57
58 private final static String[] DESKTOP_ACTIONS = new String[] { "menu", "tile", "untile", "heightexpand", "heightnormal", "restore", "removeportlet", "loadportletrender", "loadportletaction", "loadportletupdate", "addportlet", "editpage", "loadpage", "loadpageeditor" };
59 private final static String DESKTOP_ACTION_RESOURCE_NAME_PREFIX = "desktop.action.";
60
61 private static final Log log = LogFactory.getLog( JetspeedDesktopImpl.class );
62
63 private DecorationFactory decorationFactory;
64
65 /*** desktop pipeline servlet path */
66 private String desktopServletPath;
67
68 /*** default extension for layout templates */
69 private String defaultLayoutTemplateExtension;
70
71 /*** spring-fed servlet context property */
72 private ServletContext servletContext;
73
74 /*** tool for directing output to html <head> */
75 private HeaderResourceFactory headerResourceFactory;
76
77 /*** base portal URL to override default URL server info from servlet */
78 private BasePortalURL baseUrlAccess = null;
79
80 public JetspeedDesktopImpl( DecorationFactory decorationFactory, HeaderResourceFactory headerResourceFactory, String desktopServletPath, String defaultLayoutTemplateExtension )
81 {
82 this( decorationFactory, headerResourceFactory, desktopServletPath, defaultLayoutTemplateExtension, null, null, null );
83 }
84 public JetspeedDesktopImpl( DecorationFactory decorationFactory, HeaderResourceFactory headerResourceFactory, String desktopServletPath, String defaultLayoutTemplateExtension, String defaultDesktopLayoutDecoration, String defaultDesktopPortletDecoration )
85 {
86 this( decorationFactory, headerResourceFactory, desktopServletPath, defaultLayoutTemplateExtension, defaultDesktopLayoutDecoration, defaultDesktopPortletDecoration, null );
87 }
88 public JetspeedDesktopImpl( DecorationFactory decorationFactory, HeaderResourceFactory headerResourceFactory, String desktopServletPath, String defaultLayoutTemplateExtension, String defaultDesktopLayoutDecoration, String defaultDesktopPortletDecoration, BasePortalURL baseUrlAccess )
89 {
90 this.decorationFactory = decorationFactory;
91 this.headerResourceFactory = headerResourceFactory;
92
93 if ( desktopServletPath != null && desktopServletPath.length() > 0 )
94 {
95 if ( desktopServletPath.charAt( 0 ) != '/' )
96 desktopServletPath = "/" + desktopServletPath;
97 }
98 this.desktopServletPath = desktopServletPath;
99 if ( this.desktopServletPath == null || this.desktopServletPath.length() == 0 )
100 {
101 log.warn( "JetspeedDesktopImpl initialization is incomplete due to undefined desktop servlet path." );
102 this.desktopServletPath = null;
103 }
104
105 this.defaultLayoutTemplateExtension = defaultLayoutTemplateExtension;
106
107
108 if ( defaultDesktopLayoutDecoration != null && defaultDesktopLayoutDecoration.length() > 0 )
109 {
110 String existingDefaultDesktopLayoutDecoration = decorationFactory.getDefaultDesktopLayoutDecoration();
111 if ( existingDefaultDesktopLayoutDecoration == null || existingDefaultDesktopLayoutDecoration.length() == 0 )
112 {
113 decorationFactory.setDefaultDesktopLayoutDecoration( defaultDesktopLayoutDecoration );
114 }
115 }
116 if ( defaultDesktopPortletDecoration != null && defaultDesktopPortletDecoration.length() > 0 )
117 {
118 String existingDefaultDesktopPortletDecoration = decorationFactory.getDefaultDesktopPortletDecoration();
119 if ( existingDefaultDesktopPortletDecoration == null || existingDefaultDesktopPortletDecoration.length() == 0 )
120 {
121 decorationFactory.setDefaultDesktopPortletDecoration( defaultDesktopPortletDecoration );
122 }
123 }
124
125 this.baseUrlAccess = baseUrlAccess;
126 }
127
128 public void render( RequestContext request )
129 {
130 String layoutDecorationTemplatePath = null;
131 boolean layoutDecorationTemplatePathWasAssigned = false;
132 try
133 {
134 Page page = request.getPage();
135
136
137 request.setAttribute( JetspeedDesktop.DESKTOP_ENABLED_REQUEST_ATTRIBUTE, Boolean.TRUE );
138
139
140 Theme theme = decorationFactory.getTheme( page, request );
141
142 HeaderResource hr = getHeaderResourceFactory().getHeaderResouce( request );
143 JetspeedDesktopContext desktopContext = new JetspeedDesktopContextImpl( request, this.baseUrlAccess, theme, hr, defaultLayoutTemplateExtension );
144
145 String layoutTemplateIdPropertyName = null;
146 if ( "true".equals( request.getRequest().getParameter( "jsprintmode" ) ) )
147 layoutTemplateIdPropertyName = JetspeedDesktopContext.LAYOUT_PRINT_TEMPLATE_ID_PROP;
148
149 layoutDecorationTemplatePath = desktopContext.getLayoutTemplatePath( layoutTemplateIdPropertyName );
150 layoutDecorationTemplatePathWasAssigned = true;
151
152 RequestDispatcher dispatcher = request.getRequest().getRequestDispatcher( layoutDecorationTemplatePath );
153
154 hr.dojoEnable();
155
156 request.getRequest().setAttribute( JetspeedDesktopContext.DESKTOP_CONTEXT_ATTRIBUTE, desktopContext );
157 request.getRequest().setAttribute( JetspeedDesktopContext.DESKTOP_REQUEST_CONTEXT_ATTRIBUTE, request );
158 request.getRequest().setAttribute( JetspeedDesktopContext.DESKTOP_COMPONENT_MANAGER_ATTRIBUTE, Jetspeed.getComponentManager() );
159
160 String portletDecorationsBasePath = decorationFactory.getPortletDecorationsBasePath();
161 String portletDecorationsBaseRelative = portletDecorationsBasePath;
162 if ( portletDecorationsBaseRelative != null && portletDecorationsBaseRelative.length() > 1 && portletDecorationsBaseRelative.indexOf( '/' ) == 0 )
163 {
164 portletDecorationsBaseRelative = portletDecorationsBaseRelative.substring( 1 );
165 }
166 StringBuffer dojoConfigAddOn = new StringBuffer();
167 dojoConfigAddOn.append( " " ).append( DOJO_CONFIG_LAYOUT_DECORATION_PATH_VAR_NAME ).append( " = \"" ).append( desktopContext.getLayoutBasePath() ).append( "\";" ).append( EOL );
168 dojoConfigAddOn.append( " " ).append( DOJO_CONFIG_LAYOUT_VAR_NAME ).append( " = \"" ).append( desktopContext.getLayoutDecorationName() ).append( "\";" ).append( EOL );
169 dojoConfigAddOn.append( " " ).append( DOJO_CONFIG_PORTLET_DECORATIONS_PATH_VAR_NAME ).append( " = \"" ).append( portletDecorationsBasePath ).append( "\";" ).append( EOL );
170 String portletDecorationNamesContent = HeaderResourceLib.makeJSONStringArray( decorationFactory.getDesktopPortletDecorations( request ) );
171 dojoConfigAddOn.append( " " ).append( DOJO_CONFIG_PORTLET_DECORATIONS_ALLOWED_VAR_NAME ).append( " = " ).append( portletDecorationNamesContent ).append( ";" );
172 hr.addHeaderSectionFragment( DOJO_CONFIG_LAYOUT_VAR_NAME, HeaderResource.HEADER_SECTION_DOJO_CONFIG, dojoConfigAddOn.toString() );
173
174 if ( hr.isHeaderSectionIncluded( HeaderResource.HEADER_SECTION_DESKTOP_STYLE_LAYOUT ) )
175 {
176 hr.setHeaderSectionType( HeaderResource.HEADER_SECTION_DESKTOP_STYLE_LAYOUT, HeaderResource.HEADER_TYPE_LINK_TAG );
177 StringBuffer desktopThemeStyleLink = new StringBuffer();
178 int stylesheetCount = 0;
179 Iterator stylesheetIter = theme.getStyleSheets().iterator();
180 while ( stylesheetIter.hasNext() )
181 {
182 String stylesheetHref = (String)stylesheetIter.next();
183 if ( stylesheetHref != null && stylesheetHref.length() > 0 )
184 {
185 if ( ! stylesheetHref.startsWith( portletDecorationsBaseRelative ) )
186 {
187 if ( stylesheetCount > 0 )
188 {
189 desktopThemeStyleLink.append( EOL );
190 }
191 desktopThemeStyleLink.append( "<link rel=\"stylesheet\" type=\"text/css\" media=\"screen, projection\" href=\"" );
192 desktopThemeStyleLink.append( desktopContext.getPortalResourceUrl( stylesheetHref ) ).append( "\"/>" );
193 stylesheetCount++;
194 }
195 }
196 }
197 hr.addHeaderSectionFragment( "desktop.style.layout", HeaderResource.HEADER_SECTION_DESKTOP_STYLE_LAYOUT, desktopThemeStyleLink.toString() );
198 }
199
200
201 StringBuffer desktopActionLabels = new StringBuffer();
202 ResourceBundle messages = desktopContext.getLayoutResourceBundle( request.getLocale() );
203 for ( int i = 0 ; i < DESKTOP_ACTIONS.length ; i++ )
204 {
205 String actionLabel = messages.getString( DESKTOP_ACTION_RESOURCE_NAME_PREFIX + DESKTOP_ACTIONS[ i ] );
206 if ( actionLabel != null )
207 {
208 if ( desktopActionLabels.length() == 0 )
209 {
210 desktopActionLabels.append( "{ " );
211 }
212 else
213 {
214 desktopActionLabels.append( ", " );
215 }
216 desktopActionLabels.append( DESKTOP_ACTIONS[ i ] ).append( ": \"" ).append( actionLabel ).append( "\"" );
217 }
218 }
219 if ( desktopActionLabels.length() > 0 )
220 {
221 dojoConfigAddOn = new StringBuffer();
222 dojoConfigAddOn.append( " " ).append( DOJO_CONFIG_ACTION_LABELS_NAME ).append( " = " ).append( desktopActionLabels.toString() ).append( " };" ).append( EOL );
223 hr.addHeaderSectionFragment( DOJO_CONFIG_ACTION_LABELS_NAME, HeaderResource.HEADER_SECTION_DOJO_CONFIG, dojoConfigAddOn.toString() );
224 }
225
226 dispatcher.include( request.getRequest(), request.getResponse() );
227 }
228 catch ( Exception e )
229 {
230 try
231 {
232 if ( layoutDecorationTemplatePathWasAssigned )
233 {
234 layoutDecorationTemplatePath = ( layoutDecorationTemplatePath == null || layoutDecorationTemplatePath.length() == 0 ? "null" : layoutDecorationTemplatePath );
235 log.error( "Failed to include desktop layout decoration at path " + layoutDecorationTemplatePath, e );
236 request.getResponse().getWriter().println( "Desktop layout decoration " + layoutDecorationTemplatePath + " is not available" );
237 }
238 else
239 {
240 log.error( "Failed to initialize for inclusion of desktop layout decoration", e );
241 request.getResponse().getWriter().println( "Failed to initialize for inclusion of desktop layout decoration" );
242 }
243 }
244 catch ( IOException ioe )
245 {
246 log.error( "Failed to write desktop layout decoration exception information to servlet output writer", ioe );
247 }
248 }
249 }
250
251 public boolean isDesktopEnabled( RequestContext requestContext )
252 {
253 return this.decorationFactory.isDesktopEnabled( requestContext );
254 }
255
256 public ServletContext getServletContext()
257 {
258 return servletContext;
259 }
260
261 public void setServletContext(ServletContext servletContext)
262 {
263 this.servletContext = servletContext;
264 }
265
266 public HeaderResourceFactory getHeaderResourceFactory()
267 {
268 return this.headerResourceFactory;
269 }
270
271
272
273 /***
274 * Desktop servlet path ( e.g. /desktop )
275 *
276 * @return portal base url
277 */
278 public String getDesktopServletPath()
279 {
280 return this.desktopServletPath;
281 }
282
283 /***
284 * Portal base url ( e.g. http://localhost:8080/jetspeed )
285 *
286 * @return portal base url
287 */
288 public String getPortalBaseUrl( RequestContext context )
289 {
290 return HeaderResourceLib.getPortalBaseUrl( context, this.baseUrlAccess );
291 }
292
293 /***
294 * Portal base url ( e.g. http://localhost:8080/jetspeed )
295 *
296 * @return portal base url
297 */
298 public String getPortalBaseUrl( RequestContext context, boolean encode )
299 {
300 String baseurl = getPortalBaseUrl( context );
301 if ( ! encode )
302 {
303 return baseurl;
304 }
305 else
306 {
307 return context.getResponse().encodeURL( baseurl );
308 }
309 }
310
311 /***
312 * Portal base url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/javascript/dojo/ )
313 *
314 * @return portal base url with relativePath argument appended
315 */
316 public String getPortalResourceUrl( RequestContext context, String relativePath )
317 {
318 return getPortalResourceUrl( context, relativePath, false );
319 }
320
321 /***
322 * Portal base url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/javascript/dojo/ )
323 *
324 * @return portal base url with relativePath argument appended
325 */
326 public String getPortalResourceUrl( RequestContext context, String relativePath, boolean encode )
327 {
328 return HeaderResourceLib.getPortalResourceUrl( relativePath, getPortalBaseUrl( context ), encode, context );
329 }
330
331 /***
332 * Portal base servlet url ( e.g. http://localhost:8080/jetspeed/desktop/ )
333 *
334 * @return portal base servlet url
335 */
336 public String getPortalUrl( RequestContext context )
337 {
338 return HeaderResourceLib.getPortalUrl( getPortalBaseUrl( context ), context, getDesktopServletPath() );
339 }
340
341 /***
342 * Portal base servlet url ( e.g. http://localhost:8080/jetspeed/desktop/ )
343 *
344 * @return portal base servlet url
345 */
346 public String getPortalUrl( RequestContext context, boolean encode )
347 {
348 return getPortalUrl( context, null, encode );
349 }
350
351 /***
352 * Portal base servlet url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/desktop/default-page.psml )
353 *
354 * @return portal base servlet url with relativePath argument appended
355 */
356 public String getPortalUrl( RequestContext context, String relativePath )
357 {
358 return getPortalUrl( context, relativePath, false );
359 }
360
361 /***
362 * Portal base servlet url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/desktop/default-page.psml )
363 *
364 * @return portal base servlet url with relativePath argument appended
365 */
366 public String getPortalUrl( RequestContext context, String relativePath, boolean encode )
367 {
368 return HeaderResourceLib.getPortalResourceUrl( relativePath, getPortalUrl( context ), encode, context );
369 }
370 }
371