KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > ui > common > Utils


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.web.ui.common;
18
19 import java.io.BufferedReader JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.StringReader JavaDoc;
22 import java.io.UnsupportedEncodingException JavaDoc;
23 import java.net.URLEncoder JavaDoc;
24 import java.text.DateFormat JavaDoc;
25 import java.text.SimpleDateFormat JavaDoc;
26 import java.util.Calendar JavaDoc;
27 import java.util.Date JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import javax.faces.application.FacesMessage;
34 import javax.faces.component.NamingContainer;
35 import javax.faces.component.UIComponent;
36 import javax.faces.component.UIForm;
37 import javax.faces.context.FacesContext;
38 import javax.faces.context.ResponseWriter;
39 import javax.faces.el.EvaluationException;
40 import javax.faces.el.MethodBinding;
41 import javax.faces.event.AbortProcessingException;
42 import javax.faces.event.ActionEvent;
43
44 import org.alfresco.error.AlfrescoRuntimeException;
45 import org.alfresco.filesys.CIFSServer;
46 import org.alfresco.filesys.server.filesys.DiskSharedDevice;
47 import org.alfresco.filesys.smb.server.repo.ContentContext;
48 import org.alfresco.model.ContentModel;
49 import org.alfresco.repo.security.permissions.AccessDeniedException;
50 import org.alfresco.repo.webdav.WebDAVServlet;
51 import org.alfresco.service.cmr.dictionary.DictionaryService;
52 import org.alfresco.service.cmr.model.FileFolderService;
53 import org.alfresco.service.cmr.model.FileInfo;
54 import org.alfresco.service.cmr.model.FileNotFoundException;
55 import org.alfresco.service.cmr.repository.InvalidNodeRefException;
56 import org.alfresco.service.cmr.repository.NodeRef;
57 import org.alfresco.service.cmr.repository.NodeService;
58 import org.alfresco.service.cmr.repository.Path;
59 import org.alfresco.web.app.Application;
60 import org.alfresco.web.app.servlet.DownloadContentServlet;
61 import org.alfresco.web.app.servlet.ExternalAccessServlet;
62 import org.alfresco.web.bean.NavigationBean;
63 import org.alfresco.web.bean.repository.Node;
64 import org.alfresco.web.bean.repository.Repository;
65 import org.alfresco.web.bean.repository.User;
66 import org.alfresco.web.data.IDataContainer;
67 import org.alfresco.web.ui.common.component.UIStatusMessage;
68 import org.apache.commons.logging.Log;
69 import org.apache.commons.logging.LogFactory;
70 import org.apache.myfaces.renderkit.html.HtmlFormRendererBase;
71 import org.springframework.web.jsf.FacesContextUtils;
72
73 /**
74  * Class containing misc helper methods used by the JSF components.
75  *
76  * @author Kevin Roast
77  */

