1 package org.astrogrid.portal.myspace.generation ;
2
3 import java.io.IOException;
4 import java.net.URL;
5 import java.util.Map;
6 import java.io.StringReader ;
7
8 import org.apache.avalon.framework.parameters.Parameters;
9 import org.apache.cocoon.ProcessingException;
10 import org.apache.cocoon.environment.ObjectModelHelper;
11 import org.apache.cocoon.environment.Request;
12 import org.apache.cocoon.environment.Session;
13 import org.apache.cocoon.environment.SourceResolver;
14 import org.apache.cocoon.generation.AbstractGenerator;
15 import org.astrogrid.community.User;
16
17 import org.astrogrid.portal.myspace.acting.framework.ContextWrapper;
18 import org.astrogrid.portal.myspace.acting.framework.ContextWrapperFactory;
19 import org.astrogrid.portal.utils.acting.ActionUtils;
20 import org.astrogrid.portal.utils.acting.ActionUtilsFactory;
21 import org.astrogrid.store.Agsl;
22 import org.astrogrid.store.Ivorn;
23 import org.astrogrid.store.delegate.StoreClient;
24 import org.astrogrid.store.delegate.StoreFile;
25 import org.w3c.dom.Document;
26 import org.w3c.dom.Element;
27 import org.xml.sax.SAXException;
28 import org.xml.sax.helpers.XMLReaderFactory;
29 import org.xml.sax.XMLReader;
30 import org.xml.sax.InputSource;
31
32 /***
33 * Generate <code>StoreClient</code> list of files as XML.
34 *
35 * @author peter.shillan
36 */
37 public class StorageFilesGenerator extends AbstractGenerator {
38
39 private static final boolean TRACE_ENABLED = false ;
40 private static final boolean DEBUG_ENABLED = false ;
41 private static final String FILTER = "*";
42 private static final String SEPARATOR = "/";
43 private static final String MYSPACE_TREE = "myspace-tree";
44 private static final String MYSPACE_ITEM = "myspace-item";
45 private static final String MYSPACE_ENDPOINT_ATTR = "endpoint";
46 private static final String MYSPACE_FILE_ATTR = "file";
47 private static final String MYSPACE_FOLDER_ATTR = "folder";
48
49 private ContextWrapper context;
50
51 /***
52 * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
53 */
54 public void setup(SourceResolver resolver, Map objectModel, String src, Parameters params)
55 throws ProcessingException, SAXException, IOException {
56 super.setup(resolver, objectModel, src, params);
57
58
59 ActionUtils utils = ActionUtilsFactory.getActionUtils();
60 Request request = ObjectModelHelper.getRequest(objectModel);
61 Session session = request.getSession(true);
62
63
64 context = ContextWrapperFactory.getContextWrapper(
65 ContextWrapper.PARAM_PROTOCOL, utils, params, request, session);
66 }
67
68 /***
69 * Generate <code>StoreClient</code> list of files into as XML.
70 *
71 * @see org.apache.cocoon.generation.Generator#generate()
72 */
73 public void generate() throws IOException, SAXException, ProcessingException {
74 if( TRACE_ENABLED) this.getLogger().debug( "enter: StorageFilesGenerator.generate()" );
75
76 try {
77
78 StoreFile userFile = getUserFile();
79
80 if(userFile != null) {
81 StorageItemTree tree = new StorageItemTree( userFile ) ;
82 XMLReader xmlReader = XMLReaderFactory.createXMLReader() ;
83 xmlReader.setContentHandler( super.xmlConsumer ) ;
84 InputSource source = new InputSource( new StringReader( tree.toXmlString() ) ) ;
85 xmlReader.parse( source ) ;
86 }
87 else {
88 this.getLogger().error("cannot find files for user");
89
90 }
91
92 }
93 catch( IOException iox ) {
94 this.getLogger().error("cannot find files for user");
95
96 }
97 finally {
98 if( TRACE_ENABLED) this.getLogger().debug( "exit: StorageFilesGenerator.generate()" );
99 }
100
101 }
102
103
104 /***
105 * @return
106 */
107 private StoreFile getUserFile() throws IOException {
108 if( TRACE_ENABLED) this.getLogger().debug( "enter: StorageFilesGenerator.getUserFile()" );
109
110 StoreFile userFiles = null;
111 String cacheRequest = null ;
112
113 try{
114
115 User user = context.getUser();
116 if(user == null) {
117 return null;
118 }
119
120 String userId = user.getUserId();
121 if(userId == null || userId.length() == 0) {
122 return null;
123 }
124
125 cacheRequest = context.getParameter( "myspace-refresh-cache" ) ;
126 if( DEBUG_ENABLED) this.getLogger().debug( "cacheRequest: " + (cacheRequest==null ? "null" : "[" + cacheRequest.toString() + "]") );
127 if( cacheRequest != null && cacheRequest.equalsIgnoreCase( "yes") ) {
128 context.setMySpaceCache( null ) ;
129 }
130
131 userFiles = context.getMySpaceCache() ;
132 if( DEBUG_ENABLED) this.getLogger().debug( "userFiles from cache: " + userFiles );
133 if( userFiles != null ) {
134 return userFiles ;
135 }
136
137
138 StoreClient storeClient = context.getStoreClient();
139 if(storeClient == null) {
140 return null;
141 }
142
143 StoreFile root = storeClient.getFiles(getUserFilter(userId));
144 if(root == null) {
145 return null;
146 }
147
148 StoreFile[] allUsers = root.listFiles();
149
150
151 for(int userIndex = 0; userIndex < allUsers.length && userFiles == null; userIndex++) {
152 if(userId.equals(allUsers[userIndex].getName())) {
153 userFiles = allUsers[userIndex];
154 }
155 }
156
157 if( DEBUG_ENABLED) this.getLogger().debug( "userFiles into cache: " + userFiles );
158 context.setMySpaceCache( userFiles ) ;
159
160 }
161 catch( Throwable t ) {
162 t.printStackTrace() ;
163 }
164 finally {
165 if( TRACE_ENABLED) this.getLogger().debug( "exit: StorageFilesGenerator.getUserFile()" );
166 }
167
168 return userFiles;
169
170 }
171
172
173 private String getUserFilter(String userId) {
174
175 return StorageFilesGenerator.SEPARATOR + userId + StorageFilesGenerator.FILTER;
176 }
177
178
179 private String getSafeName(String fileName) {
180 StringBuffer result = new StringBuffer(32);
181
182 char character = 0;
183 for(int cIndex = 0; cIndex < fileName.length(); cIndex++) {
184 character = fileName.charAt(cIndex);
185 switch(character) {
186 case '/':
187 case '@':
188 case ' ':
189 result.append('_');
190 break;
191
192 default:
193 result.append(character);
194 break;
195 }
196 }
197
198 return result.toString();
199 }
200
201
202 private String getFolderPath(String filePath, String fileName) {
203 String result = "";
204
205 if(filePath != null) {
206 if(fileName != null) {
207 result = filePath.substring(0, filePath.length() - fileName.length());
208 if (result.endsWith("/")) {
209 result = result.substring(0, result.length());
210 }
211 }
212 }
213
214 return result;
215 }
216
217
218 private abstract class StorageItem {
219
220 protected StoreFile myStoreFile ;
221
222 public StorageItem ( StoreFile storeFile ) {
223 this.myStoreFile = storeFile ;
224 }
225
226 abstract public String toXmlString() throws ProcessingException;
227
228 /***
229 * @return Returns the storeFile.
230 */
231 public StoreFile getStoreFile() {
232 return myStoreFile;
233 }
234
235 /***
236 * @return Returns the type.
237 */
238 public abstract String getType() ;
239
240 }
241
242
243 private class FileItem extends StorageItem {
244
245 public FileItem( StoreFile storeFile ) {
246 super( storeFile ) ;
247 }
248
249 public String getType() {
250 return StorageFilesGenerator.MYSPACE_FILE_ATTR ;
251 }
252
253 public String toXmlString() throws ProcessingException {
254 if( TRACE_ENABLED) getLogger().debug( "entry: FileItem.toXmlString()" );
255 StringBuffer buffer = new StringBuffer(128) ;
256
257 String fileName = myStoreFile.getName();
258 String filePath = myStoreFile.getPath();
259 String safeName = getSafeName(filePath);
260
261 buffer
262 .append( "<" )
263 .append( StorageFilesGenerator.MYSPACE_ITEM )
264 .append( " type=\"" )
265 .append( StorageFilesGenerator.MYSPACE_FILE_ATTR )
266 .append( "\" ")
267 .append( " safe-name=\"" )
268 .append( safeName )
269 .append( "\" ")
270 .append( " full-name=\"" )
271 .append( filePath )
272 .append( "\" ")
273 .append( " item-name=\"" )
274 .append( fileName )
275 .append( "\" ")
276 .append( " id=\"" )
277 .append( safeName )
278 .append( "\" ") ;
279
280 try {
281 if( DEBUG_ENABLED) getLogger().debug("context.getStoreClient().getAgsl(filePath) start");
282 Agsl agsl = context.getStoreClient().getAgsl(filePath);
283 if( DEBUG_ENABLED) getLogger().debug("context.getStoreClient().getAgsl(filePath) end");
284
285
286
287
288
289
290
291
292 buffer
293 .append( " url=\"" )
294
295 .append( "duff url" )
296 .append( "\" ")
297 .append( " ivorn=\"" )
298 .append( agsl.toIvorn(context.getUser()).toString() )
299 .append( "\" ")
300 .append( " folder-path=\"" )
301 .append( getFolderPath(filePath, fileName) )
302 .append( "\" ")
303 .append( ">" ) ;
304
305
306
307
308
309
310
311 }
312 catch(IOException e) {
313 throw new ProcessingException("could not resolve AstroGrid URL for [" + fileName + "]", e);
314 }
315
316 buffer
317 .append( "</" )
318 .append( StorageFilesGenerator.MYSPACE_ITEM )
319 .append( ">" ) ;
320
321 if( TRACE_ENABLED) getLogger().debug( "exit: FileItem.toXmlString()" );
322 return buffer.toString() ;
323 }
324
325 }
326
327
328 private class FolderItem extends StorageItem {
329
330 public FolderItem( StoreFile storeFile ) {
331 super( storeFile ) ;
332 }
333
334 public String getType() {
335 return StorageFilesGenerator.MYSPACE_FOLDER_ATTR ;
336 }
337
338 public String toXmlString() throws ProcessingException {
339 if( TRACE_ENABLED) getLogger().debug( "entry: FolderItem.toXmlString()" );
340 StringBuffer buffer = new StringBuffer(128) ;
341
342 String fileName = myStoreFile.getName();
343 String filePath = myStoreFile.getPath();
344 String safeName = getSafeName(filePath);
345
346 buffer
347 .append( "<" )
348 .append( StorageFilesGenerator.MYSPACE_ITEM )
349 .append( " type=\"" )
350 .append( StorageFilesGenerator.MYSPACE_FOLDER_ATTR )
351 .append( "\" ")
352 .append( " safe-name=\"" )
353 .append( safeName )
354 .append( "\" ")
355 .append( " full-name=\"" )
356 .append( filePath )
357 .append( "\" ")
358 .append( " item-name=\"" )
359 .append( fileName )
360 .append( "\" ")
361 .append( " id=\"" )
362 .append( safeName )
363 .append( "\" ")
364 .append( " folder-path=\"" )
365 .append( filePath )
366 .append( "\" ")
367 .append( ">" ) ;
368
369 StoreFile[] storeFiles = myStoreFile.listFiles();
370
371 for(int fileIndex = 0; fileIndex < storeFiles.length; fileIndex++) {
372 if( storeFiles[fileIndex].isFile() ){
373 buffer.append( new FileItem( storeFiles[fileIndex] ).toXmlString() ) ;
374 }
375 else if( storeFiles[fileIndex].isFolder() ){
376 buffer.append( new FolderItem( storeFiles[fileIndex] ).toXmlString() ) ;
377 }
378 }
379
380 buffer
381 .append( "</" )
382 .append( StorageFilesGenerator.MYSPACE_ITEM )
383 .append( ">" ) ;
384
385 if( TRACE_ENABLED) getLogger().debug( "exit: FolderItem.toXmlString()" );
386 return buffer.toString() ;
387 }
388
389 }
390
391 private class StorageItemTree {
392
393 private StoreFile root ;
394 private StorageItem[] topLevel ;
395
396 public StorageItemTree( StoreFile storeFile ) {
397 this.root = storeFile ;
398 this.topLevel = new StorageItem[1] ;
399 this.topLevel[0] = new FolderItem( storeFile ) ;
400
401
402
403
404
405
406
407
408
409
410
411
412
413 }
414
415
416 public String toXmlString() throws IOException, ProcessingException {
417
418 StringBuffer buffer = new StringBuffer( 4096 ) ;
419 String returnValue ;
420
421 buffer
422 .append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" )
423 .append( "<" )
424 .append( StorageFilesGenerator.MYSPACE_TREE )
425 .append( ' ' )
426 .append( StorageFilesGenerator.MYSPACE_ENDPOINT_ATTR )
427 .append( "=\"" )
428 .append( context.getAgsl().toIvorn(context.getUser()).toString() )
429 .append( "\" >" ) ;
430
431 for(int fileIndex = 0; fileIndex < topLevel.length; fileIndex++) {
432 if( topLevel[fileIndex] != null )
433 buffer.append( topLevel[fileIndex].toXmlString() ) ;
434 }
435
436 buffer
437 .append( "</" )
438 .append( StorageFilesGenerator.MYSPACE_TREE )
439 .append( ">" ) ;
440
441 returnValue = buffer.toString() ;
442 if( DEBUG_ENABLED) getLogger().debug( "MySpaceTree...\n" + returnValue );
443
444 return buffer.toString() ;
445
446 }
447
448 }
449
450 }