KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > bridge > jsp > taglib > pageflow > TreeHelper


1 /*
2  
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5  
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8  
9  */

10
11 package org.mmbase.bridge.jsp.taglib.pageflow;
12
13 import java.io.File JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15 import java.util.Stack JavaDoc;
16 import javax.servlet.jsp.JspTagException JavaDoc;
17 import javax.servlet.http.HttpSession JavaDoc;
18 import org.mmbase.bridge.*;
19 import org.mmbase.util.logging.Logger;
20 import org.mmbase.util.logging.Logging;
21 import org.mmbase.module.core.MMBaseContext;
22
23 /**
24  * This helper-class has all Tree- and Leaf-related functionality. The algorithms that find the
25  * page to include in the directory structure are implemented here.
26  *
27  * The 'TreeInclude', 'LeafInclude', 'TreeFile' and 'LeafFile' all use this helper class. See their
28  * documentation for more information about the algorithms.
29  *
30  * @author Johannes Verelst
31  * @author Rob Vermeulen (VPRO)
32  * @version $Id: TreeHelper.java,v 1.13.2.1 2006/11/30 11:22:09 michiel Exp $
33  */

34
35 public class TreeHelper {
36     /*
37         Idea:
38             - we have a list of objectnumbers
39             - find the builder for every object
40             - call 'getSmartPath() for every object', using the cumulative
41               path as 'relative' path for the next getSmartPath() call
42             - if a path doesn't exist, we will (if we are LeafParting) look at
43               the builder-names to continue the path-walking
44             - walk the list backwards and try to find 'page' in the
45               path, if found, return that page. If not found, continue
46      
47         Needed:
48             - How to find a builder for an objectnumber? Use bridge
49             - How to find out in which path we are now? Use getRealPath
50      */

51     
52     private Cloud cloud;
53     private static final Logger log = Logging.getLoggerInstance(TreeHelper.class);
54     private static String JavaDoc htmlroot = MMBaseContext.getHtmlRoot();
55     
56     public void setCloud(Cloud cl) {
57         cloud = cl;
58     }
59     
60     /**
61      * Method to find the file to 'LeafInclude' given a list of objectnumbers
62      * @param includePage The page to include (relative path, may include URL parameters)
63      * @param objectlist The list of objectnumbers (comma-seperated) that is used to find the correct file to include
64      * @param session The session context can contain version information (used in getVerion).
65      */

66     protected String JavaDoc findLeafFile(String JavaDoc includePage, String JavaDoc objectlist, HttpSession JavaDoc session) throws JspTagException JavaDoc {
67         if ("".equals(objectlist)) {
68             return encodedPath(includePage);
69         }
70         String JavaDoc lf = getLeafFile("/", objectlist, includePage, true, session);
71         log.debug("findLeafFile = [" + lf + "]");
72         return encodedPath(lf);
73     }
74
75     /**
76      * Return the path to the include file. This path will start with the given prefix, appended by data calculated using
77      * the objectlist. If mayStartpath is true, then smartpath() will be called on objects in the objectlist,
78      * otherwise only their buildernames will be used.
79      * @param includePage The page to include (relative path, may include URL parameters)
80      * @param objectlist The list of objectnumbers (comma-seperated) that is used to find the correct file to include
81      * @param session The session context can contain version information (used in getVerion).
82      * @param maySmartpath Boolean indicating whether or not getLeafFile may call a 'getSmartpath' on the given objects
83      * @param prefix The path that was already established by previous calls to getLeafFile, deeper in the recursion tree.
84      */

85     protected String JavaDoc getLeafFile(String JavaDoc prefix, String JavaDoc objectlist, String JavaDoc includePage, boolean maySmartpath, HttpSession JavaDoc session) throws JspTagException JavaDoc {
86         if (objectlist.equals("")) {
87             String JavaDoc nudePage = includePage;
88             if (nudePage.indexOf('?') != -1) {
89                 nudePage = nudePage.substring(0, nudePage.indexOf('?'));
90             }
91
92             String JavaDoc filename = concatpath(prefix, nudePage);
93             log.debug("Check file: " + filename + " in root " + htmlroot);
94
95             if ((new File JavaDoc(concatpath(htmlroot, filename))).exists()) {
96                 // make sure that the path we return starts with a 'file.separator'
97
return concatpath(prefix, includePage);
98             } else {
99                 return "";
100             }
101         }
102
103         int firstComma = objectlist.indexOf(',');
104         String JavaDoc firstObject = null;
105         String JavaDoc otherObjects = null;
106
107         if (firstComma > 0) {
108             firstObject = objectlist.substring(0, firstComma);
109             otherObjects = objectlist.substring(firstComma + 1, objectlist.length());
110             log.debug("Splitting '" + objectlist + "' into '" + firstObject + "' and '" + otherObjects + "'");
111         } else {
112             firstObject = objectlist;
113             otherObjects = "";
114             log.debug("Only one object left: '" + firstObject + "'");
115         }
116
117         String JavaDoc finalfile = null;
118
119         // It can be the case that the first object here is not a number,
120
// but a intermediate path. In that case we concatenate this intermediate
121
// path with the path we already have (prefix) and continue with the recursive
122
// loop
123
try {
124             cloud.getNode(firstObject);
125         } catch (org.mmbase.bridge.NotFoundException e) {
126             log.debug("'" + firstObject + "' is not an object; seeing it as a path)");
127             return getLeafFile (concatpath(prefix, firstObject), otherObjects, includePage, maySmartpath, session);
128         }
129
130         // Try to find the best file (so starting with the best option)
131
// We walk the first object in the objectlist, and evaluate its
132
// smartpath. We will append that to the prefix, and continue recursively.
133

134         if (maySmartpath) {
135             String JavaDoc newprefix = prefix;
136             String JavaDoc smartpath = getSmartPath(firstObject, newprefix, session);
137             log.debug("getSmartPath(" + firstObject + "," + newprefix + "," + session + ") = " + smartpath);
138             if (!(smartpath == null || smartpath.equals(""))) {
139                 newprefix = smartpath;
140                 finalfile = getLeafFile(newprefix, otherObjects, includePage, true, session);
141             }
142         }
143
144         // In case the recursive call failed, or the 'maySmartPath' was false,
145
// we create a list of buildernames for this object; the builder of the
146
// object with the parents of that builder. We then recurse again for
147
// all these names, but we put the 'maySmartpath' to false for these
148
// recursive calls.
149

150         if (finalfile == null || "".equals(finalfile)) {
151             NodeManager nm = cloud.getNode(firstObject).getNodeManager();
152             while (nm != null) {
153                 finalfile = getLeafFile(concatpath(prefix, nm.getName()) + File.separator, otherObjects, includePage, false, session);
154                 if (!(finalfile == null || "".equals(finalfile)))
155                     return finalfile;
156                 try {
157                     nm = nm.getParent();
158                 } catch (NotFoundException e) {
159                     nm = null;
160                 }
161             }
162         } else {
163             return finalfile;
164         }
165         return "";
166     }
167     
168     /**
169      * Method to find the file to 'TreeInclude' given a list of objectnumbers
170      * @param includePage The page to include (relative path, may include URL parameters)
171      * @param objectlist The list of objectnumbers (comma-seperated) that is used to find the correct file to include
172      * @param session The session context can contain version information (used in getVerion).
173      * TODO: add support for 'intermediate paths' as LeafInclude has.
174      */

175     protected String JavaDoc findTreeFile(String JavaDoc includePage, String JavaDoc objectlist, HttpSession JavaDoc session) throws JspTagException JavaDoc {
176         if (cloud == null) {
177             throw new JspTagException JavaDoc("Cloud was not defined");
178         }
179         
180         // We have to find a specific page, so we must remove any arguments
181
String JavaDoc nudePage;
182         if (includePage.indexOf('?') != -1)
183             nudePage = includePage.substring(0, includePage.indexOf('?'));
184         else
185             nudePage = includePage;
186         
187         // Initialize the variables
188
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(objectlist, ",");
189         int numberTokens = st.countTokens();
190         Stack JavaDoc objectPaths = new Stack JavaDoc();
191         
192         int objectNumbers[] = new int[numberTokens];
193         String JavaDoc pathNow = "/";
194         
195         // Move all the objectnumbers into the array
196
for (int i = 0; i < numberTokens; i++) {
197             objectNumbers[i] = Integer.parseInt(st.nextToken());
198         }
199         
200         // Find the paths for all the nodes in the nodelist
201
for (int i = 0; i < numberTokens; i++) {
202             int objectNo = objectNumbers[i];
203             String JavaDoc field = getSmartPath("" + objectNo, pathNow, session);
204             
205             if (field == null || field.equals("")) {
206                 break;
207             }
208             
209             pathNow = field;
210             objectPaths.push(pathNow);
211         }
212         
213         // We now have a list of paths in a stack, we must now find the best one.
214
// this means we walk the stack backwards (wow, what an amazing data-type :)
215
// We return the first path we find that != null and that contains 'page'
216

217         pathNow = "";
218         while (!objectPaths.empty()) {
219             String JavaDoc path = (String JavaDoc)objectPaths.pop();
220
221             String JavaDoc pathTest = concatpath(concatpath(htmlroot, path), nudePage);
222
223             log.debug("Check file: " + pathTest);
224             if ((new File JavaDoc(pathTest)).isFile()) {
225                 // Make sure that the path is correctly encoded, if it contains spaces these must be
226
// changed into '%20' etc.
227
return encodedPath(concatpath(path, includePage));
228             }
229         }
230         
231         // Check if the file exists in the 'root'
232
log.debug("Check file: " + concatpath(htmlroot, nudePage));
233         if (new File JavaDoc(concatpath(htmlroot, nudePage)).isFile()) {
234             return includePage;
235         } else {
236             return "";
237         }
238     }
239     
240     /**
241      * A version can be set to easily make copies of websites.
242      * By setting a sessions variable with name = object type and value = number,
243      * will affect the getSmartpath method by adding the number to the end of the found smartpath.
244      * Only if the object type corresponds to the object type of which the smartpath is evaluated.
245      * @param objectnumber the objectnumber used in the smartpath
246      * @return a versionnumber, or an empty string otherwise.
247      */

248     private String JavaDoc getVersion(String JavaDoc objectnumber, HttpSession JavaDoc session) throws JspTagException JavaDoc {
249         if (session == null) {
250             // No session variable set
251
return "";
252         }
253         String JavaDoc versionnumber = (String JavaDoc)session.getAttribute(getBuilderName(objectnumber) + "version");
254         if (versionnumber == null) {
255             // The session variable was not set.
256
return "";
257         }
258         return versionnumber;
259     }
260     
261     /**
262      * gets the object type name of an object.
263      * @param objectnumber the object number of which you want the object type name
264      * @return the object type
265      */

266     private String JavaDoc getBuilderName(String JavaDoc objectnumber) throws JspTagException JavaDoc {
267         return cloud.getNode(objectnumber).getNodeManager().getName();
268     }
269     
270     /**
271      * get the smartpath of a certain object
272      * @param objectnummer the object of which you want to evaluate the smartpath.
273      * @param middle the path already evaluated (this is not used in current code).
274      * @return the smartpath
275      */

276     private String JavaDoc getSmartPath(String JavaDoc objectnumber, String JavaDoc middle, HttpSession JavaDoc session) throws JspTagException JavaDoc {
277         return (String JavaDoc)cloud.getNode(objectnumber).getValue("smartpath(" + htmlroot + "," + middle + "," + getVersion(objectnumber, session) + ")");
278     }
279     
280     /**
281      * Rewrite a path that points to a file on the filesystem to an URL path.
282      * - Split the path on 'File.seperator'
283      * - except for the last part (the file), escape all the parts
284      * - combine the parts with a '/'
285      *
286      * @param fileSystemPath the path on a filesystem pointing to a files
287      * @returns the URL-escaped version of the path
288      */

289     private String JavaDoc encodedPath(String JavaDoc fileSystemPath) {
290         String JavaDoc fp = fileSystemPath;
291         if (fp == null) {
292             fp = "";
293         }
294         File JavaDoc f = new File JavaDoc(fp);
295         String JavaDoc result = f.getName();
296         f = f.getParentFile();
297         while (f != null) {
298             String JavaDoc thisPart = f.getName();
299             result = org.mmbase.util.Encode.encode("ESCAPE_URL", thisPart) + "/" + result;
300             f = f.getParentFile();
301         }
302         return result;
303     }
304
305     /**
306      * Concatenate two paths; possibly adding or removing File.separator characters
307      * Return path1/path2
308      */

309     private String JavaDoc concatpath(String JavaDoc path1, String JavaDoc path2) {
310         if (path1 == null && path2 == null) {
311             return "";
312         } else if (path1 == null) {
313             return path2;
314         } else if (path2 == null) {
315             return path1;
316         }
317         if (path1.endsWith(File.separator) && path2.startsWith(File.separator)) {
318             // we remove the File.separator from the 2nd path element
319
return path1 + path2.substring(File.separator.length());
320         } else if (!path1.endsWith(File.separator) && !path2.startsWith(File.separator)) {
321             return path1 + File.separator + path2;
322         } else {
323             return path1 + path2;
324         }
325     }
326
327     public void doFinally() {
328         cloud = null;
329     }
330 }
331
Popular Tags