View Javadoc

1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.jetspeed.portal;
17  
18  // Java imports
19  import java.util.ArrayList;
20  import java.util.Iterator;
21  
22  
23  // ECS imports
24  import org.apache.ecs.ConcreteElement;
25  
26  // Jetspeed imports
27  import org.apache.jetspeed.om.profile.Entry;
28  import org.apache.jetspeed.om.profile.MetaInfo;
29  import org.apache.jetspeed.om.profile.PSMLDocument;
30  import org.apache.jetspeed.om.profile.Parameter;
31  import org.apache.jetspeed.om.profile.Profile;
32  import org.apache.jetspeed.om.profile.psml.PsmlParameter;
33  import org.apache.jetspeed.portal.Portlet;
34  import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
35  import org.apache.jetspeed.services.logging.JetspeedLogger;
36  import org.apache.jetspeed.services.rundata.JetspeedRunData;
37  
38  //Turbine imports
39  import org.apache.turbine.util.RunData;
40  
41  /***
42   * Default Implementation of Jetspeed Portlet Instance.
43   * It implements the methods for getting, setting and removing attributes from 
44   * portlet instance persistence storage.
45   *
46   * In a Jetspeed 1.4x PSML profile, the default XML format for an instance and attribute is:
47   *
48   * <entry>
49   *    <parameter name="someName" value="someValue"/>
50   *
51   * Since this modifies PSMLDocuments, it will make a clone once modification starts.
52   *
53   * @author <a href="mailto:sweaver@rippe.com">Scott Weaver</a>
54   * @author <a href="mailto:ggolden@apache.org">Glenn R. Golden</a>
55   * @version $Id: JetspeedPortletInstance.java,v 1.9 2004/02/23 04:05:35 jford Exp $
56   */
57  public class JetspeedPortletInstance implements PortletInstance
58  {
59      /***
60       * Static initialization of the logger for this class
61       */    
62      private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedPortletInstance.class.getName());    
63      
64      /*** The Profile (and PSMLDocument) that we started with, considered RO */
65      private Profile m_profile = null;
66  
67      /*** The Profile (and PSMLDocument) that we cloned to edit. */
68      private Profile m_clonedProfile = null;
69  
70      /*** The rundata - WARNING: it is VERY DANGEROUS to store rundata like this.
71          Rundata objects are re-used, and are only good within one request.
72          This means that a PortletInstance CANNOTA BE STORED BEYOND A SINGLE REQUEST! */
73      private JetspeedRunData m_rundata = null;
74  
75      /*** 
76       * keeping an instance of the actual Portlet around helps us with
77       * getting information that is not directly available from the PSML profile
78       */
79      private Portlet m_portlet = null;
80      
81      /***
82       * Constructs a PortletInstance from a Portlet and a RunData.
83       *
84       * @param Portlet The parent portlet of this instance.
85       * @param RunData Jetspeed Run Data
86       */
87      public JetspeedPortletInstance(Portlet portlet, RunData data)
88      {
89          this(portlet, ((JetspeedRunData) data).getProfile());
90          m_rundata = (JetspeedRunData)data;
91          
92          // if we are in an edit already, use that as the clone
93          m_clonedProfile = ((JetspeedRunData)data).getCustomizedProfile();
94      }
95  
96     /***
97      * Constructs a PortletInstance from a Portlet and a Profile
98      *
99      * @param Portlet The parent portlet of this instance.
100     * @param Profile The profile containing the instance.
101     */
102     public JetspeedPortletInstance(Portlet portlet, Profile profile)
103     {
104         m_portlet = portlet;
105         m_profile = profile;
106     }    
107  
108      /***
109      * Protect the constructor so it can only be instantitated by
110      * by the PortalPersistenceService
111      */
112     protected JetspeedPortletInstance()
113     {
114         // does nothin'
115     }
116 
117     /***
118      * @see PortletInstance#getAttribute()
119      */
120     public String getAttribute(String name, String dftValue)
121     {
122         Entry entry = getEntry();
123 
124         if (entry == null)
125         {
126             return dftValue;
127         }
128         Parameter attr = entry.getParameter(name);
129         if (attr != null)
130         {
131             return attr.getValue();
132         }
133         else
134         {
135             return dftValue;
136         }
137     }
138 
139     /***
140      * @see PortletInstance#getAttribute()
141      */
142     public String getAttribute(String name)
143     {
144         Entry entry = getEntry();
145 
146         if (entry == null)
147         {
148             return "";
149         }
150         Parameter attr = entry.getParameter(name);
151         if (attr != null)
152         {
153             return attr.getValue();
154         }
155         else
156         {
157             return "";
158         }
159     }
160 
161     /***
162      * @see PortletInstance#setAttribute(String, String)
163      */
164     public void setAttribute(String name, String value)
165     {
166         // make sure we are updating and using the clone now
167         setupForUpdate();
168         
169         Entry entry = getEntry();
170 
171         Parameter attr = entry.getParameter(name);
172          
173          // Setting a attribute to null should just remove it.
174         if(value == null)
175         {
176             removeAttribute(name);
177         }
178         else if (attr != null)
179         {
180             attr.setValue(value);
181         }
182         // If an attribute does not exist, then add it.
183         else
184         {
185             PsmlParameter newAttr = new PsmlParameter();
186             newAttr.setName(name);
187             newAttr.setValue(value);
188             entry.addParameter(newAttr);
189         }
190     }
191 
192     /***
193      * @see PortletInstance#removeAttribute(String)
194      */
195     public void removeAttribute(String name)
196     {
197         // make sure we are updating and using the clone now
198         setupForUpdate();
199         
200         Entry entry = getEntry();
201 
202         // I am assuming that we only allow one parameter per name
203         Iterator params = entry.getParameterIterator();
204         int index = -1;
205         int count = 0;
206         while (params.hasNext())
207         {
208             Parameter param = (Parameter) params.next();
209             if (param.getName().equalsIgnoreCase(name))
210             {
211                 index = count;
212                 break;
213             }
214             count++;
215         }
216 
217         // We have to wait until we are outside the loop to remove
218         // or else we throw a ConcurrentModificationException		
219         if (index != -1)
220         {
221             entry.removeParameter(index);           
222         }
223     }
224 
225     /***
226      * @see PortletInstance#removeAllAttributes()
227      */
228     public void removeAllAttributes()
229     {
230         // make sure we are updating and using the clone now
231         setupForUpdate();
232         
233         Entry entry = getEntry();
234 
235         entry.removeAllParameter();
236     }
237 
238     /***
239      * @see PortletInstance#getAttributes()
240      */
241     public Iterator getAttributes()
242     {
243         Entry entry = getEntry();
244 
245         return entry.getParameterIterator();
246     }
247 
248     /***
249      * @see PortletInstance#getAttributeNames()
250      */
251     public Iterator getAttributeNames()
252     {
253         Iterator itr = getAttributes();
254         ArrayList list = new ArrayList();
255         while(itr.hasNext());
256         {
257             Parameter param = (Parameter) itr.next();
258             list.add(param.getName());
259         }
260         
261         return list.iterator();
262     }
263 
264     /***
265      * @see PortletInstance#getDocument()
266      */
267     public PSMLDocument getDocument()
268     {
269         return getProfile().getDocument();
270     }
271 
272     /***
273      * @see PortletInstance#getProfile()
274      */
275     public Profile getProfile()
276     {
277         // use the clone if we have made it
278         if (m_clonedProfile != null) return m_clonedProfile;
279 
280         return m_profile;
281     }
282 
283     /***
284      * @see PortletInstance#getPortlet()
285      */
286     public Entry getEntry()
287     {
288         return getDocument().getEntryById(m_portlet.getID());
289     }
290 
291     /***
292      * @see PortletInstance#getDescription()
293      */
294     public String getDescription()
295     {
296         Entry entry = getEntry();
297 
298         String description = null;
299         if (entry != null)
300         {
301             MetaInfo metaInfo = entry.getMetaInfo();
302             if (metaInfo != null)
303             {
304                 description = metaInfo.getDescription();
305             }
306         }
307         return m_portlet.getDescription(description);
308     }
309 
310     /***
311      * @see PortletInstance#getName()
312      */
313     public String getName()
314     {
315         return getEntry().getParent();
316     }
317 
318     /***
319      * @see PortletInstance#getTitle()
320      */
321     public String getTitle()
322     {
323         Entry entry = getEntry();
324 
325         String title = null;
326         if (entry != null)
327         {
328             MetaInfo metaInfo = entry.getMetaInfo();
329             if (metaInfo != null)
330             {
331                 title = metaInfo.getTitle();
332             }
333         }
334         return m_portlet.getTitle(title);
335     }
336 
337     /***
338      * @see PortletInstance#getImage()
339      */
340     public String getImage()
341     {
342         Entry entry = getEntry();
343 
344         String image = null;
345         if (entry != null)
346         {
347             MetaInfo metaInfo = entry.getMetaInfo();
348             if (metaInfo != null)
349             {
350                 return image = metaInfo.getImage();
351             }
352         }
353         return m_portlet.getImage(image);
354     }
355 
356     /***
357      * @see PortletInstance#getPortlet()
358      */
359     public Portlet getPortlet()
360     {
361         return m_portlet;
362     }
363     
364     /***
365      * @see PortletInstance#getContent()
366      */
367     public ConcreteElement getContent()
368     {
369       return m_portlet.getContent(m_rundata);
370     }
371     
372     /***
373      * @see PortletInstance#isShowTitleBar()
374      */
375     public boolean isShowTitleBar()
376     {
377       return m_portlet.isShowTitleBar(m_rundata);
378     }
379 
380     /***
381     * Setup for making a change to the Entry
382     * We must not change the PSMLDocument that we started with, instead we make a clone
383     * and start using it.
384     */
385     private void setupForUpdate()
386     {
387         if (m_clonedProfile != null) return;
388         
389         try
390         {
391             m_clonedProfile = (Profile) m_profile.clone();
392         }
393         catch (CloneNotSupportedException e)
394         {
395             logger.warn("JetspeedPortletInstance: cannot clone Profile!: " + e);
396         }
397     }
398 }
399