KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > tigris > scarab > util > ScarabLink


1 package org.tigris.scarab.util;
2
3 /* ================================================================
4  * Copyright (c) 2000-2002 CollabNet. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowlegement: "This product includes
19  * software developed by Collab.Net <http://www.Collab.Net/>."
20  * Alternately, this acknowlegement may appear in the software itself, if
21  * and wherever such third-party acknowlegements normally appear.
22  *
23  * 4. The hosted project names must not be used to endorse or promote
24  * products derived from this software without prior written
25  * permission. For written permission, please contact info@collab.net.
26  *
27  * 5. Products derived from this software may not use the "Tigris" or
28  * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
29  * prior written permission of Collab.Net.
30  *
31  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
32  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
35  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
37  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
39  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  *
43  * ====================================================================
44  *
45  * This software consists of voluntary contributions made by many
46  * individuals on behalf of Collab.Net.
47  */

48
49 import java.util.Enumeration JavaDoc;
50
51 import org.apache.fulcrum.parser.ParameterParser;
52 import org.apache.fulcrum.parser.ValueParser;
53 import org.apache.fulcrum.pool.InitableRecyclable;
54 import org.apache.turbine.DynamicURI;
55 import org.apache.turbine.RunData;
56 import org.apache.turbine.Turbine;
57 import org.apache.turbine.tool.TemplateLink;
58 import org.tigris.scarab.om.Issue;
59 import org.tigris.scarab.om.Module;
60 import org.tigris.scarab.om.ModuleManager;
61 import org.tigris.scarab.om.ScarabUser;
62 import org.tigris.scarab.services.security.ScarabSecurity;
63
64 /**
65  * This class adds a ModuleManager.CURRENT_PROJECT to every link. This class is added
66  * into the context to replace the $link that Turbine adds.
67  *
68  * @author <a HREF="mailto:jon@collab.net">Jon S. Stevens</a>
69  * @author <a HREF="mailto:jmcnally@collab.net">John McNally</a>
70  * @author <a HREF="mailto:maartenc@tigris.org">Maarten Coene</a>
71  * @version $Id: ScarabLink.java 9476 2005-03-16 22:56:11Z dabbous $
72  */

