1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.decoration;
18
19 import java.io.File;
20 import java.io.Serializable;
21 import java.net.MalformedURLException;
22 import java.net.URL;
23 import java.net.URLClassLoader;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Locale;
27 import java.util.MissingResourceException;
28 import java.util.Properties;
29 import java.util.ResourceBundle;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.jetspeed.util.Path;
34
35 /***
36 * Base class implementing the most common methods shared between
37 * LayoutDecorations and PortletDecorations.
38 *
39 *
40 * @author <href a="mailto:weaver@apache.org">Scott T. Weaver</a>
41 * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
42 *
43 * @see org.apache.jetspeed.decoration.Decoration
44 * @see org.apache.jetspeed.decoration.LayoutDecoration
45 * @see org.apache.jetspeed.decoration.PortletDecoration
46 *
47 */
48 public class BaseDecoration implements Decoration, Serializable
49 {
50 private static final Log log = LogFactory.getLog(BaseDecoration.class);
51
52 protected static final String NO_SUCH_RESOURCE = "no_such_resource";
53 protected transient Properties config;
54 private transient ResourceValidator validator;
55 private final String name;
56 private final Path basePath;
57 private final Path baseClientPath;
58 private transient PathResolverCache cache;
59 private final String commonStylesheet;
60 private final String portalStylesheet;
61 private final String desktopStylesheet;
62 private List actions;
63 private String currentModeAction;
64 private String currentStateAction;
65 private boolean supportsDesktop;
66
67 /***
68 *
69 * @param config <code>java.util.Properties</code> object containing configuration infomation
70 * for this Decoration.
71 * @param validator The ResourceValidator to be used in looking up fully-qualified resource pathes
72 * @param baseClientPath The "root" of the decroation hierarchy.
73 *
74 * @throws InvalidDecorationConfigurationException
75 */
76 public BaseDecoration( Properties config, ResourceValidator validator, Path basePath, Path baseClientPath, PathResolverCache cache )
77 {
78 this.config = config;
79 this.validator = validator;
80 this.basePath = basePath;
81 this.baseClientPath= baseClientPath;
82 this.cache = cache;
83
84 this.name = config.getProperty( "name" );
85
86 this.commonStylesheet = config.getProperty( "stylesheet", DEFAULT_COMMON_STYLE_SHEET );
87
88 this.supportsDesktop = "true".equalsIgnoreCase( config.getProperty( Decoration.DESKTOP_SUPPORTED_PROPERTY ) );
89 if ( this.supportsDesktop )
90 {
91 this.portalStylesheet = config.getProperty( "stylesheet.portal", DEFAULT_PORTAL_STYLE_SHEET );
92 this.desktopStylesheet = config.getProperty( "stylesheet.desktop", DEFAULT_DESKTOP_STYLE_SHEET );
93 }
94 else
95 {
96 this.portalStylesheet = null;
97 this.desktopStylesheet = null;
98 }
99
100 log.info( "BaseDecoration basePath: " + basePath.toString() );
101 log.info( "BaseDecoration baseClientPath: " + baseClientPath.toString() );
102
103 }
104
105 public void init(Properties config, ResourceValidator validator, PathResolverCache cache)
106 {
107 this.config = config;
108 this.validator = validator;
109 this.cache = cache;
110 }
111
112 public String getName()
113 {
114 return name;
115 }
116
117 public String getBasePath()
118 {
119 return basePath.toString();
120 }
121
122 public String getBasePath( String relativePath )
123 {
124 if ( relativePath == null )
125 {
126 return basePath.toString();
127 }
128 return basePath.addSegment( relativePath ).toString();
129 }
130
131 public String getResource( String path )
132 {
133 Path workingPath = baseClientPath.getChild( path );
134
135 String hit = cache.getPath( workingPath.toString());
136 if( hit != null )
137 {
138 return hit;
139 }
140 else
141 {
142 String locatedPath = getResource( baseClientPath, new Path( path ) );
143 if( ! locatedPath.startsWith( NO_SUCH_RESOURCE ) )
144 {
145 if( ! path.startsWith( "/" ) )
146 {
147 locatedPath = locatedPath.substring( 1 );
148 }
149 cache.addPath( workingPath.toString(), locatedPath );
150 return locatedPath;
151 }
152 }
153 return null;
154 }
155
156 /***
157 * Recursively tries to locate a resource.
158 *
159 * @param rootPath initial path to start looking for the <code>searchPath.</code>
160 * The "pruning" of the rootPath of subsequest recursive calls follows the logic
161 * detailed in the {@link Decoration#getResource(String)} method.
162 * @param searchPath relative path to the resource we wish to locate.
163 * @return
164 *
165 * @see Decoration
166 */
167 protected String getResource( Path rootPath, Path searchPath )
168 {
169 String pathString = rootPath.getChild( searchPath ).toString();
170 if( validator.resourceExists( pathString ) )
171 {
172 return pathString;
173 }
174 else if( rootPath.length() > 0 )
175 {
176
177 return getResource( rootPath.removeLastPathSegment(), searchPath );
178 }
179 else
180 {
181 return NO_SUCH_RESOURCE + searchPath.getFileExtension();
182 }
183 }
184
185 public String getStyleSheet()
186 {
187 if ( this.commonStylesheet != null )
188 {
189 return getResource( this.commonStylesheet );
190 }
191 return null;
192 }
193 public String getStyleSheetPortal()
194 {
195 if ( this.portalStylesheet != null )
196 {
197 return getResource( this.portalStylesheet );
198 }
199 return null;
200 }
201 public String getStyleSheetDesktop()
202 {
203 if ( this.desktopStylesheet != null )
204 {
205 return getResource( this.desktopStylesheet );
206 }
207 return null;
208 }
209
210 public List getActions()
211 {
212 if(actions != null)
213 {
214 return actions;
215 }
216 else
217 {
218 return Collections.EMPTY_LIST;
219 }
220 }
221
222 public void setActions( List actions )
223 {
224 this.actions = actions;
225 }
226
227 public String getProperty( String name )
228 {
229 return config.getProperty( name );
230 }
231
232 public String getBaseCSSClass()
233 {
234 return config.getProperty( Decoration.BASE_CSS_CLASS_PROP, getName() );
235 }
236
237 public String getCurrentModeAction()
238 {
239 return this.currentModeAction;
240 }
241 public void setCurrentModeAction( String currentModeAction )
242 {
243 this.currentModeAction = currentModeAction;
244 }
245
246 public String getCurrentStateAction()
247 {
248 return this.currentStateAction;
249 }
250 public void setCurrentStateAction( String currentStateAction )
251 {
252 this.currentStateAction = currentStateAction;
253 }
254
255 public String getResourceBundleName()
256 {
257 return config.getProperty( Decoration.RESOURCE_BUNDLE_PROP );
258 }
259
260 public ResourceBundle getResourceBundle( Locale locale, org.apache.jetspeed.request.RequestContext context )
261 {
262 String resourceDirName = context.getConfig().getServletContext()
263 .getRealPath( getResource( RESOURCES_DIRECTORY_NAME ) );
264 File resourceDir = new File( resourceDirName );
265 String resourceName = getResourceBundleName();
266 if ( resourceName == null )
267 {
268 throw new NullPointerException( "Decoration cannot get ResourceBundle due to null value for decoration property " + Decoration.RESOURCE_BUNDLE_PROP + "." );
269 }
270 if ( !resourceDir.isDirectory() )
271 {
272 throw new MissingResourceException(
273 "Can't find the resource directory: " + resourceDirName,
274 resourceName + "_" + locale, "" );
275 }
276 URL[] urls = new URL[1];
277 try
278 {
279 urls[0] = resourceDir.toURL();
280 }
281 catch ( MalformedURLException e )
282 {
283 throw new MissingResourceException(
284 "The resource directory cannot be parsed as a URL: "
285 + resourceDirName, resourceName + "_" + locale, "");
286 }
287 return ResourceBundle.getBundle( resourceName, locale, new URLClassLoader( urls ) );
288 }
289
290 public boolean supportsDesktop()
291 {
292 return this.supportsDesktop;
293 }
294 }