78 public final class Utils
79 {
80    private static final String JavaDoc MSG_TIME_PATTERN = "time_pattern";
81    private static final String JavaDoc MSG_DATE_PATTERN = "date_pattern";
82    private static final String JavaDoc MSG_DATE_TIME_PATTERN = "date_time_pattern";
83    
84    private static final String JavaDoc IMAGE_PREFIX16 = "/images/filetypes/";
85    private static final String JavaDoc IMAGE_PREFIX32 = "/images/filetypes32/";
86    private static final String JavaDoc IMAGE_POSTFIX = ".gif";
87    private static final String JavaDoc DEFAULT_FILE_IMAGE16 = IMAGE_PREFIX16 + "_default" + IMAGE_POSTFIX;
88    private static final String JavaDoc DEFAULT_FILE_IMAGE32 = IMAGE_PREFIX32 + "_default" + IMAGE_POSTFIX;
89    
90    private static final Map JavaDoc<String JavaDoc, String JavaDoc> s_fileExtensionMap = new HashMap JavaDoc<String JavaDoc, String JavaDoc>(89, 1.0f);
91    
92    private static Log logger = LogFactory.getLog(Utils.class);
93    
94    /**
95     * Private constructor
96     */

97    private Utils()
98    {
99    }
100    
101    /**
102     * Encodes the given string, so that it can be used within an HTML page.
103     *
104     * @param string the String to convert
105     */

106    public static String JavaDoc encode(String JavaDoc string)
107    {
108       if (string == null)
109       {
110          return "";
111       }
112
113       StringBuilder JavaDoc sb = null; //create on demand
114
String JavaDoc enc;
115       char c;
116       for (int i = 0; i < string.length(); i++)
117       {
118          enc = null;
119          c = string.charAt(i);
120          switch (c)
121          {
122             case '"': enc = "&quot;"; break; //"
123
case '&': enc = "&amp;"; break; //&
124
case '<': enc = "&lt;"; break; //<
125
case '>': enc = "&gt;"; break; //>
126

127             //german umlauts
128
case '\u00E4' : enc = "&auml;"; break;
129             case '\u00C4' : enc = "&Auml;"; break;
130             case '\u00F6' : enc = "&ouml;"; break;
131             case '\u00D6' : enc = "&Ouml;"; break;
132             case '\u00FC' : enc = "&uuml;"; break;
133             case '\u00DC' : enc = "&Uuml;"; break;
134             case '\u00DF' : enc = "&szlig;"; break;
135             
136             //misc
137
//case 0x80: enc = "&euro;"; break; sometimes euro symbol is ascii 128, should we suport it?
138
case '\u20AC': enc = "&euro;"; break;
139             case '\u00AB': enc = "&laquo;"; break;
140             case '\u00BB': enc = "&raquo;"; break;
141             case '\u00A0': enc = "&nbsp;"; break;
142             
143             default:
144                if (((int)c) >= 0x80)
145                {
146                   //encode all non basic latin characters
147
enc = "&#" + ((int)c) + ";";
148                }
149                break;
150          }
151          
152          if (enc != null)
153          {
154             if (sb == null)
155             {
156                String JavaDoc soFar = string.substring(0, i);
157                sb = new StringBuilder JavaDoc(i + 8);
158                sb.append(soFar);
159             }
160             sb.append(enc);
161          }
162          else
163          {
164             if (sb != null)
165             {
166                sb.append(c);
167             }
168          }
169       }
170       
171       if (sb == null)
172       {
173          return string;
174       }
175       else
176       {
177          return sb.toString();
178       }
179    }
180    
181    /**
182     * Crop a label within a SPAN element, using ellipses '...' at the end of label and
183     * and encode the result for HTML output. A SPAN will only be generated if the label
184     * is beyond the default setting of 32 characters in length.
185     *
186     * @param text to crop and encode
187     *
188     * @return encoded and cropped resulting label HTML
189     */

190    public static String JavaDoc cropEncode(String JavaDoc text)
191    {
192       return cropEncode(text, 32);
193    }
194    
195    /**
196     * Crop a label within a SPAN element, using ellipses '...' at the end of label and
197     * and encode the result for HTML output. A SPAN will only be generated if the label
198     * is beyond the specified number of characters in length.
199     *
200     * @param text to crop and encode
201     * @param length length of string to crop too
202     *
203     * @return encoded and cropped resulting label HTML
204     */

205    public static String JavaDoc cropEncode(String JavaDoc text, int length)
206    {
207       if (text.length() > length)
208       {
209          String JavaDoc label = text.substring(0, length - 3) + "...";
210          StringBuilder JavaDoc buf = new StringBuilder JavaDoc(length + 32 + text.length());
211          buf.append("<span title=\"")
212             .append(Utils.encode(text))
213             .append("\">")
214             .append(Utils.encode(label))
215             .append("</span>");
216          return buf.toString();
217       }
218       else
219       {
220          return Utils.encode(text);
221       }
222    }
223    
224    /**
225     * Replace one string instance with another within the specified string
226     *
227     * @param str
228     * @param repl
229     * @param with
230     *
231     * @return replaced string
232     */

233    public static String JavaDoc replace(String JavaDoc str, String JavaDoc repl, String JavaDoc with)
234    {
235        int lastindex = 0;
236        int pos = str.indexOf(repl);
237
238        // If no replacement needed, return the original string
239
// and save StringBuffer allocation/char copying
240
if (pos < 0)
241        {
242            return str;
243        }
244        
245        int len = repl.length();
246        int lendiff = with.length() - repl.length();
247        StringBuilder JavaDoc out = new StringBuilder JavaDoc((lendiff <= 0) ? str.length() : (str.length() + (lendiff << 3)));
248        for (; pos >= 0; pos = str.indexOf(repl, lastindex = pos + len))
249        {
250            out.append(str.substring(lastindex, pos)).append(with);
251        }
252        
253        return out.append(str.substring(lastindex, str.length())).toString();
254    }
255    
256    /**
257     * Remove all occurances of a String from a String
258     *
259     * @param str String to remove occurances from
260     * @param match The string to remove
261     *
262     * @return new String with occurances of the match removed
263     */

264    public static String JavaDoc remove(String JavaDoc str, String JavaDoc match)
265    {
266       int lastindex = 0;
267       int pos = str.indexOf(match);
268
269       // If no replacement needed, return the original string
270
// and save StringBuffer allocation/char copying
271
if (pos < 0)
272       {
273           return str;
274       }
275       
276       int len = match.length();
277       StringBuilder JavaDoc out = new StringBuilder JavaDoc(str.length());
278       for (; pos >= 0; pos = str.indexOf(match, lastindex = pos + len))
279       {
280           out.append(str.substring(lastindex, pos));
281       }
282       
283       return out.append(str.substring(lastindex, str.length())).toString();
284    }
285    
286    /**
287     * Replaces carriage returns and line breaks with the &lt;br&gt; tag.
288     *
289     * @param str The string to be parsed
290     * @return The string with line breaks removed
291     */

292    public static String JavaDoc replaceLineBreaks(String JavaDoc str)
293    {
294       String JavaDoc replaced = null;
295       
296       if (str != null)
297       {
298          try
299          {
300             StringBuilder JavaDoc parsedContent = new StringBuilder JavaDoc();
301             BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new StringReader JavaDoc(str));
302             String JavaDoc line = reader.readLine();
303             while (line != null)
304             {
305                parsedContent.append(line).append("<br/>");
306                line = reader.readLine();
307             }
308             
309             replaced = parsedContent.toString();
310          }
311          catch (IOException JavaDoc ioe)
312          {
313             if (logger.isWarnEnabled())
314             {
315                logger.warn("Failed to replace line breaks in string: " + str);
316             }
317          }
318       }
319       
320       return replaced;
321    }
322    
323    /**
324     * Helper to output an attribute to the output stream
325     *
326     * @param out ResponseWriter
327     * @param attr attribute value object (cannot be null)
328     * @param mapping mapping to output as e.g. style="..."
329     *
330     * @throws IOException
331     */

