KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > forward > JetspeedForwardService


1 /*
2  * Copyright 2000-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
17 package org.apache.jetspeed.services.forward;
18
19 // java
20
import java.util.Map JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.TreeMap JavaDoc;
26 import java.util.Map.Entry;
27 import java.io.File JavaDoc;
28 import java.io.FileReader JavaDoc;
29 import javax.servlet.ServletConfig JavaDoc;
30
31 // turbine, services
32
import org.apache.turbine.util.RunData;
33 import org.apache.turbine.util.DynamicURI;
34 import org.apache.turbine.services.resources.ResourceService;
35 import org.apache.turbine.services.TurbineBaseService;
36 import org.apache.turbine.services.TurbineServices;
37 import org.apache.turbine.services.InitializationException;
38 import org.apache.turbine.services.servlet.TurbineServlet;
39
40 // marshaling
41
import javax.xml.parsers.DocumentBuilder JavaDoc;
42 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
43 import org.w3c.dom.Document JavaDoc;
44 import org.w3c.dom.Node JavaDoc;
45 import org.exolab.castor.mapping.Mapping;
46 import org.exolab.castor.xml.Unmarshaller;
47 import org.apache.xml.serialize.OutputFormat;
48 import org.xml.sax.InputSource JavaDoc;
49
50 // jetspeed
51
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
52 import org.apache.jetspeed.services.logging.JetspeedLogger;
53 import org.apache.jetspeed.util.template.JetspeedLink;
54 import org.apache.jetspeed.util.template.JetspeedLinkFactory;
55
56 // forwarding configuration
57
import org.apache.jetspeed.services.forward.configuration.ForwardsConfiguration;
58 import org.apache.jetspeed.services.forward.configuration.Forward;
59 import org.apache.jetspeed.services.forward.configuration.Page;
60 import org.apache.jetspeed.services.forward.configuration.Pane;
61 import org.apache.jetspeed.services.forward.configuration.Portlet;
62 import org.apache.jetspeed.services.forward.configuration.PortletForward;
63 import org.apache.jetspeed.services.forward.configuration.QueryParam;
64
65
66 /**
67  * <P>This is the implementation of the Jetspeed Forward services.
68  * The interface defines methods for forwarding navigation to
69  * other pages or panes in the portal. The Forward service
70  * provides an abstraction, by removing the hard-coding of
71  * portal resources in your actions. Instead, all forward targets
72  * are defined in a centralized configuration file. By using the
73  * forward service, you use logical forward names in your java code.</P>
74  *
75  * @see org.apache.jetspeed.om.profile.Profile
76  * @author <a HREF="mailto:david@bluesunrise.com">David Sean Taylor</a>
77  * @version $Id: JetspeedForwardService.java,v 1.7 2004/02/23 03:51:09 jford Exp $
78  */

79
80 public class JetspeedForwardService extends TurbineBaseService
81                                     implements ForwardService
82 {
83     /**
84      * Static initialization of the logger for this class
85      */

86     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedForwardService.class.getName());
87     
88     // configuration keys
89
protected final static String JavaDoc CONFIG_MAPPING = "mapping";
90     protected final static String JavaDoc CONFIG_DIRECTORY = "directory";
91
92     // configuration parameters
93
protected String JavaDoc mapping = // the forwards XML-Java mapping
94
"/WEB-INF/conf/forwards-mapping.xml";
95
96     protected String JavaDoc directory = // the location of forwards definitions
97
"/WEB-INF/conf/forwards/";
98
99     /** the Castor mapping file name */
100     protected Mapping mapper = null;
101
102     /** the output format for pretty printing when saving registries */
103     protected OutputFormat format = null;
104
105
106     // Forward definitions
107
protected Map JavaDoc forwards = new HashMap JavaDoc();
108     
109     // Portlet Forward definitions
110
protected Map JavaDoc portletForwards = new TreeMap JavaDoc();
111
112
113     protected final static String JavaDoc KEY_DELIMITER = ":";
114
115     /**
116      * This is the early initialization method called by the
117      * Turbine <code>Service</code> framework
118      * @param conf The <code>ServletConfig</code>
119      * @exception throws a <code>InitializationException</code> if the service
120      * fails to initialize
121      */

