View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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         if (log.isDebugEnabled())
101         {
102             log.debug( "BaseDecoration basePath: " + basePath.toString() );
103             log.debug( "BaseDecoration baseClientPath: " + baseClientPath.toString() );
104         }
105     }
106     
107     public void init(Properties config, ResourceValidator validator, PathResolverCache cache)
108     {
109         this.config = config;
110         this.validator = validator;
111         this.cache = cache;
112     }    
113 
114     public String getName()
115     {        
116         return name;
117     }
118     
119     public String getBasePath()
120     {
121         return basePath.toString();
122     }
123     
124     public String getBasePath( String relativePath )
125     {
126         if ( relativePath == null )
127         {
128             return basePath.toString();
129         }
130         return basePath.addSegment( relativePath ).toString();
131     }
132         
133     public String getResource( String path )
134     {        
135         Path workingPath = baseClientPath.getChild( path );
136         
137         String hit = cache.getPath( workingPath.toString()); 
138         if(  hit != null )
139         {
140             return hit;
141         }
142         else
143         {
144             String locatedPath = getResource( baseClientPath, new Path( path ) );
145             if( ! locatedPath.startsWith( NO_SUCH_RESOURCE ) )
146             {
147                 if( ! path.startsWith( "/" ) )
148                 {
149                     locatedPath = locatedPath.substring( 1 );
150                 }
151                 cache.addPath( workingPath.toString(), locatedPath );
152                 return locatedPath;
153             }
154         }
155 	    return null;
156     }
157     
158     /***
159      * Recursively tries to locate a resource.
160      * 
161      * @param rootPath initial path to start looking for the <code>searchPath.</code>
162      * The "pruning" of the rootPath of subsequest recursive calls follows the logic
163      * detailed in the {@link Decoration#getResource(String)} method.
164      * @param searchPath relative path to the resource we wish to locate.
165      * @return
166      * 
167      * @see Decoration
168      */
169     protected String getResource( Path rootPath, Path searchPath )
170     {
171         String pathString = rootPath.getChild( searchPath ).toString();
172         if( validator.resourceExists( pathString ) )
173         {
174             return pathString;
175         }
176         else if( rootPath.length() > 0 )
177         {
178             
179             return getResource( rootPath.removeLastPathSegment(), searchPath );
180         }
181         else
182         {
183             return NO_SUCH_RESOURCE + searchPath.getFileExtension();
184         }
185     }
186 
187     public String getStyleSheet()
188     {
189         if ( this.commonStylesheet != null )
190         {
191             return getResource( this.commonStylesheet );
192         }
193         return null;
194     }
195     public String getStyleSheetPortal()
196     {
197         if ( this.portalStylesheet != null )
198         {
199             return getResource( this.portalStylesheet );
200         }
201         return null;
202     }
203     public String getStyleSheetDesktop()
204     {
205         if ( this.desktopStylesheet != null )
206         {
207             return getResource( this.desktopStylesheet );
208         }
209         return null;
210     }
211 
212     public List getActions()
213     {
214        if(actions != null)
215        {
216            return actions;
217        }
218        else
219        {
220            return Collections.EMPTY_LIST;
221        }
222     }
223 
224     public void setActions( List actions )
225     {
226         this.actions = actions;
227     }
228 
229     public String getProperty( String name )
230     {
231         return config.getProperty( name );
232     }
233 
234     public String getBaseCSSClass()
235     {
236         return config.getProperty( Decoration.BASE_CSS_CLASS_PROP, getName() );
237     }
238 
239     public String getCurrentModeAction()
240     {
241         return this.currentModeAction;
242     }
243     public void setCurrentModeAction( String currentModeAction )
244     {
245         this.currentModeAction = currentModeAction;
246     }
247 
248     public String getCurrentStateAction()
249     {
250         return this.currentStateAction;
251     }
252     public void setCurrentStateAction( String currentStateAction )
253     {
254         this.currentStateAction = currentStateAction;
255     }
256     
257     public String getResourceBundleName()
258     {
259         return config.getProperty( Decoration.RESOURCE_BUNDLE_PROP );
260     }
261     
262     public ResourceBundle getResourceBundle( Locale locale, org.apache.jetspeed.request.RequestContext context )
263     {
264         String resourceDirName = context.getConfig().getServletContext()
265                 .getRealPath( getResource( RESOURCES_DIRECTORY_NAME ) );
266         File resourceDir = new File( resourceDirName );
267         String resourceName = getResourceBundleName();
268         if ( resourceName == null )
269         {
270             throw new NullPointerException( "Decoration cannot get ResourceBundle due to null value for decoration property " + Decoration.RESOURCE_BUNDLE_PROP + "." );
271         }
272         if ( !resourceDir.isDirectory() )
273         {
274             throw new MissingResourceException(
275                     "Can't find the resource directory: " + resourceDirName,
276                     resourceName + "_" + locale, "" );
277         }
278         URL[] urls = new URL[1];
279         try
280         {
281             urls[0] = resourceDir.toURL();
282         }
283         catch ( MalformedURLException e )
284         {
285             throw new MissingResourceException(
286                     "The resource directory cannot be parsed as a URL: "
287                             + resourceDirName, resourceName + "_" + locale, "");
288         }
289         return ResourceBundle.getBundle( resourceName, locale, new URLClassLoader( urls ) );
290     }
291     
292     public boolean supportsDesktop()
293     {
294         return this.supportsDesktop;
295     }
296 }