332    public static void outputAttribute(ResponseWriter out, Object JavaDoc attr, String JavaDoc mapping)
333       throws IOException JavaDoc
334    {
335       if (attr != null)
336       {
337          out.write(' ');
338          out.write(mapping);
339          out.write("=\"");
340          out.write(attr.toString());
341          out.write('"');
342       }
343    }
344    
345    /**
346     * Get the hidden field name for any action component.
347     *
348     * All components that wish to simply encode a form value with their client ID can reuse the same
349     * hidden field within the parent form. NOTE: components which use this method must only encode
350     * their client ID as the value and nothing else!
351     *
352     * Build a shared field name from the parent form name and the string "act".
353     *
354     * @return hidden field name shared by all action components within the Form.
355     */

356    public static String JavaDoc getActionHiddenFieldName(FacesContext context, UIComponent component)
357    {
358       return Utils.getParentForm(context, component).getClientId(context) + NamingContainer.SEPARATOR_CHAR + "act";
359    }
360    
361    /**
362     * Helper to recursively render a component and it's child components
363     *
364     * @param context FacesContext
365     * @param component UIComponent
366     *
367     * @throws IOException
368     */

369    public static void encodeRecursive(FacesContext context, UIComponent component)
370       throws IOException JavaDoc
371    {
372       if (component.isRendered() == true)
373       {
374          component.encodeBegin(context);
375          
376          // follow the spec for components that render their children
377
if (component.getRendersChildren() == true)
378          {
379             component.encodeChildren(context);
380          }
381          else
382          {
383             if (component.getChildCount() != 0)
384             {
385                for (Iterator JavaDoc i=component.getChildren().iterator(); i.hasNext(); /**/)
386                {
387                   encodeRecursive(context, (UIComponent)i.next());
388                }
389             }
390          }
391          
392          component.encodeEnd(context);
393       }
394    }
395    
396    /**
397     * Generate the JavaScript to submit set the specified hidden Form field to the
398     * supplied value and submit the parent Form.
399     *
400     * NOTE: the supplied hidden field name is added to the Form Renderer map for output.
401     *
402     * @param context FacesContext
403     * @param component UIComponent to generate JavaScript for
404     * @param fieldId Hidden field id to set value for
405     * @param fieldValue Hidden field value to set hidden field too on submit
406     *
407     * @return JavaScript event code
408     */

409    public static String JavaDoc generateFormSubmit(FacesContext context, UIComponent component, String JavaDoc fieldId, String JavaDoc fieldValue)
410    {
411       return generateFormSubmit(context, component, fieldId, fieldValue, null);
412    }
413    
414    /**
415     * Generate the JavaScript to submit set the specified hidden Form field to the
416     * supplied value and submit the parent Form.
417     *
418     * NOTE: the supplied hidden field name is added to the Form Renderer map for output.
419     *
420     * @param context FacesContext
421     * @param component UIComponent to generate JavaScript for
422     * @param fieldId Hidden field id to set value for
423     * @param fieldValue Hidden field value to set hidden field too on submit
424     * @param params Optional map of param name/values to output
425     *
426     * @return JavaScript event code
427     */