122     public synchronized void init(ServletConfig JavaDoc conf) throws InitializationException
123     {
124
125         // already initialized
126
if (getInit()) return;
127
128         try
129         {
130             // get configuration parameters from Jetspeed Resources
131
ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
132                                                          .getResources(ForwardService.SERVICE_NAME);
133
134             this.mapping = serviceConf.getString(CONFIG_MAPPING, this.mapping);
135
136             this.directory = serviceConf.getString(CONFIG_DIRECTORY, this.directory);
137
138             this.mapping = TurbineServlet.getRealPath(this.mapping);
139             this.directory = TurbineServlet.getRealPath(this.directory);
140
141             loadForwards();
142
143         }
144         catch (Exception JavaDoc e)
145         {
146             logger.error("ForwardService: Failed to load ", e);
147         }
148
149         // initialization done
150
setInit(true);
151
152      }
153
154
155
156     /**
157      * This is the shutdown method called by the
158      * Turbine <code>Service</code> framework
159      */

160     public void shutdown()
161     {
162     }
163
164     /**
165      * Forward to a specific forward by name.
166      * All parameters are resolved statically (via the forward definition)
167      *
168      * @param rundata The turbine rundata context for this request.
169      * @param forwardName Forward to this abstract forward name.
170      * @return DynamicURI the full link to the referenced page
171      */

172     public DynamicURI forward(RunData rundata, String JavaDoc forwardName)
173     {
174         return forwardInternal(rundata, forwardName, null, null);
175     }
176
177     /**
178      * Forward to a specific forward by name.
179      * Parameters are resolved both statically and dynamically, with the
180      * dynamic parameter overriding the static parameter definitions.
181      *
182      * @param rundata The turbine rundata context for this request.
183      * @param forwardName Forward to this abstract forward name.
184      * @param parameters The dynamic Validation Parameters used in creating validation forwards
185      * @return DynamicURI the full link to the referenced page
186      */

187     public DynamicURI forwardDynamic(RunData rundata, String JavaDoc forwardName, Map JavaDoc parameters)
188     {
189         return forwardInternal(rundata, forwardName, null, parameters);
190     }
191
192     /**
193      * Internal implementation of Forward used by both forwards and portlet forwards.
194      *
195      * @param rundata The turbine rundata context for this request.
196      * @param name Forward to this abstract forward name.
197      * @param staticParams Map of static query parameters from PortletForward
198      * overriding the static Forwards query parameters
199      * @param dynamicParams Map of dynamic query parameters overriding both
200      * static PortletForward parameters and static Forwards query parameters
201      * @return DynamicURI the full link to the referenced page
202      */

