001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.portal.coplets.basket;
018:
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.FileOutputStream;
022: import java.io.IOException;
023: import java.io.InputStreamReader;
024: import java.io.ObjectInputStream;
025: import java.io.ObjectOutputStream;
026: import java.lang.reflect.Constructor;
027: import java.util.ArrayList;
028: import java.util.HashMap;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Map;
032:
033: import org.apache.avalon.framework.activity.Disposable;
034: import org.apache.avalon.framework.activity.Initializable;
035: import org.apache.avalon.framework.component.Component;
036: import org.apache.avalon.framework.context.Context;
037: import org.apache.avalon.framework.context.ContextException;
038: import org.apache.avalon.framework.context.Contextualizable;
039: import org.apache.avalon.framework.logger.AbstractLogEnabled;
040: import org.apache.avalon.framework.parameters.ParameterException;
041: import org.apache.avalon.framework.parameters.Parameterizable;
042: import org.apache.avalon.framework.parameters.Parameters;
043: import org.apache.avalon.framework.service.ServiceException;
044: import org.apache.avalon.framework.service.ServiceManager;
045: import org.apache.avalon.framework.service.Serviceable;
046: import org.apache.avalon.framework.thread.ThreadSafe;
047: import org.apache.cocoon.Constants;
048: import org.apache.cocoon.ProcessingException;
049: import org.apache.cocoon.components.ContextHelper;
050: import org.apache.cocoon.components.cron.CronJob;
051: import org.apache.cocoon.components.cron.JobScheduler;
052: import org.apache.cocoon.components.cron.ServiceableCronJob;
053: import org.apache.cocoon.environment.Request;
054: import org.apache.cocoon.environment.Session;
055: import org.apache.cocoon.portal.PortalService;
056: import org.apache.cocoon.portal.coplet.CopletData;
057: import org.apache.cocoon.portal.coplet.CopletInstanceData;
058: import org.apache.cocoon.portal.coplets.basket.events.AddItemEvent;
059: import org.apache.cocoon.portal.coplets.basket.events.ContentStoreEvent;
060: import org.apache.cocoon.portal.coplets.basket.events.CleanBriefcaseEvent;
061: import org.apache.cocoon.portal.coplets.basket.events.MoveItemEvent;
062: import org.apache.cocoon.portal.coplets.basket.events.RefreshBasketEvent;
063: import org.apache.cocoon.portal.coplets.basket.events.RemoveItemEvent;
064: import org.apache.cocoon.portal.coplets.basket.events.ShowBasketEvent;
065: import org.apache.cocoon.portal.coplets.basket.events.ShowItemEvent;
066: import org.apache.cocoon.portal.coplets.basket.events.UploadItemEvent;
067: import org.apache.cocoon.portal.event.EventManager;
068: import org.apache.cocoon.portal.event.Receiver;
069: import org.apache.cocoon.portal.layout.impl.CopletLayout;
070: import org.apache.cocoon.servlet.multipart.Part;
071: import org.apache.cocoon.servlet.multipart.PartOnDisk;
072: import org.apache.cocoon.util.ClassUtils;
073: import org.apache.commons.io.IOUtils;
074: import org.apache.excalibur.source.Source;
075: import org.apache.excalibur.source.SourceResolver;
076:
077: /**
078: * This is the implementation of the basket manager
079: *
080: * @version CVS $Id: BasketManagerImpl.java 433543 2006-08-22 06:22:54Z crossley $
081: */
082: public class BasketManagerImpl extends AbstractLogEnabled implements
083: BasketManager, Serviceable, Receiver, Contextualizable,
084: Initializable, Disposable, Parameterizable, ThreadSafe,
085: Component {
086:
087: /** The service manager */
088: protected ServiceManager manager;
089:
090: /** The component context */
091: protected Context context;
092:
093: /** The configuration for storing baskets */
094: protected String directory;
095:
096: /** The class name of the basket */
097: protected String basketClassName = Basket.class.getName();
098:
099: /** The class name of the briefcase */
100: protected String briefcaseClassName = Briefcase.class.getName();
101:
102: /** The class name of the folder */
103: protected String folderClassName = Folder.class.getName();
104:
105: /** All actions for a basket */
106: protected List basketActions = new ArrayList();
107:
108: /** All actions for a briefcase */
109: protected List briefcaseActions = new ArrayList();
110:
111: /** All batches */
112: protected List batches = new ArrayList();
113:
114: /** Scheduler */
115: protected JobScheduler scheduler;
116:
117: /* (non-Javadoc)
118: * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
119: */
120: public void parameterize(Parameters parameters)
121: throws ParameterException {
122: this .directory = parameters.getParameter("directory",
123: this .directory);
124: this .basketClassName = parameters.getParameter("basket-class",
125: this .basketClassName);
126: this .briefcaseClassName = parameters.getParameter(
127: "briefcase-class", this .briefcaseClassName);
128: this .folderClassName = parameters.getParameter("folder-class",
129: this .folderClassName);
130: String[] names = parameters.getNames();
131: if (names != null) {
132: for (int i = 0; i < names.length; i++) {
133: final String current = names[i];
134: if (current.startsWith("basket:action:")) {
135: final String value = parameters
136: .getParameter(current);
137: final String key = current.substring(14);
138: this .basketActions.add(new ActionInfo(key, value));
139: } else if (current.startsWith("briefcase:action:")) {
140: final String value = parameters
141: .getParameter(current);
142: final String key = current.substring(17);
143: this .briefcaseActions
144: .add(new ActionInfo(key, value));
145: }
146: }
147: }
148: }
149:
150: /* (non-Javadoc)
151: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
152: */
153: public void contextualize(Context context) throws ContextException {
154: this .context = context;
155: this .directory = ((File) context
156: .get(Constants.CONTEXT_WORK_DIR)).getAbsolutePath();
157: }
158:
159: /* (non-Javadoc)
160: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
161: */
162: public void service(ServiceManager manager) throws ServiceException {
163: this .manager = manager;
164: this .scheduler = (JobScheduler) this .manager
165: .lookup(JobScheduler.ROLE);
166: }
167:
168: /* (non-Javadoc)
169: * @see org.apache.avalon.framework.activity.Disposable#dispose()
170: */
171: public void dispose() {
172: if (this .manager != null) {
173: this .manager.release(this .scheduler);
174: this .scheduler = null;
175: this .manager = null;
176: }
177: }
178:
179: /* (non-Javadoc)
180: * @see org.apache.avalon.framework.activity.Initializable#initialize()
181: */
182: public void initialize() throws Exception {
183: EventManager eventManager = null;
184: try {
185: eventManager = (EventManager) this .manager
186: .lookup(EventManager.ROLE);
187: eventManager.subscribe(this );
188: } finally {
189: this .manager.release(eventManager);
190: }
191: }
192:
193: /**
194: * @see Receiver
195: */
196: public void inform(ContentStoreEvent event, PortalService service) {
197: // dispatch
198: final Session session = ContextHelper.getRequest(this .context)
199: .getSession();
200: if (event instanceof AddItemEvent) {
201:
202: this .processAddItemEvent((AddItemEvent) event);
203:
204: } else if (event instanceof RemoveItemEvent) {
205:
206: this .processRemoveItemEvent((RemoveItemEvent) event);
207:
208: } else if (event instanceof RefreshBasketEvent) {
209:
210: session.removeAttribute(ALL_BRIEFCASES_KEY);
211:
212: } else if (event instanceof CleanBriefcaseEvent) {
213:
214: this .processCleanBriefcaseEvent(
215: (CleanBriefcaseEvent) event, session);
216:
217: } else if (event instanceof UploadItemEvent) {
218:
219: this .processUploadItemEvent((UploadItemEvent) event);
220: } else if (event instanceof ShowItemEvent) {
221:
222: this .processShowItemEvent((ShowItemEvent) event);
223: } else if (event instanceof ShowBasketEvent) {
224:
225: this .processShowBasketEvent((ShowBasketEvent) event,
226: session);
227: } else if (event instanceof MoveItemEvent) {
228: ContentStore source = ((MoveItemEvent) event)
229: .getContentStore();
230: ContentStore target = ((MoveItemEvent) event).getTarget();
231: Object item = ((MoveItemEvent) event).getItem();
232: source.removeItem(item);
233: target.addItem(item);
234: this .saveContentStore(source);
235: this .saveContentStore(target);
236: }
237: }
238:
239: /**
240: * Process an upload and add the item to the content store
241: * @param event The event triggering the action
242: */
243: protected void processUploadItemEvent(UploadItemEvent event) {
244: final ContentStore store = event.getContentStore();
245: final Request req = ContextHelper.getRequest(this .context);
246: final List paramNames = event.getItemNames();
247: final Iterator i = paramNames.iterator();
248: while (i.hasNext()) {
249: final String name = (String) i.next();
250: final Object o = req.get(name);
251: if (o != null && o instanceof Part) {
252: final Part file = (Part) o;
253: try {
254: byte[] c = IOUtils.toByteArray(file
255: .getInputStream());
256: ContentItem ci = new ContentItem(
257: file.getFileName(), true);
258: ci.setContent(c);
259: store.addItem(ci);
260: } catch (Exception ignore) {
261: // ignore the exception
262: }
263: if (file instanceof PartOnDisk) {
264: ((PartOnDisk) file).getFile().delete();
265: }
266: }
267: }
268: }
269:
270: /**
271: * Show one item of the basket
272: * @param event The event triggering the action
273: */
274: protected void processShowItemEvent(ShowItemEvent event) {
275: if (event.getItem() instanceof ContentItem) {
276: PortalService service = null;
277: try {
278: service = (PortalService) this .manager
279: .lookup(PortalService.ROLE);
280:
281: ContentItem ci = (ContentItem) event.getItem();
282: CopletLayout layout = (CopletLayout) event.getLayout();
283: CopletInstanceData cid = null;
284: if (ci.isContent()) {
285: CopletData copletData = service
286: .getComponentManager().getProfileManager()
287: .getCopletData(event.getCopletDataId());
288: cid = service.getComponentManager()
289: .getCopletFactory().newInstance(copletData);
290: cid.setAttribute("item-content", ci.getContent());
291: } else {
292: if (ci.getURL() != null) {
293: SourceResolver resolver = null;
294: Source source = null;
295: String url = null;
296: try {
297: resolver = (SourceResolver) this .manager
298: .lookup(SourceResolver.ROLE);
299: url = ci.getURL();
300: source = resolver.resolveURI(url);
301: CopletData copletData = service
302: .getComponentManager()
303: .getProfileManager().getCopletData(
304: event.getCopletDataId());
305: cid = service.getComponentManager()
306: .getCopletFactory().newInstance(
307: copletData);
308: cid.setAttribute("item-content", IOUtils
309: .toByteArray(source
310: .getInputStream()));
311: } catch (IOException se) {
312: this .getLogger().warn(
313: "Unable to get content for " + url,
314: se);
315: } catch (ServiceException se) {
316: this .getLogger().warn(
317: "Unable to get source resolver.",
318: se);
319: } finally {
320: if (source != null) {
321: resolver.release(source);
322: }
323: this .manager.release(resolver);
324: }
325:
326: } else {
327: final CopletInstanceData original = service
328: .getComponentManager()
329: .getProfileManager()
330: .getCopletInstanceData(ci.getCopletId());
331: final CopletData copletData = original
332: .getCopletData();
333: cid = service.getComponentManager()
334: .getCopletFactory().newInstance(
335: copletData);
336: Map attributes = (Map) ci
337: .getAttribute("coplet-attributes");
338: Iterator i = attributes.entrySet().iterator();
339: while (i.hasNext()) {
340: Map.Entry entry = (Map.Entry) i.next();
341: cid.setAttribute(entry.getKey().toString(),
342: entry.getValue());
343: }
344: // now copy the original attributes
345: attributes = original.getAttributes();
346: i = attributes.entrySet().iterator();
347: while (i.hasNext()) {
348: Map.Entry entry = (Map.Entry) i.next();
349: cid.setAttribute(entry.getKey().toString(),
350: entry.getValue());
351: }
352: }
353: }
354: layout.setCopletInstanceData(cid);
355: } catch (ProcessingException pe) {
356: this .getLogger().warn("Unable to create new instance.",
357: pe);
358: } catch (ServiceException se) {
359: this .getLogger().warn(
360: "Unable to lookup portal service.", se);
361: } finally {
362: this .manager.release(service);
363: }
364: }
365: }
366:
367: /**
368: * Show the selected basket
369: */
370: protected void processShowBasketEvent(ShowBasketEvent event,
371: Session session) {
372: Briefcase briefcase = (Briefcase) this .loadContentStore(
373: BRIEFCASE_KEY, event.getBasketId());
374: session.setAttribute(BRIEFCASE_KEY, briefcase);
375: }
376:
377: /**
378: * Cleaning a briefcase or all
379: * @param event The triggering event
380: * @param session The session
381: */
382: protected void processCleanBriefcaseEvent(
383: CleanBriefcaseEvent event, Session session) {
384: final Briefcase briefcase = (Briefcase) event.getContentStore();
385: final List baskets = (List) session
386: .getAttribute(ALL_BRIEFCASES_KEY);
387: if (briefcase == null) {
388: // remove all briefcases
389: if (baskets != null) {
390: Iterator i = baskets.iterator();
391: while (i.hasNext()) {
392: ContentStoreDescription entry = (ContentStoreDescription) i
393: .next();
394: this .deleteContentStore(BRIEFCASE_KEY, entry.id);
395: }
396: session.removeAttribute(ALL_BRIEFCASES_KEY);
397: }
398: } else {
399: // remove one briefcase
400: this .deleteContentStore(BRIEFCASE_KEY, briefcase.getId());
401: if (baskets != null) {
402: Iterator i = baskets.iterator();
403: boolean found = false;
404: while (i.hasNext() && !found) {
405: ContentStoreDescription entry = (ContentStoreDescription) i
406: .next();
407: if (entry.id.equals(briefcase.getId())) {
408: found = true;
409: i.remove();
410: }
411: }
412: }
413: }
414: }
415:
416: /**
417: * This method processes removing one item from a content store
418: * @param event The event triggering the action
419: */
420: protected void processRemoveItemEvent(RemoveItemEvent event) {
421: final Object item = event.getItem();
422: final ContentStore store = event.getContentStore();
423:
424: store.removeItem(item);
425:
426: this .saveContentStore(store);
427: }
428:
429: /**
430: * This method processes adding one item to a content store
431: * @param event The event triggering the action
432: */
433: protected void processAddItemEvent(AddItemEvent event) {
434: final ContentStore store = event.getContentStore();
435: final Object item = event.getItem();
436: if (item instanceof ContentItem) {
437: ContentItem ci = (ContentItem) item;
438:
439: if (ci.isContent()) {
440: SourceResolver resolver = null;
441: Source source = null;
442: String url = null;
443: try {
444: resolver = (SourceResolver) this .manager
445: .lookup(SourceResolver.ROLE);
446: url = ci.getURL();
447: if (url == null) {
448: // copy coplet attributes
449: PortalService service = null;
450: try {
451: service = (PortalService) this .manager
452: .lookup(PortalService.ROLE);
453: CopletInstanceData cid = service
454: .getComponentManager()
455: .getProfileManager()
456: .getCopletInstanceData(
457: ci.getCopletId());
458: url = "coplet://" + ci.getCopletId();
459: Map attributes = new HashMap();
460: Iterator i = cid.getAttributes().entrySet()
461: .iterator();
462: while (i.hasNext()) {
463: Map.Entry entry = (Map.Entry) i.next();
464: attributes.put(entry.getKey(), entry
465: .getValue());
466: }
467: i = cid.getCopletData().getAttributes()
468: .entrySet().iterator();
469: while (i.hasNext()) {
470: Map.Entry entry = (Map.Entry) i.next();
471: attributes.put(entry.getKey(), entry
472: .getValue());
473: }
474: ci.setAttribute("coplet-attributes",
475: attributes);
476: } catch (ServiceException se) {
477: this .getLogger().warn(
478: "Unable to lookup portal service.",
479: se);
480: } finally {
481: this .manager.release(service);
482: }
483: }
484: source = resolver.resolveURI(url);
485: ci.setContent(IOUtils.toByteArray(source
486: .getInputStream()));
487: } catch (IOException se) {
488: this .getLogger().warn(
489: "Unable to get content for " + url, se);
490: } catch (ServiceException se) {
491: this .getLogger().warn(
492: "Unable to get source resolver.", se);
493: } finally {
494: if (source != null) {
495: resolver.release(source);
496: }
497: this .manager.release(resolver);
498: }
499: } else if (ci.getURL() == null) {
500: // copy coplet attributes
501: PortalService service = null;
502: try {
503: service = (PortalService) this .manager
504: .lookup(PortalService.ROLE);
505: CopletInstanceData cid = service
506: .getComponentManager().getProfileManager()
507: .getCopletInstanceData(ci.getCopletId());
508: Map attributes = new HashMap();
509: Iterator i = cid.getAttributes().entrySet()
510: .iterator();
511: while (i.hasNext()) {
512: Map.Entry entry = (Map.Entry) i.next();
513: attributes
514: .put(entry.getKey(), entry.getValue());
515: }
516: i = cid.getCopletData().getAttributes().entrySet()
517: .iterator();
518: while (i.hasNext()) {
519: Map.Entry entry = (Map.Entry) i.next();
520: attributes
521: .put(entry.getKey(), entry.getValue());
522: }
523: ci.setAttribute("coplet-attributes", attributes);
524: } catch (ServiceException se) {
525: this .getLogger().warn(
526: "Unable to lookup portal service.", se);
527: } finally {
528: this .manager.release(service);
529: }
530: }
531: store.addItem(ci);
532: } else {
533: store.addItem(item);
534: }
535: this .saveContentStore(store);
536: }
537:
538: /**
539: * Save the content store if it is a briefcase or a folder
540: */
541: protected void saveContentStore(ContentStore store) {
542: if (store instanceof Briefcase) {
543: this .saveContentStore(BRIEFCASE_KEY, store);
544: } else if (store instanceof Folder) {
545: this .saveContentStore(FOLDER_KEY, store);
546: }
547: }
548:
549: /**
550: * Load the content store for a single user
551: * @param type The type of the content store (briefcase or folder)
552: * @return The content store or null
553: */
554: protected ContentStore loadContentStore(String type, String userId) {
555: if (this .directory != null) {
556: final String suffix;
557: if (FOLDER_KEY.equals(type)) {
558: suffix = ".folder";
559: } else {
560: suffix = ".briefcase";
561: }
562: File file = new File(this .directory, userId + suffix);
563: if (file.exists()) {
564: try {
565: ObjectInputStream ois = new ObjectInputStream(
566: new FileInputStream(file));
567: ContentStore store = (ContentStore) ois
568: .readObject();
569: ois.close();
570: return store;
571: } catch (Exception ignore) {
572: // ignore this
573: }
574: }
575: }
576: return null;
577: }
578:
579: /**
580: * Load a content store
581: * @param type The type of the content store (briefcase or folder)
582: */
583: protected ContentStore loadContentStore(String type) {
584: ContentStore store = null;
585: String user = this .getUser();
586: if (user != null) {
587: store = this .loadContentStore(type, user);
588: }
589: if (store == null && user != null) {
590: try {
591: final String clazzName;
592: if (BRIEFCASE_KEY.equals(type)) {
593: clazzName = this .briefcaseClassName;
594: } else {
595: clazzName = this .folderClassName;
596: }
597:
598: final Class clazz = ClassUtils.loadClass(clazzName);
599: final Constructor constructor = clazz
600: .getConstructor(new Class[] { String.class });
601:
602: store = (ContentStore) constructor
603: .newInstance(new Object[] { user });
604: } catch (Exception ignore) {
605: if (BRIEFCASE_KEY.equals(type)) {
606: store = new Briefcase(user);
607: } else {
608: store = new Folder(user);
609: }
610: }
611: }
612: return store;
613: }
614:
615: /**
616: * Delete the content store for a user
617: */
618: protected void deleteContentStore(String type, String userId) {
619: final String suffix;
620: if (FOLDER_KEY.equals(type)) {
621: suffix = ".folder";
622: } else {
623: suffix = ".briefcase";
624: }
625: if (this .directory != null) {
626: File file = new File(this .directory, userId + suffix);
627: if (file.exists()) {
628: file.delete();
629: }
630: }
631: }
632:
633: /**
634: * Save the content store for a single user
635: */
636: protected void saveContentStore(String type, ContentStore store) {
637: final String userId = store.getId();
638: final String suffix;
639: if (FOLDER_KEY.equals(type)) {
640: suffix = ".folder";
641: } else {
642: suffix = ".briefcase";
643: }
644:
645: if (this .directory != null) {
646: File file = new File(this .directory, userId + suffix);
647: try {
648: if (!file.exists()) {
649: file.createNewFile();
650: file = new File(this .directory, userId + suffix);
651: }
652: ObjectOutputStream oos = new ObjectOutputStream(
653: new FileOutputStream(file));
654: oos.writeObject(store);
655: oos.close();
656: } catch (Exception ignore) {
657: // ignore this
658: }
659: }
660: }
661:
662: /**
663: * Get briefcases of all users
664: */
665: protected List loadBriefcases() {
666: if (this .directory != null) {
667: File directory = new File(this .directory);
668: if (directory.exists()) {
669: List briefcases = new ArrayList();
670: File[] files = directory.listFiles();
671: for (int i = 0; i < files.length; i++) {
672: String user = files[i].getName();
673: int pos = user.indexOf(".briefcase");
674: if (pos != -1) {
675: user = user.substring(0, pos);
676: ContentStore store = this .loadContentStore(
677: BRIEFCASE_KEY, user);
678: if (store != null) {
679: ContentStoreDescription bd = new ContentStoreDescription();
680: bd.id = user;
681: bd.size = store.contentSize();
682: briefcases.add(bd);
683: }
684: }
685: }
686: return briefcases;
687: }
688: }
689: return null;
690: }
691:
692: /* (non-Javadoc)
693: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBasket()
694: */
695: public Basket getBasket() {
696: Session session = ContextHelper.getRequest(this .context)
697: .getSession();
698: Basket basket = (Basket) session.getAttribute(BASKET_KEY);
699: if (basket == null) {
700: final String user = this .getUser();
701: try {
702: final Class clazz = ClassUtils
703: .loadClass(this .basketClassName);
704: final Constructor constructor = clazz
705: .getConstructor(new Class[] { String.class });
706:
707: basket = (Basket) constructor
708: .newInstance(new Object[] { user });
709: } catch (Exception ignore) {
710: basket = new Basket(user);
711: }
712: session.setAttribute(BASKET_KEY, basket);
713: }
714: return basket;
715: }
716:
717: /* (non-Javadoc)
718: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBriefcase()
719: */
720: public Briefcase getBriefcase() {
721: Session session = ContextHelper.getRequest(this .context)
722: .getSession();
723: Briefcase briefcase = (Briefcase) session
724: .getAttribute(BRIEFCASE_KEY);
725: if (briefcase == null) {
726: briefcase = (Briefcase) this
727: .loadContentStore(BRIEFCASE_KEY);
728: session.setAttribute(BRIEFCASE_KEY, briefcase);
729: }
730: return briefcase;
731: }
732:
733: public Folder getFolder() {
734: Session session = ContextHelper.getRequest(this .context)
735: .getSession();
736: Folder folder = (Folder) session.getAttribute(FOLDER_KEY);
737: if (folder == null) {
738: folder = (Folder) this .loadContentStore(FOLDER_KEY);
739: session.setAttribute(FOLDER_KEY, folder);
740: }
741: return folder;
742: }
743:
744: /* (non-Javadoc)
745: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBriefcaseDescriptions()
746: */
747: public List getBriefcaseDescriptions() {
748: Session session = ContextHelper.getRequest(this .context)
749: .getSession();
750: List briefcases = (List) session
751: .getAttribute(ALL_BRIEFCASES_KEY);
752: if (briefcases == null) {
753: briefcases = this .loadBriefcases();
754: if (briefcases == null) {
755: briefcases = new ArrayList();
756: }
757: session.setAttribute(ALL_BRIEFCASES_KEY, briefcases);
758: }
759: return briefcases;
760: }
761:
762: /**
763: * Get the current user
764: */
765: protected String getUser() {
766: PortalService service = null;
767: try {
768: service = (PortalService) this .manager
769: .lookup(PortalService.ROLE);
770: return service.getComponentManager().getProfileManager()
771: .getUser().getUserName();
772: } catch (ServiceException ignore) {
773: // ignore this
774: } finally {
775: this .manager.release(service);
776: }
777: return null;
778:
779: }
780:
781: /* (non-Javadoc)
782: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBasketActions()
783: */
784: public List getBasketActions() {
785: return this .basketActions;
786: }
787:
788: /* (non-Javadoc)
789: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBriefcaseActions()
790: */
791: public List getBriefcaseActions() {
792: return this .briefcaseActions;
793: }
794:
795: /* (non-Javadoc)
796: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#addBatch(org.apache.cocoon.portal.coplets.basket.ContentItem, int, org.apache.cocoon.portal.coplets.basket.BasketManager.ActionInfo)
797: */
798: public void addBatch(ContentItem item, int frequencyInDays,
799: ActionInfo action) {
800: final String name = action.name + "_" + item;
801:
802: final BatchInfo info = new BatchInfo();
803: info.item = item;
804: info.frequencyInSeconds = frequencyInDays * 60 * 60 * 24;
805: info.action = action;
806: if (frequencyInDays > 0) {
807: synchronized (this .batches) {
808: BatchInfo old = this .searchBatchInfo(item, action);
809: if (old != null) {
810: this .batches.remove(old);
811: this .scheduler.removeJob(name);
812: }
813: this .batches.add(info);
814: }
815: }
816: final Job job = new Job(action.url, item);
817:
818: try {
819: if (frequencyInDays > 0) {
820: this .scheduler.addPeriodicJob(name, job,
821: info.frequencyInSeconds, false, null, null);
822: } else {
823: this .scheduler.fireJob(job);
824: }
825:
826: } catch (Exception ignore) {
827: this .getLogger().warn(
828: "Exception during adding of new batch.", ignore);
829: }
830: }
831:
832: protected BatchInfo searchBatchInfo(ContentItem item,
833: ActionInfo info) {
834: final Iterator i = this .batches.iterator();
835: while (i.hasNext()) {
836: final BatchInfo current = (BatchInfo) i.next();
837: if (current.item.equals(item)) {
838: if (current.action.name.equals(info.name)) {
839: return current;
840: }
841: }
842: }
843: return null;
844: }
845:
846: protected static final class BatchInfo {
847: public ContentItem item;
848: public int frequencyInSeconds;
849: public ActionInfo action;
850: }
851:
852: /* (non-Javadoc)
853: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBasketAction(java.lang.String)
854: */
855: public ActionInfo getBasketAction(String name) {
856: final Iterator i = this .basketActions.iterator();
857: while (i.hasNext()) {
858: final ActionInfo current = (ActionInfo) i.next();
859: if (current.name.equals(name)) {
860: return current;
861: }
862: }
863: return null;
864: }
865:
866: /* (non-Javadoc)
867: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#getBriefcaseAction(java.lang.String)
868: */
869: public ActionInfo getBriefcaseAction(String name) {
870: final Iterator i = this .briefcaseActions.iterator();
871: while (i.hasNext()) {
872: final ActionInfo current = (ActionInfo) i.next();
873: if (current.name.equals(name)) {
874: return current;
875: }
876: }
877: return null;
878: }
879:
880: public static final class Job extends ServiceableCronJob implements
881: CronJob {
882:
883: protected final String url;
884:
885: public Job(String url, ContentItem item) {
886: final StringBuffer buffer = new StringBuffer(url);
887: boolean hasParams = url.indexOf('?') != -1;
888: Iterator i = item.attributes.entrySet().iterator();
889: while (i.hasNext()) {
890: final Map.Entry current = (Map.Entry) i.next();
891: final String key = current.getKey().toString();
892: if (!"coplet-attributes".equals(key)) {
893: if (hasParams) {
894: buffer.append('&');
895: } else {
896: buffer.append('?');
897: hasParams = true;
898: }
899: buffer.append(key);
900: buffer.append('=');
901: buffer.append(current.getValue().toString());
902: }
903: }
904: // now add coplet attributes
905: Map copletAttributes = (Map) item.attributes
906: .get("coplet-attributes");
907: if (copletAttributes != null) {
908: i = copletAttributes.entrySet().iterator();
909: while (i.hasNext()) {
910: final Map.Entry current = (Map.Entry) i.next();
911: final String key = current.getKey().toString();
912: if (hasParams) {
913: buffer.append('&');
914: } else {
915: buffer.append('?');
916: hasParams = true;
917: }
918: buffer.append(key);
919: buffer.append('=');
920: buffer.append(current.getValue().toString());
921: }
922: }
923: this .url = buffer.toString();
924: }
925:
926: /* (non-Javadoc)
927: * @see org.apache.cocoon.components.cron.CronJob#execute(java.lang.String)
928: */
929: public void execute(String jobname) {
930: SourceResolver resolver = null;
931: Source source = null;
932: try {
933: resolver = (SourceResolver) this .manager
934: .lookup(SourceResolver.ROLE);
935: source = resolver.resolveURI(this .url);
936:
937: InputStreamReader r = new InputStreamReader(source
938: .getInputStream());
939: try {
940: char[] b = new char[8192];
941:
942: while (r.read(b) > 0) {
943: // nothing to do
944: }
945:
946: } finally {
947: r.close();
948: }
949: } catch (Exception ignore) {
950: // we ignore all
951: this .getLogger().warn(
952: "Exception during execution of job " + jobname,
953: ignore);
954: } finally {
955: if (resolver != null) {
956: resolver.release(source);
957: this .manager.release(resolver);
958: }
959: }
960: }
961: }
962:
963: /* (non-Javadoc)
964: * @see org.apache.cocoon.portal.coplets.basket.BasketManager#update(org.apache.cocoon.portal.coplets.basket.ContentStore)
965: */
966: public void update(ContentStore store) {
967: this.saveContentStore(store);
968: }
969: }
|