428    public static String JavaDoc generateFormSubmit(FacesContext context, UIComponent component, String JavaDoc fieldId, String JavaDoc fieldValue, Map JavaDoc<String JavaDoc, String JavaDoc> params)
429    {
430       UIForm form = Utils.getParentForm(context, component);
431       if (form == null)
432       {
433          throw new IllegalStateException JavaDoc("Must nest components inside UIForm to generate form submit!");
434       }
435       
436       String JavaDoc formClientId = form.getClientId(context);
437       
438       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
439       buf.append("document.forms[");
440       buf.append("'");
441       buf.append(formClientId);
442       buf.append("'");
443       buf.append("]['");
444       buf.append(fieldId);
445       buf.append("'].value='");
446       buf.append(fieldValue);
447       buf.append("';");
448       
449       if (params != null)
450       {
451          for (String JavaDoc name : params.keySet())
452          {
453             buf.append("document.forms[");
454             buf.append("'");
455             buf.append(formClientId);
456             buf.append("'");
457             buf.append("]['");
458             buf.append(name);
459             buf.append("'].value='");
460             buf.append(params.get(name));
461             buf.append("';");
462             
463             // weak, but this seems to be the way Sun RI do it...
464
//FormRenderer.addNeededHiddenField(context, name);
465
HtmlFormRendererBase.addHiddenCommandParameter(form, name);
466          }
467       }
468       
469       buf.append("document.forms[");
470       buf.append("'");
471       buf.append(formClientId);
472       buf.append("'");
473       buf.append("].submit()");
474       
475       buf.append(";return false;");
476       
477       // weak, but this seems to be the way Sun RI do it...
478
//FormRenderer.addNeededHiddenField(context, fieldId);
479
HtmlFormRendererBase.addHiddenCommandParameter(form, fieldId);
480       
481       return buf.toString();
482    }
483    
484    /**
485     * Generate the JavaScript to submit the parent Form.
486     *
487     * @param context FacesContext
488     * @param component UIComponent to generate JavaScript for
489     *
490     * @return JavaScript event code
491     */

492    public static String JavaDoc generateFormSubmit(FacesContext context, UIComponent component)
493    {
494       UIForm form = Utils.getParentForm(context, component);
495       if (form == null)
496       {
497          throw new IllegalStateException JavaDoc("Must nest components inside UIForm to generate form submit!");
498       }
499       
500       String JavaDoc formClientId = form.getClientId(context);
501       
502       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(48);
503       
504       buf.append("document.forms[");
505       buf.append("'");
506       buf.append(formClientId);
507       buf.append("'");
508       buf.append("].submit()");
509       
510       buf.append(";return false;");
511       
512       return buf.toString();
513    }
514    
515    /**
516     * Enum representing the client URL type to generate
517     */

518    public enum URLMode {HTTP_DOWNLOAD, HTTP_INLINE, WEBDAV, CIFS, SHOW_DETAILS, FTP}
519    
520    /**
521     * Generates a URL for the given usage for the given node.
522     *
523     * The supported values for the usage parameter are of URLMode enum type
524     * @see URLMode
525     *
526     * @param context Faces context
527     * @param node The node to generate the URL for
528     * @param usage What the URL is going to be used for
529     * @return The URL for the requested usage without the context path
530     */