203     private DynamicURI forwardInternal(RunData rundata,
204                                    String JavaDoc forwardName,
205                                    Map JavaDoc staticParams,
206                                    Map JavaDoc dynamicParams)
207     {
208         DynamicURI duri = null;
209         Forward forward = null;
210
211         try
212         {
213             JetspeedLink link = JetspeedLinkFactory.getInstance(rundata);
214             int rootType = JetspeedLink.DEFAULT;
215             int elementType = JetspeedLink.DEFAULT;
216             String JavaDoc rootValue = null;
217             String JavaDoc pageName = null;
218             String JavaDoc elementValue = null;
219             String JavaDoc actionName = null;
220             String JavaDoc templateName = null;
221             String JavaDoc mediaType = null;
222             String JavaDoc language = null;
223             String JavaDoc country = null;
224
225
226             forward = (Forward)this.forwards.get(forwardName);
227             if (null != forward)
228             {
229                 Pane pane = forward.getPane();
230                 if (null != pane)
231                 {
232                     elementValue = pane.getId();
233                     elementType = JetspeedLink.PANE_ID;
234                     if (elementValue == null)
235                     {
236                         elementValue = pane.getName();
237                         elementType = JetspeedLink.PANE_NAME;
238                     }
239                 }
240                 else // can't have both portlet and pane
241
{
242                     Portlet portlet = forward.getPortlet();
243                     if (null != portlet)
244                     {
245                         elementValue = portlet.getId();
246                         elementType = JetspeedLink.PORTLET_ID;
247                         if (elementValue == null)
248                         {
249                             elementValue = portlet.getName();
250                             elementType = JetspeedLink.PORTLET_NAME;
251                         }
252                         actionName = portlet.getAction();
253                     }
254                 }
255
256                 Page page = forward.getPage();
257                 if (null != page)
258                 {
259                     pageName = page.getName();
260
261                     String JavaDoc user = page.getUser();
262                     if (user != null)
263                     {
264                         rootType = JetspeedLink.USER;
265                         rootValue = user;
266                     }
267                     else
268                     {
269                         String JavaDoc role = page.getRole();
270                         if (role != null)
271                         {
272                             rootType = JetspeedLink.ROLE;
273                             rootValue = role;
274                         }
275                         else
276                         {
277                             String JavaDoc group = page.getGroup();
278                             if (group != null)
279                             {
280                                 rootType = JetspeedLink.GROUP;
281                                 rootValue = group;
282                             }
283                             else
284                             {
285                                 rootType = JetspeedLink.CURRENT;
286                             }
287                         }
288                     }
289                 }
290
291                 duri = link.getLink(rootType,
292                              rootValue,
293                              pageName,
294                              elementType,
295                              elementValue,
296                              actionName,
297                              templateName, // not yet implemented
298
mediaType, // not yet implemented
299
language, // not yet implemented
300
country); // not yet implemented
301

302             }
303             else
304             {
305                 // forward not found, log it and return to home page
306
// TODO: perhaps this could be configurable to go to a default error page
307
logger.error("Forward not found, going to Home Page:" + forwardName);
308                 duri = link.getHomePage();
309     
310             }
311     
312             if (null == duri)
313             {
314                 duri = link.getPage();
315             }
316
317             Map JavaDoc baseQueryParams = null;
318             if (null != forward)
319             {
320                 baseQueryParams = forward.getQueryParams();
321             }
322             setQueryParams(duri, baseQueryParams, staticParams, dynamicParams);
323
324             rundata.setRedirectURI(duri.toString());
325             JetspeedLinkFactory.putInstance(link);
326         }
327         catch (Throwable JavaDoc t)
328         {
329             logger.error("Exception in Forward",t);
330         }
331         return duri;
332     }
333
334     /**
335      * Adds query parameters to the final URI.
336      * Parameters are merged from the base forwards definition, with the
337      * overlay parameters being overlaid over th base parameters
338      *
339      * @param duri The dynamic URI to have query parameters added to it
340      * @param baseQueryParams The base query parameters from the forward definition
341      * @param staticParams Map of static query parameters from PortletForward
342      * overriding the static Forwards query parameters
343      * @param dynamicParams Map of dynamic query parameters overriding both
344      * static PortletForward parameters and static Forwards query parameters
345      * @return DynamicURI The new URI including query parameters
346      */

347     private DynamicURI setQueryParams(DynamicURI duri,
348                                       Map JavaDoc baseQueryParams,
349                                       Map JavaDoc staticParams,
350                                       Map JavaDoc dynamicParams)
351     {
352         if (baseQueryParams == null && staticParams == null && dynamicParams == null)
353         {
354             return duri;
355         }
356
357         Iterator JavaDoc it = null;
358
359         // First add the base params
360
if (baseQueryParams != null)
361         {
362             it = baseQueryParams.values().iterator();
363             while (it.hasNext())
364             {
365                 QueryParam qparam = (QueryParam)it.next();
366                 if ( (null == staticParams || !staticParams.containsKey(qparam.getName()))
367                     && (null == dynamicParams || !dynamicParams.containsKey(qparam.getName())))
368                 {
369                     duri.addQueryData(qparam.getName(), qparam.getValue());
370                 }
371             }
372         }
373
374         // Then add the static params
375
if (staticParams != null)
376         {
377             it = staticParams.values().iterator();
378             while (it.hasNext())
379             {
380                 QueryParam qparam = (QueryParam)it.next();
381                 if (null == dynamicParams || !dynamicParams.containsKey(qparam.getName()))
382                 {
383                     duri.addQueryData(qparam.getName(), qparam.getValue());
384                 }
385             }
386         }
387         
388         // Then add the dynamic params
389
if (dynamicParams != null)
390         {
391             it = dynamicParams.entrySet().iterator();
392             while (it.hasNext())
393             {
394                 Entry entry = (Entry)it.next();
395                 duri.addQueryData((String JavaDoc)entry.getKey(), entry.getValue());
396             }
397         }
398
399         return duri;
400     }
401
402     
403     private void dumpMap(String JavaDoc mapName, Map JavaDoc map)
404     {
405         System.out.println("----------- MAP: " + mapName);
406         Iterator JavaDoc it = map.values().iterator();
407         while (it.hasNext())
408         {
409             QueryParam qparam = (QueryParam)it.next();
410             System.out.println("name = " + qparam.getName() + ", value = " + qparam.getValue());
411         }
412     }
413
414     /**
415      * For the given portlet and given action, forward to the target
416      * defined in the forward configuration for the portlet + action.
417      * All parameters are resolved statically (via the forward definition)
418      *
419      * @param portlet The name of the portlet for which we are forwarding.
420      * @param target A logical target name. Portlets can have 1 or more targets.
421      * @return DynamicURI the full link to the referenced page
422      */