73 public class ScarabLink extends TemplateLink
74     implements InitableRecyclable, SkipFiltering
75 {
76     private RunData data;
77     private String JavaDoc label;
78     private String JavaDoc attributeText;
79     private String JavaDoc alternateText;
80     private String JavaDoc currentModuleId;
81     private String JavaDoc lastUsedModuleId;
82     private Module currentModule;
83     private Module lastUsedModule;
84     private boolean isOmitModule;
85     private boolean overrideSecurity;
86
87     /**
88      * Constructor.
89      *
90      */

91     public ScarabLink()
92     {
93     }
94
95     /**
96      * This will initialise a TemplateLink object that was
97      * constructed with the default constructor (ApplicationTool
98      * method).
99      *
100      * @param data assumed to be a RunData object
101      */

102     public void init(Object JavaDoc data)
103     {
104         // we just blithely cast to RunData as if another object
105
// or null is passed in we'll throw an appropriate runtime
106
// exception.
107
super.init(data);
108         this.data = (RunData)data;
109         setAbsolute(false);
110     }
111
112     public void refresh()
113     {
114         super.refresh();
115         setAbsolute(false);
116         label = null;
117         attributeText = null;
118         alternateText = null;
119         lastUsedModuleId = null;
120         lastUsedModule = null;
121         super.setPage(null);
122         super.removePathInfo(ScarabConstants.TEMPLATE);
123         isOmitModule = false;
124         overrideSecurity = false;
125     }
126
127     private void initCurrentModule()
128     {
129         if (currentModule == null)
130         {
131             ScarabUser user = (ScarabUser)data.getUser();
132             if (user != null)
133             {
134                 currentModule = user.getCurrentModule();
135             }
136         }
137     }
138
139     /**
140      * Gets the server name.
141      *
142      * @return A String with the server name.
143      */

144     public String JavaDoc getServerName()
145     {
146         initCurrentModule();
147         String JavaDoc result = null;
148         if (currentModule != null)
149         {
150             result = currentModule.getHttpDomain();
151         }
152         if (result == null || result.length() == 0)
153         {
154             result = super.getServerName();
155         }
156         return result;
157     }
158
159     /**
160      * Gets the server port.
161      *
162      * @return A String with the server port.
163      */

164     public int getServerPort()
165     {
166         initCurrentModule();
167         int result = -1;
168         try
169         {
170             if (currentModule != null)
171             {
172                 String JavaDoc port = currentModule.getPort();
173                 if (port.length() == 0)
174                 {
175                     result = super.getServerPort();
176                 }
177                 else
178                 {
179                     result = Integer.parseInt(port);
180                 }
181             }
182         }
183         catch (Exception JavaDoc e)
184         {
185             Log.get().debug("Could not parse port number", e);
186         }
187         if (result == -1)
188         {
189             result = super.getServerPort();
190         }
191         return result;
192     }
193
194     /**
195      * Gets the server scheme (HTTP or HTTPS).
196      *
197      * @return A String with the server scheme.
198      */

199     public String JavaDoc getServerScheme()
200     {
201         initCurrentModule();
202         String JavaDoc result = null;
203         try
204         {
205             if (currentModule != null)
206             {
207                 result = currentModule.getScheme();
208             }
209         }
210         catch (Exception JavaDoc e)
211         {
212             Log.get().debug("Could not get scheme parameter", e);
213         }
214         if (result == null || result.length() == 0)
215         {
216             result = super.getServerScheme();
217         }
218         return result;
219     }
220
221     /**
222      * Gets the server scriptName (/s).
223      *
224      * @return A String with the server scriptName.
225      */

226     public String JavaDoc getScriptName()
227     {
228         initCurrentModule();
229         String JavaDoc result = null;
230         try
231         {
232             if (currentModule != null)
233             {
234                 result = currentModule.getScriptName();
235             }
236         }
237         catch (Exception JavaDoc e)
238         {
239             Log.get().debug("Could not get script name parameter", e);
240         }
241         if (result == null || result.length() == 0)
242         {
243             result = super.getScriptName();
244         }
245         return result;
246     }
247
248     /**
249      * Sets the template variable used by the Template Service.
250      *
251      * @param t A String with the template name.
252      * @return A TemplateLink.
253      */

254     public TemplateLink setPage(String JavaDoc t)
255     {
256         String JavaDoc moduleid = data.getParameters().getString(ScarabConstants.CURRENT_MODULE);
257         return setPage(t, moduleid);
258     }
259    
260     /**
261      * Causes the link to not include the module id. Useful for templates
262      * where a module is not required or desired.
263      *
264      * @return a <code>ScarabLink</code> value
265      */

266     public ScarabLink omitModule()
267     {
268         isOmitModule = true;
269         return this;
270     }
271
272     /**
273      * Shuts off permission checking. Use case: a user saves a query with
274      * module scope, so an email is sent to the project owner to approve it.
275      * The email is sent from the user who does not have permission to
276      * use the Approval.vm template. But it is known that the recipient(s)
277      * does, because that is how they are chosen to receive the email.
278      * We probably need a different link tool for emails that is not
279      * request based. but for now use this sparingly and with forethought.
280      *
281      * @return this
282      */

283     public ScarabLink overrideSecurity()
284     {
285         overrideSecurity = true;
286         return this;
287     }
288   
289     /**
290      * Sets the template variable used by the Template Service. The
291      * module id of the new selected module is given.
292      *
293      * @param t A String with the template name.
294      * @param moduleid The id of the new selected module.
295      * @return A TemplateLink.
296      */

297     protected TemplateLink setPage(String JavaDoc t, String JavaDoc moduleid)
298     {
299
300         this.currentModuleId = moduleid;
301         this.lastUsedModuleId = moduleid;
302
303         if (isSet(moduleid) && !isOmitModule)
304         {
305             addPathInfo(ScarabConstants.CURRENT_MODULE, moduleid);
306         }
307
308         String JavaDoc issueKey = data.getParameters()
309             .getString(ScarabConstants.REPORTING_ISSUE);
310         if (isSet(issueKey))
311         {
312             addPathInfo(ScarabConstants.REPORTING_ISSUE, issueKey);
313         }
314         Object JavaDoc threadKey = ((ScarabUser)data.getUser()).getThreadKey();
315         if (threadKey != null)
316         {
317             addPathInfo(ScarabConstants.THREAD_QUERY_KEY, threadKey);
318         }
319         String JavaDoc reportKey = data.getParameters()
320             .getString(ScarabConstants.CURRENT_REPORT);
321         if (isSet(reportKey))
322         {
323             if (t.startsWith("report"))
324             {
325                 addPathInfo(ScarabConstants.CURRENT_REPORT, reportKey);
326             }
327             else if (!t.startsWith("help"))
328             {
329                 addPathInfo(ScarabConstants.REMOVE_CURRENT_REPORT, reportKey);
330             }
331         }
332         // if a screen is to be passed along, add it
333
String JavaDoc historyScreen = data.getParameters()
334             .getString(ScarabConstants.HISTORY_SCREEN);
335         if (isSet(historyScreen))
336         {
337             addPathInfo(ScarabConstants.HISTORY_SCREEN, historyScreen);
338         }
339         // if a admin menu is to be passed along, add it
340
String JavaDoc adminMenu = data.getParameters()
341             .getString(ScarabConstants.CURRENT_ADMIN_MENU);
342         if (isSet(adminMenu))
343         {
344             addPathInfo(ScarabConstants.CURRENT_ADMIN_MENU, adminMenu);
345         }
346         // if a debug is set, add it
347
String JavaDoc debug = data.getParameters()
348             .getString(ScarabConstants.DEBUG);
349         if (isSet(debug))
350         {
351             addPathInfo(ScarabConstants.DEBUG, debug);
352         }
353         
354         super.setPage(t);
355         return this;
356     }
357
358     private boolean isSet(String JavaDoc s)
359     {
360         return s != null && s.length() > 0;
361     }
362
363     /**
364      * Returns the name of the template that is being being processed
365      */

366     public String JavaDoc getCurrentView()
367     {
368         String JavaDoc temp = data.getParameters().getString(ScarabConstants.TEMPLATE, null);
369         if (temp != null)
370         {
371             temp = temp.replace(',', '/');
372         }
373         return temp;
374     }
375
376     public ScarabLink setPathInfo(String JavaDoc key, String JavaDoc value)
377     {
378         removePathInfo(key);
379         addPathInfo(key, value);
380         return this;
381     }
382
383     // where is this method being used, i do not understand its purpose - jdm
384
public ScarabLink addPathInfo(String JavaDoc key, ParameterParser pp)
385     {
386         addPathInfo(key, pp);
387         return this;
388     }
389
390     /**
391      * Adds a name=value pair to the path_info string. This method is missing
392      * in DynamicURI, but should be there.
393      *
394      * @param name A String with the name to add.
395      * @param value A double with the value to add.
396      */

397     public DynamicURI addPathInfo(String JavaDoc name, boolean value)
398     {
399         addPathInfo(name, (value ? "true" : "false"));
400         return this;
401     }
402
403     /**
404      * Adds all the parameters in a ValueParser to the pathinfo except
405      * the action, screen, or template keys as defined by Turbine
406      */

407     public ScarabLink addPathInfo(ValueParser pp)
408     {
409         // would be nice if DynamicURI included this method but it requires
410
// a specific implementation of ParameterParser
411
Enumeration JavaDoc e = pp.keys();
412         while (e.hasMoreElements())
413         {
414             String JavaDoc key = (String JavaDoc)e.nextElement();
415             if (!key.equalsIgnoreCase(Turbine.ACTION) &&
416                  !key.equalsIgnoreCase(Turbine.SCREEN) &&
417                  !key.equalsIgnoreCase(Turbine.TEMPLATE))
418             {
419                 String JavaDoc[] values = pp.getStrings(key);
420                 for (int i=0; i<values.length; i++)
421                 {
422                     addPathInfo(key, values[i]);
423                 }
424             }
425         }
426         return this;
427     }
428
429     /**
430      * Setting the label will cause the link tool to print out the
431      * the text for the anchor tag. This is useful in that if the link
432      * should not be active for security reasons it can be completely
433      * eliminated.
434      *
435      * @param label a <code>String</code> value
436      * @return a <code>ScarabLink</code> value
437      */

438     public ScarabLink setLabel(String JavaDoc label)
439     {
440         this.label = label;
441         return this;
442     }
443     
444     /**
445      * Allows for setting attributes such as class on an anchor tag
446      * <a class="xxx" HREF="yyy">label</a>. Note the complete anchor
447      * tag is only returned from toString, if the lable has been set
448      * so this setter will have no effect unless setLabel is called.
449      *
450      * @param attributeText a <code>String</code> value
451      * @return a <code>ScarabLink</code> value
452      */

453     public ScarabLink setAttributeText(String JavaDoc attributeText)
454     {
455         this.attributeText = attributeText;
456         return this;
457     }
458
459     /**
460      * Text that will be returned from toString if the user did not have
461      * permission to see the link. The default is the empty string
462      *
463      * @param alternateText a <code>String</code> value
464      * @return a <code>ScarabLink</code> value
465      */

466     public ScarabLink setAlternateText(String JavaDoc alternateText)
467     {
468         this.alternateText = alternateText;
469         return this;
470     }
471
472     /**
473      * Prints out the url and resets the relative flag to true.
474      *
475      * @return a <code>String</code> url
476      */

477     public String JavaDoc toString()
478     {
479         String JavaDoc tostring = null;
480         String JavaDoc alternateText = this.alternateText;
481         // will reset link if false
482
if (isAllowed())
483         {
484             tostring = getLink();
485         }
486         else
487         {
488             tostring = (alternateText == null) ? "" : alternateText;
489         }
490         refresh();
491         return tostring;
492     }
493
494     /**
495      * Returns a short link for viewing a single issue
496      *
497      * @param issue an <code>Issue</code> value
498      * @return a <code>String</code> value
499      * @exception Exception if an error occurs
500      */

501     public ScarabLink getIssueIdLink(Issue issue)
502         throws Exception JavaDoc
503     {
504         this.addPathInfo("id", issue.getUniqueId());
505         return this;
506     }
507
508     /**
509      * Returns a short link for viewing a single issue that will not
510      * include session info and will be absolute. It is meant to
511      * be suitable for embedding in an email that points to the issue.
512      *
513      * @param issue an <code>Issue</code> value
514      * @return a <code>String</code> value
515      * @exception Exception if an error occurs
516      */

517     public ScarabLink getIssueIdAbsoluteLink(Issue issue)
518         throws Exception JavaDoc
519     {
520         ScarabLink link = getIssueIdLink(issue);
521         link.setRelative(false).setEncodeUrl(false);
522         return link;
523     }
524
525     /**
526      * Check if the user has the permission to see the link. If the user
527      * has the permission(s), <code>true</code> is returned. if the
528      * user does NOT have the proper permissions, this method has the
529      * side effect of reseting the link, so that it is ready for use
530      * in building the next link.
531      */

532     public boolean isAllowed()
533     {
534         boolean allowed = overrideSecurity || isAllowed(getPage());
535
536         if (!allowed)
537         {
538             // reset link
539
super.toString();
540             refresh();
541         }
542         
543         return allowed;
544     }
545
546     /**
547      * Check if the user has the permission to see the template t. If the user
548      * has the permission(s), <code>true</code> is returned. If template t is
549      * null, this method returns false.
550      */

551     public boolean isAllowed(String JavaDoc t)
552     {
553         if (t == null)
554         {
555             //check pathinfo for "id"
556
int count = pathInfo.size();
557             for (int i = 0; i < count; i++)
558             {
559                 Object JavaDoc[] pair = (Object JavaDoc[]) pathInfo.get(i);
560                 if ("id".equals(pair[0]))
561                 {
562                     t = "ViewIssue.vm";
563                     break;
564                 }
565             }
566             if (t == null)
567             {
568                 //check querydata for "id"
569
count = queryData.size();
570                 for (int i = 0; i < count; i++)
571                 {
572                     Object JavaDoc[] pair = (Object JavaDoc[]) queryData.get(i);
573                     if ("id".equals(pair[0]))
574                     {
575                         t = "ViewIssue.vm";
576                         break;
577                     }
578                 }
579                 if (t == null)
580                 {
581                     return false;
582                 }
583             }
584         }
585         boolean allowed = false;
586         try
587         {
588             String JavaDoc perm = ScarabSecurity.getScreenPermission(t);
589             if (perm != null)
590             {
591                 initCurrentModule();
592                 
593                 if (currentModuleId != null)
594                 {
595                     if (currentModule == null ||
596                         !currentModule.getModuleId().toString()
597                         .equals(currentModuleId))
598                     {
599                         currentModule = ModuleManager
600                             .getInstance(new Integer JavaDoc(currentModuleId));
601                     }
602                 }
603                 ScarabUser user = (ScarabUser)data.getUser();
604                 allowed = currentModule != null
605                           && (user.hasLoggedIn() || AnonymousUserUtil.isUserAnonymous(user))
606                           && user.hasPermission(perm, currentModule);
607             }
608             else
609             {
610                 allowed = true;
611             }
612         }
613         catch (Exception JavaDoc e)
614         {
615             allowed = false;
616             Log.get().info("Could not check permission due to: ", e);
617         }
618         return allowed;
619     }
620
621     private String JavaDoc getLink()
622     {
623         String JavaDoc s = null;
624         if (label != null && label.length() > 0)
625         {
626             StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(50);
627             sbuf.append("<a ");
628             if (attributeText != null && attributeText.length() > 0)
629             {
630                 sbuf.append(attributeText);
631                 sbuf.append(' ');
632             }
633             sbuf.append("href=\"")
634                 .append(super.toString())
635                 .append("\">")
636                 .append(label)
637                 .append("</a>");
638             s = sbuf.toString();
639         }
640         else
641         {
642             s = super.toString();
643         }
644         return s;
645     }
646
647     /**
648      * Give subclasses access to the RunData, so they do not have to
649      * reimplement the pooling code, just to get at it.
650      */

651     protected RunData getRunData()
652     {
653         return data;
654     }
655
656     // ****************************************************************
657
// ****************************************************************
658
// Implementation of Recyclable
659
// ****************************************************************
660
// ****************************************************************
661

662     private boolean disposed = false;
663
664     /**
665      * Recycles the object by removing its disposed flag.
666      */

667     public void recycle()
668     {
669         disposed = false;
670     }
671
672     /**
673      * Disposes the object by setting its disposed flag.
674      */

675     public void dispose()
676     {
677         data = null;
678         refresh();
679         disposed = true;
680     }
681
682     /**
683      * Checks whether the object is disposed.
684      *
685      * @return true, if the object is disposed.
686      */

687     public boolean isDisposed()
688     {
689         return disposed;
690     }
691 }
692
Popular Tags