531    public static String JavaDoc generateURL(FacesContext context, Node node, URLMode usage)
532    {
533       String JavaDoc url = null;
534       
535       switch (usage)
536       {
537          case WEBDAV:
538          {
539             // calculate a WebDAV URL for the given node
540
FileFolderService fileFolderService = Repository.getServiceRegistry(
541                   context).getFileFolderService();
542             try
543             {
544                List JavaDoc<FileInfo> paths = fileFolderService.getNamePath(null, node.getNodeRef());
545                User user = Application.getCurrentUser(context);
546                
547                // build up the webdav url
548
StringBuilder JavaDoc path = new StringBuilder JavaDoc("/").append(WebDAVServlet.WEBDAV_PREFIX);
549                
550                // build up the path skipping the first path as it is the root folder
551
boolean homeSpaceFound = false;
552                for (int x = 1; x < paths.size(); x++)
553                {
554                   path.append("/").append(
555                         Utils.replace(URLEncoder.encode(paths.get(x).getName(), "UTF-8"), "+", "%20"));
556                }
557                url = path.toString();
558             }
559             catch (AccessDeniedException e)
560             {
561                // cannot build path if user don't have access all the way up
562
}
563             catch (FileNotFoundException nodeErr)
564             {
565                // cannot build path if file no longer exists
566
}
567             catch (UnsupportedEncodingException JavaDoc encErr)
568             {
569                if (logger.isWarnEnabled())
570                   logger.warn("Failed to calculate webdav url for node: " + node.getNodeRef(), encErr);
571             }
572             break;
573          }
574          
575          case CIFS:
576          {
577             // calculate a CIFS path for the given node
578

579             // get hold of the node service, cifsServer and navigation bean
580
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
581             NavigationBean navBean = (NavigationBean)context.getExternalContext().
582                   getSessionMap().get("NavigationBean");
583             CIFSServer cifsServer = (CIFSServer)FacesContextUtils.getRequiredWebApplicationContext(
584                   context).getBean("cifsServer");
585             
586             if (nodeService != null && navBean != null && cifsServer != null)
587             {
588                DiskSharedDevice diskShare = cifsServer.getConfiguration().getPrimaryFilesystem();
589                
590                if (diskShare != null)
591                {
592                   ContentContext contentCtx = (ContentContext) diskShare.getContext();
593                   NodeRef rootNode = contentCtx.getRootNode();
594                   try
595                   {
596                      Path path = nodeService.getPath(node.getNodeRef());
597                      url = Repository.getNamePath(nodeService, path, rootNode, "\\",
598                            "file:///" + navBean.getCIFSServerPath(diskShare));
599                   }
600                   catch (AccessDeniedException e)
601                   {
602                      // cannot build path if user don't have access all the way up
603
}
604                   catch (InvalidNodeRefException nodeErr)
605                   {
606                      // cannot build path if node no longer exists
607
}
608                }
609             }
610             break;
611          }
612          
613          case HTTP_DOWNLOAD:
614          {
615             url = DownloadContentServlet.generateDownloadURL(node.getNodeRef(), node.getName());
616             break;
617          }
618          
619          case HTTP_INLINE:
620          {
621             url = DownloadContentServlet.generateBrowserURL(node.getNodeRef(), node.getName());
622             break;
623          }
624          
625          case SHOW_DETAILS:
626          {
627             DictionaryService dd = Repository.getServiceRegistry(context).getDictionaryService();
628             
629             // default to showing details of content
630
String JavaDoc outcome = "showDocDetails";
631             
632             // if the node is a type of folder then make the outcome to show space details
633
if (dd.isSubClass(node.getType(), ContentModel.TYPE_FOLDER))
634             {
635                outcome = "showSpaceDetails";
636             }
637             
638             // build the url
639
url = ExternalAccessServlet.generateExternalURL(outcome,
640                   Repository.getStoreRef().getProtocol() + "/" +
641                   Repository.getStoreRef().getIdentifier() + "/" + node.getId());
642             break;
643          }
644          
645          case FTP:
646          {
647             // not implemented yet!
648
break;
649          }
650       }
651       
652       return url;
653    }
654    
655    /**
656     * Build a context path safe image tag for the supplied image path.
657     * Image path should be supplied with a leading slash '/'.
658     *
659     * @param context FacesContext
660     * @param image The local image path from the web folder with leading slash '/'
661     * @param width Width in pixels
662     * @param height Height in pixels
663     * @param alt Optional alt/title text
664     * @param onclick JavaScript onclick event handler code
665     *
666     * @return Populated <code>img</code> tag
667     */

668    public static String JavaDoc buildImageTag(FacesContext context, String JavaDoc image, int width, int height, String JavaDoc alt, String JavaDoc onclick)
669    {
670       return buildImageTag(context, image, width, height, alt, onclick, null);
671    }
672    
673    /**
674     * Build a context path safe image tag for the supplied image path.
675     * Image path should be supplied with a leading slash '/'.
676     *
677     * @param context FacesContext
678     * @param image The local image path from the web folder with leading slash '/'
679     * @param width Width in pixels
680     * @param height Height in pixels
681     * @param alt Optional alt/title text
682     * @param onclick JavaScript onclick event handler code
683     * @param align Optional HTML alignment value
684     *
685     * @return Populated <code>img</code> tag
686     */