423     public DynamicURI forward(RunData rundata, String JavaDoc portlet, String JavaDoc target)
424     {
425         return forwardDynamic(rundata, portlet, target, null);
426     }
427
428     /**
429      * For the given portlet and given action, forward to the target
430      * defined in the forward configuration for the portlet + action.
431      * Parameters are resolved both statically and dynamically, with the
432      * dynamic parameter overriding the static parameter definitions.
433      *
434      * @param portlet The name of the portlet for which we are forwarding.
435      * @param target A logical target name. Portlets can have 1 or more targets.
436      * @param parameters The dynamic Validation Parameters used in creating validation forwards
437      * @return DynamicURI the full link to the referenced page
438      */

439     public DynamicURI forwardDynamic(RunData rundata,
440                                  String JavaDoc portlet,
441                                  String JavaDoc target,
442                                  Map JavaDoc parameters)
443     {
444         try
445         {
446             Map JavaDoc staticParams = null;
447             String JavaDoc forwardName = "";
448             String JavaDoc key = makePortletForwardKey(portlet, target);
449             PortletForward pf = (PortletForward)this.portletForwards.get(key);
450             if (null != pf)
451             {
452                 staticParams = pf.getQueryParams();
453                 Forward forward = (Forward)this.forwards.get(pf.getForward());
454                 if (null != forward)
455                 {
456                     forwardName = forward.getName();
457                 }
458             }
459             return forwardInternal(rundata, forwardName, staticParams, parameters);
460         }
461         catch (Throwable JavaDoc t)
462         {
463             t.printStackTrace();
464         }
465         return new DynamicURI();
466
467     }
468
469     /**
470      * Get a collection of all forwards in the system.
471      *
472      * @return Collection of all forward definitions
473      */

474     public Collection JavaDoc getForwards()
475     {
476         return this.forwards.values();
477     }
478
479     /**
480      * Get a collection of all portlet forwards in the system.
481      *
482      * @return Collection of all portlet forward definitions
483      */

484     public Collection JavaDoc getPortletForwards()
485     {
486         return this.portletForwards.values();
487     }
488
489     /**
490      * Lookup a single forward definition by forward name
491      *
492      * @param forwardName The name of the Forward to find
493      * @return Forward The found forward definition or null if not found
494      */

495     public Forward getForward(String JavaDoc forwardName)
496     {
497         return (Forward)this.forwards.get(forwardName);
498     }
499
500     /**
501      * Lookup a single portlet forward definition by portlet name + target name
502      *
503      * @param portlet The name of the portlet in the Portlet Forward to find
504      * @param target The name of the target in the Portlet Forward to find
505      * @return Forward The found portlet forward definition or null if not found
506      */

507     public PortletForward getPortletForward(String JavaDoc portlet, String JavaDoc target)
508     {
509         return (PortletForward)this.portletForwards.get(makePortletForwardKey(portlet, target));
510     }
511
512     /**
513      * Load all forward configuration files from forwards directory.
514      *
515      *
516      */

