KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > portal > generic > MapBasedInvocationFactory


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2001-2004 Caucho Technology, Inc. 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
8  * are 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
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution, if
19  * any, must include the following acknowlegement:
20  * "This product includes software developed by the
21  * Caucho Technology (http://www.caucho.com/)."
22  * Alternately, this acknowlegement may appear in the software itself,
23  * if and wherever such third-party acknowlegements normally appear.
24  *
25  * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * info@caucho.com.
29  *
30  * 5. Products derived from this software may not be called "Resin"
31  * nor may "Resin" appear in their names without prior written
32  * permission of Caucho Technology.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37  * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
38  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
39  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
40  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
43  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
44  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  *
46  * @author Sam
47  */

48
49
50 package com.caucho.portal.generic;
51
52 import javax.portlet.PortletMode;
53 import javax.portlet.WindowState;
54 import java.util.HashSet JavaDoc;
55 import java.util.Iterator JavaDoc;
56 import java.util.LinkedHashMap JavaDoc;
57 import java.util.Map JavaDoc;
58 import java.util.Set JavaDoc;
59 import java.util.logging.Level JavaDoc;
60 import java.util.logging.Logger JavaDoc;
61
62
63 /**
64  */

65 public class MapBasedInvocationFactory
66   implements InvocationFactory, Cloneable JavaDoc
67 {
68   static protected final Logger JavaDoc log =
69     Logger.getLogger(MapBasedInvocationFactory.class.getName());
70
71   private String JavaDoc _reservedNamespace = "__";
72   private String JavaDoc _actionTargetParameterName = "A";
73   private String JavaDoc _windowStateParameterName = "W";
74   private String JavaDoc _portletModeParameterName = "M";
75
76
77   private LinkedHashMap JavaDoc<String JavaDoc, MapBasedInvocation> _invocationMap
78     = new LinkedHashMap JavaDoc<String JavaDoc, MapBasedInvocation>();
79
80   private String JavaDoc _actionNamespace;
81
82   private Set JavaDoc<WindowState> _windowStatesUsed;
83   private Set JavaDoc<PortletMode> _portletModesUsed;
84
85   // this class is not required to be thread-safe
86
private StringBuffer JavaDoc _buffer = new StringBuffer JavaDoc(256);
87
88   /**
89    * The reserved namespace is used to mark parameters that have special
90    * meaning to the portal. The specification suggests "javax.portal.", which
91    * is rather long so the default is "__".
92    *
93    * This implementation also uses the reserved namespace as a prefix to
94    * parameter names.
95    */

96   public void setReservedNamespace(String JavaDoc namespace)
97   {
98     _reservedNamespace = namespace;
99   }
100
101   /**
102    * The reserved namespace is used to mark parameters that have special
103    * meaning to the portal.
104    */

105   public String JavaDoc getReservedNamespace()
106   {
107     return _reservedNamespace;
108   }
109
110   /**
111    * The name of the parameter to use to store the namespace of
112    * the target of an action.
113    */

114   public void setActionTargetParameterName(String JavaDoc name)
115   {
116     _actionTargetParameterName = name;
117   }
118
119   /**
120    * The name of the parameter to use to store the namespace of
121    * the target of an action.
122    */

123   public String JavaDoc getActionTargetParameterName()
124   {
125     return _actionTargetParameterName;
126   }
127
128   /**
129    * The name of the parameter to use to store the window state.
130    */

131   public void setWindowStateParameterName(String JavaDoc name)
132   {
133     _windowStateParameterName = name;
134   }
135
136   /**
137    * The name of the parameter to use to store the window state.
138    */

139   public String JavaDoc getWindowStateParameterName()
140   {
141     return _windowStateParameterName;
142   }
143
144   /**
145    * The name of the parameter to use to store the portlet mode.
146    */

147   public void setPortletModeParameterName(String JavaDoc name)
148   {
149     _portletModeParameterName = name;
150   }
151
152   /**
153    * The name of the parameter to use to store the portlet mode.
154    */

155   public String JavaDoc getPortletModeParameterName()
156   {
157     return _portletModeParameterName;
158   }
159
160   public void start(Map JavaDoc<String JavaDoc, String JavaDoc[]> rawParameters)
161   {
162     if (rawParameters != null)
163       decodeRawParameters(rawParameters);
164   }
165
166   public void finish()
167   {
168     _windowStatesUsed = null;
169     _portletModesUsed = null;
170
171     _actionNamespace = null;
172     _invocationMap.clear();
173   }
174
175   public boolean isActionTarget(String JavaDoc namespace)
176   {
177     return namespace == _actionNamespace;
178   }
179
180   /**
181    * The actionNamespace and actionMap are null in the returned clone
182    * The invocation that matches the passed namespace will not have any
183    * parameters.
184    */

185   protected MapBasedInvocationFactory clone(String JavaDoc namespace)
186   {
187     try {
188       MapBasedInvocationFactory clone
189         = (MapBasedInvocationFactory) super.clone();
190
191       clone._windowStatesUsed = null;
192       clone._portletModesUsed = null;
193       clone._actionNamespace = null;
194
195       clone._invocationMap = new LinkedHashMap JavaDoc<String JavaDoc, MapBasedInvocation>();
196
197       Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation>> iter
198         = _invocationMap.entrySet().iterator();
199
200       while (iter.hasNext()) {
201         Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation> entry = iter.next();
202         String JavaDoc invocationNamespace = entry.getKey();
203         MapBasedInvocation invocation = entry.getValue();
204
205         boolean keepParameters = !namespace.equals(invocationNamespace);
206
207         clone._invocationMap.put( invocationNamespace,
208                                   invocation.clone(keepParameters) );
209       }
210
211       return clone;
212     }
213     catch (CloneNotSupportedException JavaDoc ex) {
214       throw new RuntimeException JavaDoc(ex);
215     }
216   }
217
218   protected void decodeRawParameters(Map JavaDoc<String JavaDoc, String JavaDoc[]> raw)
219   {
220     _buffer.setLength(0);
221     StringBuffer JavaDoc buf = _buffer;
222
223     buf.append(_reservedNamespace);
224     int len = buf.length();
225
226     buf.append(_reservedNamespace);
227     buf.append(_actionTargetParameterName);
228     String JavaDoc actionTargetParameterName = buf.toString();
229
230     buf.setLength(len);
231     buf.append(_windowStateParameterName);
232     String JavaDoc windowStateParameterName = buf.toString();
233
234     buf.setLength(len);
235     buf.append(_portletModeParameterName);
236     String JavaDoc portletModeParameterName = buf.toString();
237
238     MapBasedInvocation invocation = null;
239
240     // first, determine the target of the action, if any.
241
String JavaDoc[] action = raw.get(actionTargetParameterName);
242     _actionNamespace = action == null || action.length == 0 ? null : action[0];
243
244     if (_actionNamespace != null)
245       getInvocation(_actionNamespace);
246
247     // iterate the parameters.
248
// parameters that begin with the _reservedNamespace are render
249
// parameters.
250
// parameters that do not begin with the _reservedNamespace are action
251
// parameters, and belong to the Invocation for _actionNamespace.
252

253     Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, String JavaDoc[]>> iter = raw.entrySet().iterator();
254
255     while (iter.hasNext()) {
256       Map.Entry JavaDoc<String JavaDoc, String JavaDoc[]> entry = iter.next();
257       String JavaDoc key = entry.getKey();
258       String JavaDoc[] values = entry.getValue();
259
260
261       String JavaDoc namespace = null;
262
263       if (key.startsWith(_reservedNamespace)) {
264
265         int keyLen = key.length();
266
267         int st = _reservedNamespace.length();
268         int nd = key.indexOf('.', st);
269         if (nd > -1) {
270           namespace = key.substring(st, nd);
271           nd++;
272         }
273         else {
274           if ( log.isLoggable(Level.FINE)
275                && !key.equals(actionTargetParameterName) )
276             log.fine("unusable raw parameter name `" + key + "'");
277           continue;
278         }
279         
280         if (nd < keyLen)
281           key = key.substring(nd);
282         else {
283           if ( log.isLoggable(Level.FINE) )
284             log.fine("unusable . raw parameter name `" + key + "'");
285           continue;
286         }
287       }
288       else {
289         if (_actionNamespace == null) {
290           log.finer("unusable raw action parameter name `" + key + "'");
291           continue;
292         } else
293           namespace = _actionNamespace;
294       }
295
296       if (invocation == null || !invocation.getNamespace().equals(namespace))
297         invocation = getInvocation(namespace);
298
299       if (windowStateParameterName.equals(key)) {
300         invocation.setWindowStateName(values);
301       }
302       else if (portletModeParameterName.equals(key)) {
303         invocation.setPortletModeName(values);
304       }
305       else {
306         invocation.getParameterMap().put(key, values);
307       }
308     }
309
310   }
311
312
313   public String JavaDoc getURL()
314   {
315     _buffer.setLength(0);
316     StringBuffer JavaDoc buf = _buffer;
317
318     StringBuffer JavaDoc url = _buffer;
319
320     if (_actionNamespace != null)
321       appendReserved(url, null, _actionTargetParameterName, _actionNamespace);
322
323     Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation>> iter
324       = _invocationMap.entrySet().iterator();
325
326     // "view" and "normal" are defaults. They only to to be included
327
// in the url if:
328
// 1) some namespace uses view or normal and has no parameters
329
// 2) some other namespace uses a different portlet mode/window state
330
//
331
// They only need to be included once, the purpose for including them is so
332
// that on a subsequent request the windowStatesUsed and portletModesUsed
333
// are correct.
334

335     String JavaDoc viewPortletModeNamespace = null;
336     String JavaDoc normalWindowStateNamespace = null;
337     boolean needViewPortletMode = false;
338     boolean needNormalWindowState = false;
339
340     boolean sawActionNamespace = false;
341
342     while (iter.hasNext()) {
343       Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation> entry = iter.next();
344       String JavaDoc namespace = entry.getKey();
345       MapBasedInvocation invocation = entry.getValue();
346
347       // when the namespace is the target of an action, the parameter
348
// names are not encoded
349
String JavaDoc paramNamespace = namespace == _actionNamespace ? null : namespace;
350
351       PortletMode portletMode = invocation.getPortletMode();
352       WindowState windowState = invocation.getWindowState();
353       Map JavaDoc<String JavaDoc, String JavaDoc[]> parameterMap = invocation._parameterMap;
354
355       boolean hasParameters = parameterMap != null && !parameterMap.isEmpty();
356
357       if (portletMode == PortletMode.VIEW) {
358         if (viewPortletModeNamespace == null && !hasParameters)
359           viewPortletModeNamespace = namespace;
360       }
361       else {
362         needViewPortletMode = true;
363
364         String JavaDoc key = _portletModeParameterName;
365         String JavaDoc value = portletMode.toString();
366
367         appendReserved( url, namespace, key, value );
368       }
369
370
371       if (windowState == WindowState.NORMAL) {
372         if (normalWindowStateNamespace == null && !hasParameters)
373           normalWindowStateNamespace = namespace;
374       }
375       else {
376         needNormalWindowState = true;
377
378         String JavaDoc key = _windowStateParameterName;
379         String JavaDoc value = windowState.toString();
380
381         appendReserved( url, namespace, key, value );
382       }
383
384       if (parameterMap != null && !parameterMap.isEmpty())
385       {
386         Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, String JavaDoc[]>> paramIter
387           = parameterMap.entrySet().iterator();
388
389         while (paramIter.hasNext()) {
390           Map.Entry JavaDoc<String JavaDoc, String JavaDoc[]> paramEntry = paramIter.next();
391
392           String JavaDoc paramKey = paramEntry.getKey();
393           String JavaDoc[] paramValues = paramEntry.getValue();
394
395           if (paramValues == null || paramValues.length == 0)
396             continue;
397
398           appendParameter( url, paramNamespace, paramKey, paramValues );
399         }
400       }
401       
402     } // iterate invocationMap
403

404     if (needViewPortletMode && viewPortletModeNamespace != null) {
405       String JavaDoc key = _portletModeParameterName;
406
407       if (viewPortletModeNamespace == _actionNamespace)
408         viewPortletModeNamespace = null;
409
410       appendReserved( url, viewPortletModeNamespace, key, "view" );
411     }
412
413     if (needNormalWindowState && normalWindowStateNamespace != null) {
414       String JavaDoc key = _windowStateParameterName;
415
416       if (normalWindowStateNamespace == _actionNamespace)
417         normalWindowStateNamespace = null;
418
419       appendReserved( url, normalWindowStateNamespace, key, "normal" );
420     }
421
422     return url.toString();
423   }
424
425   private void appendReserved( StringBuffer JavaDoc url, String JavaDoc namespace,
426                                String JavaDoc key, String JavaDoc value )
427   {
428     url.append(url.length() == 0 ? '?' : '&');
429
430     url.append(_reservedNamespace);
431
432     if (namespace != null) {
433       url.append(namespace);
434       url.append('.');
435     }
436
437     url.append(_reservedNamespace);
438     url.append(key);
439     url.append('=');
440     HttpUtil.encode(value, url);
441   }
442
443   private void appendParameter( StringBuffer JavaDoc url, String JavaDoc namespace,
444                                 String JavaDoc key, String JavaDoc values[] )
445   {
446     for (int i = 0; i < values.length; i++) {
447       url.append(url.length() == 0 ? '?' : '&');
448
449       if (namespace != null) {
450         url.append(_reservedNamespace);
451         url.append(namespace);
452         url.append('.');
453       }
454
455       HttpUtil.encode(key, url);
456       url.append('=');
457       HttpUtil.encode(values[i], url);
458     }
459   }
460
461
462   /**
463    * @return a Set of all WindowState's used.
464    */

465   public Set JavaDoc<WindowState> getWindowStatesUsed()
466   {
467     if (_windowStatesUsed == null) {
468       _windowStatesUsed = new HashSet JavaDoc<WindowState>();
469
470       if (_invocationMap != null) {
471         Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation>> iter
472           = _invocationMap.entrySet().iterator();
473
474         while (iter.hasNext()) {
475           Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation> entry = iter.next();
476           _windowStatesUsed.add(entry.getValue().getWindowState());
477         }
478       }
479     }
480
481     if (_windowStatesUsed.isEmpty())
482       _windowStatesUsed.add(WindowState.NORMAL);
483
484     return _windowStatesUsed;
485   }
486
487   private void addWindowStateUsed(WindowState windowState)
488   {
489     if (_windowStatesUsed != null)
490       _windowStatesUsed.add(windowState);
491   }
492
493   /**
494    * @return a Set of all PortletMode's used.
495    */

496   public Set JavaDoc<PortletMode> getPortletModesUsed()
497   {
498     if (_portletModesUsed == null) {
499       _portletModesUsed = new HashSet JavaDoc<PortletMode>();
500
501       if (_invocationMap != null) {
502         Iterator JavaDoc<Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation>> iter
503           = _invocationMap.entrySet().iterator();
504
505         while (iter.hasNext()) {
506           Map.Entry JavaDoc<String JavaDoc, MapBasedInvocation> entry = iter.next();
507           _portletModesUsed.add(entry.getValue().getPortletMode());
508         }
509       }
510     }
511
512     if (_portletModesUsed.isEmpty())
513       _portletModesUsed.add(PortletMode.VIEW);
514
515     return _portletModesUsed;
516   }
517
518   private void addPortletModeUsed(PortletMode portletMode)
519   {
520     if (_portletModesUsed != null)
521       _portletModesUsed.add(portletMode);
522   }
523
524   /**
525    * Return a Invocation appropriate for the passed namespace.
526    */

527   public MapBasedInvocation getInvocation(String JavaDoc namespace)
528   {
529     if (namespace == null)
530       throw new NullPointerException JavaDoc("namespace cannot be null");
531
532     MapBasedInvocation invocation = _invocationMap.get(namespace);
533
534     if (invocation == null) {
535       invocation = new MapBasedInvocation(this);
536
537       invocation.start(namespace);
538       _invocationMap.put(namespace, invocation);
539     }
540
541     return invocation;
542   }
543
544   protected InvocationURL createActionURL(String JavaDoc namespace)
545   {
546     MapBasedInvocationFactory clone = clone(namespace);
547     clone._actionNamespace = namespace;
548     return new MapBasedInvocationURL(clone, namespace);
549   }
550
551   protected InvocationURL createRenderURL(String JavaDoc namespace)
552   {
553     MapBasedInvocationFactory clone = clone(namespace);
554     clone._actionNamespace = null;
555     return new MapBasedInvocationURL(clone, namespace);
556   }
557
558   public String JavaDoc toString()
559   {
560     return "[MapBasedInvocationFactory actionNamespace=" + _actionNamespace
561       + " invocationMap=" + _invocationMap
562       + "]";
563   }
564
565   private static class MapBasedInvocation implements Invocation, Cloneable JavaDoc
566   {
567     private MapBasedInvocationFactory _factory;
568
569     private String JavaDoc _namespace;
570     private WindowState _windowState = WindowState.NORMAL;
571     private PortletMode _portletMode = PortletMode.VIEW;
572     private Map JavaDoc<String JavaDoc, String JavaDoc[]> _parameterMap;
573
574     public MapBasedInvocation(MapBasedInvocationFactory factory)
575     {
576       _factory = factory;
577     }
578
579     public void start(String JavaDoc namespace)
580     {
581       if (_namespace != null)
582         throw new IllegalStateException JavaDoc("missing finish()?");
583
584       _namespace = namespace;
585     }
586
587     public void finish()
588     {
589       _windowState = WindowState.NORMAL;
590       _portletMode = PortletMode.VIEW;
591       if (_parameterMap != null)
592         _parameterMap.clear();
593       _namespace = null;
594     }
595
596     public MapBasedInvocation clone(boolean keepParameters)
597     {
598       try {
599         MapBasedInvocation clone = (MapBasedInvocation) super.clone();
600
601         if (keepParameters && _parameterMap != null)
602           clone._parameterMap
603             = new LinkedHashMap JavaDoc<String JavaDoc, String JavaDoc[]>(_parameterMap);
604         else
605           clone._parameterMap = null;
606
607         return clone;
608       }
609       catch (CloneNotSupportedException JavaDoc ex) {
610         throw new RuntimeException JavaDoc(ex);
611       }
612     }
613
614     public String JavaDoc getNamespace()
615     {
616       return _namespace;
617     }
618
619     public boolean isActionTarget()
620     {
621       return _factory.isActionTarget(_namespace);
622     }
623
624     public Map JavaDoc<String JavaDoc, String JavaDoc[]> getParameterMap()
625     {
626       if (_parameterMap == null)
627         _parameterMap = new LinkedHashMap JavaDoc<String JavaDoc, String JavaDoc[]>();
628
629       return _parameterMap;
630     }
631
632     public Map JavaDoc<String JavaDoc, String JavaDoc[]> releaseParameterMap()
633     {
634       Map JavaDoc<String JavaDoc, String JavaDoc[]> map = getParameterMap();
635       _parameterMap = null;
636       return map;
637     }
638
639     public WindowState getWindowState()
640     {
641       return _windowState;
642     }
643
644     public void setWindowState(WindowState windowState)
645     {
646       _windowState = windowState == null ? WindowState.NORMAL : windowState;
647       _factory.addWindowStateUsed(_windowState);
648     }
649
650     void setWindowStateName(String JavaDoc[] values)
651     {
652       String JavaDoc windowStateName
653         = values == null || values.length == 0 ? null : values[0];
654
655       if (windowStateName == null)
656         setWindowState(WindowState.NORMAL);
657       else if (windowStateName.equals("normal"))
658           setWindowState(WindowState.NORMAL);
659       else if (windowStateName.equals("minimized"))
660           setWindowState(WindowState.MINIMIZED);
661       else if (windowStateName.equals("maximized"))
662         setWindowState(WindowState.MAXIMIZED);
663       else
664         setWindowState(new WindowState(windowStateName));
665     }
666
667     public PortletMode getPortletMode()
668     {
669       return _portletMode;
670     }
671
672     public void setPortletMode(PortletMode portletMode)
673     {
674       _portletMode = portletMode == null ? PortletMode.VIEW : portletMode;
675       _factory.addPortletModeUsed(_portletMode);
676     }
677
678     void setPortletModeName(String JavaDoc[] values)
679     {
680       String JavaDoc portletModeName
681         = values == null || values.length == 0 ? null : values[0];
682
683       if (portletModeName == null)
684         setPortletMode(PortletMode.VIEW);
685       else if (portletModeName.equals("view"))
686           setPortletMode(PortletMode.VIEW);
687       else if (portletModeName.equals("edit"))
688           setPortletMode(PortletMode.EDIT);
689       else if (portletModeName.equals("help"))
690           setPortletMode(PortletMode.HELP);
691       else
692         setPortletMode(new PortletMode(portletModeName));
693     }
694
695     public InvocationURL createActionURL()
696     {
697       return _factory.createActionURL(_namespace);
698     }
699
700     public InvocationURL createRenderURL()
701     {
702       return _factory.createRenderURL(_namespace);
703     }
704
705     public String JavaDoc toString()
706     {
707       return "[MapBasedInvocationFactory "
708         + " namespace=" + _namespace
709         + " windowState=" + _windowState
710         + " portletMode=" + _portletMode
711         + " parameters=" + _parameterMap
712         + "]";
713
714     }
715   }
716
717   static class MapBasedInvocationURL
718     extends InvocationURL
719   {
720     MapBasedInvocationFactory _factory;
721
722     MapBasedInvocationURL(MapBasedInvocationFactory factory, String JavaDoc namespace)
723     {
724       super(factory, namespace);
725       _factory = factory;
726     }
727
728     public String JavaDoc getURL()
729     {
730       return _factory.getURL();
731     }
732
733   }
734 }
735
736
Popular Tags