687    public static String JavaDoc buildImageTag(FacesContext context, String JavaDoc image, int width, int height, String JavaDoc alt, String JavaDoc onclick, String JavaDoc align)
688    {
689       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(200);
690       
691       buf.append("<img SRC=\"")
692          .append(context.getExternalContext().getRequestContextPath())
693          .append(image)
694          .append("\" width=")
695          .append(width)
696          .append(" height=")
697          .append(height)
698          .append(" border=0");
699       
700       if (alt != null)
701       {
702          alt = Utils.encode(alt);
703          buf.append(" alt=\"")
704             .append(alt)
705             .append("\" title=\"")
706             .append(alt)
707             .append('"');
708       }
709       
710       if (align != null)
711       {
712          buf.append(" align=")
713             .append(align);
714       }
715       
716       if (onclick != null)
717       {
718          buf.append(" onclick=\"")
719             .append(onclick)
720             .append("\" style='cursor:pointer'");
721       }
722       
723       buf.append('>');
724       
725       return buf.toString();
726    }
727    
728    /**
729     * Build a context path safe image tag for the supplied image path.
730     * Image path should be supplied with a leading slash '/'.
731     *
732     * @param context FacesContext
733     * @param image The local image path from the web folder with leading slash '/'
734     * @param width Width in pixels
735     * @param height Height in pixels
736     * @param alt Optional alt/title text
737     *
738     * @return Populated <code>img</code> tag
739     */

740    public static String JavaDoc buildImageTag(FacesContext context, String JavaDoc image, int width, int height, String JavaDoc alt)
741    {
742       return buildImageTag(context, image, width, height, alt, null);
743    }
744    
745    /**
746     * Build a context path safe image tag for the supplied image path.
747     * Image path should be supplied with a leading slash '/'.
748     *
749     * @param context FacesContext
750     * @param image The local image path from the web folder with leading slash '/'
751     * @param alt Optional alt/title text
752     *
753     * @return Populated <code>img</code> tag
754     */

755    public static String JavaDoc buildImageTag(FacesContext context, String JavaDoc image, String JavaDoc alt)
756    {
757       return buildImageTag(context, image, alt, null);
758    }
759    
760    /**
761     * Build a context path safe image tag for the supplied image path.
762     * Image path should be supplied with a leading slash '/'.
763     *
764     * @param context FacesContext
765     * @param image The local image path from the web folder with leading slash '/'
766     * @param alt Optional alt/title text
767     * @param align Optional HTML alignment value
768     *
769     * @return Populated <code>img</code> tag
770     */

771    public static String JavaDoc buildImageTag(FacesContext context, String JavaDoc image, String JavaDoc alt, String JavaDoc align)
772    {
773       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(128);
774       
775       buf.append("<img SRC=\"")
776          .append(context.getExternalContext().getRequestContextPath())
777          .append(image)
778          .append("\" border=0");
779       
780       if (alt != null)
781       {
782          alt = Utils.encode(alt);
783          buf.append(" alt=\"")
784             .append(alt)
785             .append("\" title=\"")
786             .append(alt)
787             .append('"');
788       }
789       if (align != null)
790       {
791          buf.append(" align=")
792             .append(align);
793       }
794       
795       buf.append('>');
796       
797       return buf.toString();
798    }
799    
800    /**
801     * Return the parent UIForm component for the specified UIComponent
802     *
803     * @param context FaceContext
804     * @param component The UIComponent to find parent Form for
805     *
806     * @return UIForm parent or null if none found in hiearachy
807     */

808    public static UIForm getParentForm(FacesContext context, UIComponent component)
809    {
810       UIComponent parent = component.getParent();
811       while (parent != null)
812       {
813          if (parent instanceof UIForm)
814          {
815             break;
816          }
817          parent = parent.getParent();
818       }
819       return (UIForm)parent;
820    }
821    
822    /**
823     * Return the parent UIComponent implementing the NamingContainer interface for
824     * the specified UIComponent.
825     *
826     * @param context FaceContext
827     * @param component The UIComponent to find parent Form for
828     *
829     * @return NamingContainer parent or null if none found in hiearachy
830     */

831    public static UIComponent getParentNamingContainer(FacesContext context, UIComponent component)
832    {
833       UIComponent parent = component.getParent();
834       while (parent != null)
835       {
836          if (parent instanceof NamingContainer)
837          {
838             break;
839          }
840          parent = parent.getParent();
841       }
842       return (UIComponent)parent;
843    }
844    
845    /**
846     * Return the parent UIComponent implementing the IDataContainer interface for
847     * the specified UIComponent.
848     *
849     * @param context FaceContext
850     * @param component The UIComponent to find parent IDataContainer for
851     *
852     * @return IDataContainer parent or null if none found in hiearachy
853     */

854    public static IDataContainer getParentDataContainer(FacesContext context, UIComponent component)
855    {
856       UIComponent parent = component.getParent();
857       while (parent != null)
858       {
859          if (parent instanceof IDataContainer)
860          {
861             break;
862          }
863          parent = parent.getParent();
864       }
865       return (IDataContainer)parent;
866    }
867    
868    /**
869     * Determines whether the given component is disabled or readonly
870     *
871     * @param component The component to test
872     * @return true if the component is either disabled or set to readonly
873     */