517     protected void loadForwards()
518         throws InitializationException
519     {
520         // create the serializer output format
521
this.format = new OutputFormat();
522         this.format.setIndenting(true);
523         this.format.setIndent(4);
524
525         File JavaDoc map = new File JavaDoc(this.mapping);
526         if (map.exists() && map.isFile() && map.canRead())
527         {
528             try
529             {
530                 this.mapper = new Mapping();
531                 InputSource JavaDoc is = new InputSource JavaDoc(new FileReader JavaDoc(map));
532                 is.setSystemId(this.mapping);
533                 this.mapper.loadMapping(is);
534             }
535             catch (Exception JavaDoc e)
536             {
537                 String JavaDoc msg = "ForwardService: Error in castor mapping creation";
538                 logger.error(msg, e);
539                 throw new InitializationException(msg, e);
540             }
541         }
542         else
543         {
544             String JavaDoc msg = "ForwardService: Mapping not found or not a file or unreadable: " + this.mapping;
545             logger.error(msg);
546             throw new InitializationException(msg);
547         }
548
549
550         try
551         {
552         
553             File JavaDoc directory = new File JavaDoc(this.directory);
554             File JavaDoc[] files = directory.listFiles();
555             for (int ix=0; ix < files.length; ix++)
556             {
557                 if (files[ix].isDirectory())
558                 {
559                     continue;
560                 }
561
562                 loadForwardConfiguration(files[ix]);
563             }
564
565         }
566         catch (Exception JavaDoc e)
567         {
568             String JavaDoc msg = "ForwardService: Fatal error loading Forward configurations";
569             logger.error(msg, e);
570             throw new InitializationException(msg, e);
571         }
572
573     }
574
575     protected String JavaDoc makePortletForwardKey(String JavaDoc portlet, String JavaDoc target)
576     {
577         StringBuffer JavaDoc key = new StringBuffer JavaDoc(portlet);
578         key.append(KEY_DELIMITER);
579         key.append(target);
580         return key.toString();
581     }
582
583     /**
584      * Load and unmarshal a Forward Configuration from a file.
585      *
586      * @param file the absolute file path storing this fragment
587      */

588     protected void loadForwardConfiguration(File JavaDoc file)
589     {
590         try
591         {
592             DocumentBuilderFactory JavaDoc dbfactory = DocumentBuilderFactory.newInstance();
593             DocumentBuilder JavaDoc builder = dbfactory.newDocumentBuilder();
594
595             Document JavaDoc doc = builder.parse(file);
596
597             Unmarshaller unmarshaller = new Unmarshaller(this.mapper);
598             ForwardsConfiguration configuration =
599                 (ForwardsConfiguration) unmarshaller.unmarshal((Node JavaDoc) doc);
600
601             Iterator JavaDoc it = configuration.getForwards().iterator();
602             while (it.hasNext())
603             {
604                 Forward forward = (Forward)it.next();
605                 if (this.forwards.containsKey(forward.getName()))
606                 {
607                     logger.error("ForwardService: already contains Forward key: " + forward.getName());
608                 }
609                 else
610                 {
611                     this.forwards.put(forward.getName(), forward);
612                 }
613                 
614                 resyncParamMap(forward.getQueryParams());
615
616             }
617
618             it = configuration.getPortletForwards().iterator();
619             while (it.hasNext())
620             {
621                 PortletForward pf = (PortletForward)it.next();
622                 String JavaDoc key = makePortletForwardKey(pf.getPortlet(), pf.getTarget());
623                 if (this.portletForwards.containsKey(key))
624                 {
625                     logger.error("ForwardService: already contains portletForward key: " + key);
626                 }
627                 else
628                 {
629                     this.portletForwards.put(key, pf);
630                     resyncParamMap(pf.getQueryParams());
631                 }
632             }
633
634
635         }
636         catch (Throwable JavaDoc t)
637         {
638             logger.error("ForwardService: Could not unmarshal: " + file, t);
639         }
640
641     }
642
643     private void resyncParamMap(Map JavaDoc map)
644     {
645         // Castor doesn't set the keys properly for maps
646
// get the base query params
647
ArrayList JavaDoc list = new ArrayList JavaDoc(map.size());
648         Iterator JavaDoc it = map.values().iterator();
649         while (it.hasNext())
650         {
651             QueryParam qp = (QueryParam)it.next();
652             list.add(qp);
653         }
654         map.clear();
655         it = list.iterator();
656         while (it.hasNext())
657         {
658             QueryParam qp = (QueryParam)it.next();
659             map.put(qp.getName(), qp);
660         }
661
662     }
663 }
664
665
Popular Tags