874    public static boolean isComponentDisabledOrReadOnly(UIComponent component)
875    {
876       boolean disabled = false;
877       boolean readOnly = false;
878       
879       Object JavaDoc disabledAttr = component.getAttributes().get("disabled");
880       if (disabledAttr != null)
881       {
882          disabled = disabledAttr.equals(Boolean.TRUE);
883       }
884       
885       if (disabled == false)
886       {
887          Object JavaDoc readOnlyAttr = component.getAttributes().get("disabled");
888          if (readOnlyAttr != null)
889          {
890             readOnly = readOnlyAttr.equals(Boolean.TRUE);
891          }
892       }
893
894       return disabled || readOnly;
895    }
896    
897    /**
898     * Invoke the method encapsulated by the supplied MethodBinding
899     *
900     * @param context FacesContext
901     * @param method MethodBinding to invoke
902     * @param event ActionEvent to pass to the method of signature:
903     * public void myMethodName(ActionEvent event)
904     */

905    public static void processActionMethod(FacesContext context, MethodBinding method, ActionEvent event)
906    {
907       try
908       {
909          method.invoke(context, new Object JavaDoc[] {event});
910       }
911       catch (EvaluationException e)
912       {
913          Throwable JavaDoc cause = e.getCause();
914          if (cause instanceof AbortProcessingException)
915          {
916             throw (AbortProcessingException)cause;
917          }
918          else
919          {
920             throw e;
921          }
922       }
923    }
924    
925    /**
926     * Adds a global error message
927     *
928     * @param msg The error message
929     */

930    public static void addErrorMessage(String JavaDoc msg)
931    {
932       addErrorMessage(msg, null);
933    }
934    
935    /**
936     * Adds a global error message and logs exception details
937     *
938     * @param msg The error message
939     * @param err The exception to log
940     */

941    public static void addErrorMessage(String JavaDoc msg, Throwable JavaDoc err)
942    {
943       FacesContext context = FacesContext.getCurrentInstance( );
944       FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
945       context.addMessage(null, facesMsg);
946       if (err != null)
947       {
948          if ((err instanceof InvalidNodeRefException == false &&
949               err instanceof AccessDeniedException == false) || logger.isDebugEnabled())
950          {
951             logger.error(msg, err);
952          }
953       }
954    }
955    
956    /**
957     * Adds a global status message that will be displayed by a Status Message UI component
958     *
959     * @param severity Severity of the message
960     * @param msg Text of the message
961     */

962    public static void addStatusMessage(FacesMessage.Severity severity, String JavaDoc msg)
963    {
964       FacesContext fc = FacesContext.getCurrentInstance();
965       String JavaDoc time = getTimeFormat(fc).format(new Date JavaDoc(System.currentTimeMillis()));
966       FacesMessage fm = new FacesMessage(severity, time, msg);
967       fc.addMessage(UIStatusMessage.STATUS_MESSAGE, fm);
968    }
969    
970    /**
971     * @return the formatter for locale sensitive Time formatting
972     */

973    public static DateFormat JavaDoc getTimeFormat(FacesContext fc)
974    {
975       return getDateFormatFromPattern(fc, Application.getMessage(fc, MSG_TIME_PATTERN));
976    }
977    
978    /**
979     * @return the formatter for locale sensitive Date formatting
980     */

981    public static DateFormat JavaDoc getDateFormat(FacesContext fc)
982    {
983       return getDateFormatFromPattern(fc, Application.getMessage(fc, MSG_DATE_PATTERN));
984    }
985    
986    /**
987     * @return the formatter for locale sensitive Date & Time formatting
988     */

989    public static DateFormat JavaDoc getDateTimeFormat(FacesContext fc)
990    {
991       return getDateFormatFromPattern(fc, Application.getMessage(fc, MSG_DATE_TIME_PATTERN));
992    }
993    
994    /**
995     * @return DataFormat object for the specified pattern
996     */

997    private static DateFormat JavaDoc getDateFormatFromPattern(FacesContext fc, String JavaDoc pattern)
998    {
999       if (pattern == null)
1000      {
1001         throw new IllegalArgumentException JavaDoc("DateTime pattern is mandatory.");
1002      }
1003      try
1004      {
1005         return new SimpleDateFormat JavaDoc(pattern, Application.getLanguage(fc));
1006      }
1007      catch (IllegalArgumentException JavaDoc err)
1008      {
1009         throw new AlfrescoRuntimeException("Invalid DateTime pattern", err);
1010      }
1011   }
1012   
1013   /**
1014    * Parse XML format date YYYY-MM-DDTHH:MM:SS
1015    * @param isoDate
1016    * @return Date or null if failed to parse
1017    */

1018   public static Date JavaDoc parseXMLDateFormat(String JavaDoc isoDate)
1019   {
1020      Date JavaDoc parsed = null;
1021      
1022      try
1023      {
1024         int offset = 0;
1025         
1026         // extract year
1027
int year = Integer.parseInt(isoDate.substring(offset, offset += 4));
1028         if (isoDate.charAt(offset) != '-')
1029         {
1030            throw new IndexOutOfBoundsException JavaDoc("Expected - character but found " + isoDate.charAt(offset));
1031         }
1032         
1033         // extract month
1034
int month = Integer.parseInt(isoDate.substring(offset += 1, offset += 2));
1035         if (isoDate.charAt(offset) != '-')
1036         {
1037            throw new IndexOutOfBoundsException JavaDoc("Expected - character but found " + isoDate.charAt(offset));
1038         }
1039         
1040         // extract day
1041
int day = Integer.parseInt(isoDate.substring(offset += 1, offset += 2));
1042         if (isoDate.charAt(offset) != 'T')
1043         {
1044            throw new IndexOutOfBoundsException JavaDoc("Expected T character but found " + isoDate.charAt(offset));
1045         }
1046         
1047         // extract hours, minutes, seconds and milliseconds
1048
int hour = Integer.parseInt(isoDate.substring(offset += 1, offset += 2));
1049         if (isoDate.charAt(offset) != ':')
1050         {
1051            throw new IndexOutOfBoundsException JavaDoc("Expected : character but found " + isoDate.charAt(offset));
1052         }
1053         int minutes = Integer.parseInt(isoDate.substring(offset += 1, offset += 2));
1054         if (isoDate.charAt(offset) != ':')
1055         {
1056            throw new IndexOutOfBoundsException JavaDoc("Expected : character but found " + isoDate.charAt(offset));
1057         }
1058         int seconds = Integer.parseInt(isoDate.substring(offset += 1 , offset += 2));
1059         
1060         // initialize Calendar object
1061
Calendar JavaDoc calendar = Calendar.getInstance();
1062         calendar.setLenient(false);
1063         calendar.set(Calendar.YEAR, year);
1064         calendar.set(Calendar.MONTH, month - 1);
1065         calendar.set(Calendar.DAY_OF_MONTH, day);
1066         calendar.set(Calendar.HOUR_OF_DAY, hour);
1067         calendar.set(Calendar.MINUTE, minutes);
1068         calendar.set(Calendar.SECOND, seconds);
1069         
1070         // extract the date
1071
parsed = calendar.getTime();
1072      }
1073      catch(IndexOutOfBoundsException JavaDoc e)
1074      {
1075      }
1076      catch(NumberFormatException JavaDoc e)
1077      {
1078      }
1079      catch(IllegalArgumentException JavaDoc e)
1080      {
1081      }
1082      
1083      return parsed;
1084   }
1085
1086   /**
1087    * Return the image path to the filetype icon for the specified file name string
1088    *
1089    * @param name File name to build filetype icon path for
1090    * @param small True for the small 16x16 icon or false for the large 32x32
1091    *
1092    * @return the image path for the specified node type or the default icon if not found
1093    */

1094   public static String JavaDoc getFileTypeImage(String JavaDoc name, boolean small)
1095   {
1096      String JavaDoc image = (small ? DEFAULT_FILE_IMAGE16 : DEFAULT_FILE_IMAGE32);
1097      
1098      int extIndex = name.lastIndexOf('.');
1099      if (extIndex != -1 && name.length() > extIndex + 1)
1100      {
1101         String JavaDoc ext = name.substring(extIndex + 1).toLowerCase();
1102         String JavaDoc key = ext + ' ' + (small ? "16" : "32");
1103         
1104         // found file extension for appropriate size image
1105
synchronized (s_fileExtensionMap)
1106         {
1107            image = s_fileExtensionMap.get(key);
1108            if (image == null)
1109            {
1110               // not found create for first time
1111
image = (small ? IMAGE_PREFIX16 : IMAGE_PREFIX32) + ext + IMAGE_POSTFIX;
1112               
1113               // does this image exist on the web-server?
1114
if (FacesContext.getCurrentInstance().getExternalContext().getResourceAsStream(image) != null)
1115               {
1116                  // found the image for this extension - save it for later
1117
s_fileExtensionMap.put(key, image);
1118               }
1119               else
1120               {
1121                  // not found, save the default image for this extension instead
1122
image = (small ? DEFAULT_FILE_IMAGE16 : DEFAULT_FILE_IMAGE32);
1123                  s_fileExtensionMap.put(key, image);
1124               }
1125            }
1126         }
1127      }
1128      
1129      return image;
1130   }
1131}
1132
Popular Tags