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.acting;
018:
019: import java.io.IOException;
020: import java.util.ArrayList;
021: import java.util.Enumeration;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.apache.avalon.framework.configuration.Configuration;
028: import org.apache.avalon.framework.configuration.ConfigurationException;
029: import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
030: import org.apache.avalon.framework.parameters.ParameterException;
031: import org.apache.avalon.framework.parameters.Parameterizable;
032: import org.apache.avalon.framework.parameters.Parameters;
033: import org.apache.avalon.framework.service.ServiceException;
034: import org.apache.avalon.framework.thread.ThreadSafe;
035: import org.apache.cocoon.ProcessingException;
036: import org.apache.cocoon.acting.ServiceableAction;
037: import org.apache.cocoon.components.source.SourceUtil;
038: import org.apache.cocoon.environment.ObjectModelHelper;
039: import org.apache.cocoon.environment.Redirector;
040: import org.apache.cocoon.environment.Request;
041: import org.apache.cocoon.environment.Session;
042: import org.apache.cocoon.environment.SourceResolver;
043: import org.apache.cocoon.portal.PortalService;
044: import org.apache.cocoon.portal.acting.helpers.CopletMapping;
045: import org.apache.cocoon.portal.acting.helpers.FullScreenMapping;
046: import org.apache.cocoon.portal.acting.helpers.LayoutMapping;
047: import org.apache.cocoon.portal.acting.helpers.Mapping;
048: import org.apache.excalibur.source.Source;
049: import org.xml.sax.SAXException;
050:
051: /**
052: * This action helps you in creating bookmarks
053: *
054: * The definition file is:
055: * <bookmarks>
056: * <events>
057: * <event type="jxpath" id="ID">
058: * <targetid>tagetId</targetid>
059: * <targettype>layout|coplet</targettype>
060: * <path/>
061: * </event>
062: * <event type="fullscreen" id="ID">
063: * <targetid>copletId</targetid>
064: * <layoutid>layoutId</layoutid>
065: * </event>
066: * </events>
067: * </bookmarks>
068: *
069: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
070: * @version CVS $Id: BookmarkAction.java 433543 2006-08-22 06:22:54Z crossley $
071: */
072: public class BookmarkAction extends ServiceableAction implements
073: ThreadSafe, Parameterizable {
074:
075: protected Map eventMap = new HashMap();
076:
077: protected String historyParameterName;
078:
079: protected String configurationFile;
080:
081: /* (non-Javadoc)
082: * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters)
083: */
084: public void parameterize(Parameters parameters)
085: throws ParameterException {
086: this .historyParameterName = parameters.getParameter(
087: "history-parameter-name", "history");
088: this .configurationFile = parameters.getParameter("src", null);
089: if (this .configurationFile == null)
090: return;
091:
092: // The "lazy-load" parameter allows to defer loading of the config from "src" at
093: // the first call to act. This is for now undocumented until
094: // That was needed in the case of a dynamic source ("cocoon://blah") produced by the sitemap where
095: // the action is defined. Loading immediately in that case leads to an infinite loop where the sitemap
096: // is constantly reloaded.
097: if (!parameters.getParameterAsBoolean("lazy-load", false)) {
098: loadConfig();
099: }
100: }
101:
102: private void loadConfig() throws ParameterException {
103: Configuration config;
104: org.apache.excalibur.source.SourceResolver resolver = null;
105: try {
106: resolver = (org.apache.excalibur.source.SourceResolver) this .manager
107: .lookup(org.apache.excalibur.source.SourceResolver.ROLE);
108: Source source = null;
109: try {
110: source = resolver.resolveURI(configurationFile);
111: SAXConfigurationHandler handler = new SAXConfigurationHandler();
112: SourceUtil.toSAX(source, handler);
113: config = handler.getConfiguration();
114: } catch (ProcessingException se) {
115: throw new ParameterException(
116: "Unable to read configuration from "
117: + configurationFile, se);
118: } catch (SAXException se) {
119: throw new ParameterException(
120: "Unable to read configuration from "
121: + configurationFile, se);
122: } catch (IOException ioe) {
123: throw new ParameterException(
124: "Unable to read configuration from "
125: + configurationFile, ioe);
126: } finally {
127: resolver.release(source);
128: }
129: } catch (ServiceException se) {
130: throw new ParameterException(
131: "Unable to lookup source resolver.", se);
132: } finally {
133: this .manager.release(resolver);
134: }
135: Configuration[] events = config.getChild("events").getChildren(
136: "event");
137: if (events != null) {
138: for (int i = 0; i < events.length; i++) {
139: try {
140: final String type = events[i].getAttribute("type");
141: final String id = events[i].getAttribute("id");
142: if ("jxpath".equals(type)) {
143: if (this .eventMap.containsKey(id)) {
144: throw new ParameterException(
145: "The id for the event " + id
146: + " is not unique.");
147: }
148: final String targetType = events[i].getChild(
149: "targettype").getValue();
150: final String targetId = events[i].getChild(
151: "targetid").getValue();
152: final String path = events[i].getChild("path")
153: .getValue();
154: if ("layout".equals(targetType)) {
155: LayoutMapping mapping = new LayoutMapping();
156: mapping.layoutId = targetId;
157: mapping.path = path;
158: this .eventMap.put(id, mapping);
159: } else if ("coplet".equals(targetType)) {
160: CopletMapping mapping = new CopletMapping();
161: mapping.copletId = targetId;
162: mapping.path = path;
163: this .eventMap.put(id, mapping);
164: } else {
165: throw new ParameterException(
166: "Unknown target type " + targetType);
167: }
168: } else if ("fullscreen".equals(type)) {
169: if (this .eventMap.containsKey(id)) {
170: throw new ParameterException(
171: "The id for the event " + id
172: + " is not unique.");
173: }
174: final String targetId = events[i].getChild(
175: "targetid").getValue();
176: final String layoutId = events[i].getChild(
177: "layoutid").getValue();
178: FullScreenMapping mapping = new FullScreenMapping();
179: mapping.copletId = targetId;
180: mapping.layoutId = layoutId;
181: this .eventMap.put(id, mapping);
182: } else {
183: throw new ParameterException(
184: "Unknown event type for event " + id
185: + ": " + type);
186: }
187: } catch (ConfigurationException ce) {
188: throw new ParameterException(
189: "Configuration exception", ce);
190: }
191: }
192: }
193:
194: // Nullify config filename so as not to reload it.
195: this .configurationFile = null;
196: }
197:
198: public Map act(Redirector redirector, SourceResolver resolver,
199: Map objectModel, String source, Parameters par)
200: throws Exception {
201: if (this .getLogger().isDebugEnabled()) {
202: this .getLogger().debug(
203: "BEGIN act resolver=" + resolver + ", objectModel="
204: + objectModel + ", source=" + source
205: + ", par=" + par);
206: }
207:
208: if (this .configurationFile != null) {
209: loadConfig();
210: }
211:
212: Map result;
213: PortalService service = null;
214: try {
215: service = (PortalService) this .manager
216: .lookup(PortalService.ROLE);
217:
218: service.getComponentManager().getPortalManager().process();
219:
220: final Request request = ObjectModelHelper
221: .getRequest(objectModel);
222: final Session session = request.getSession(false);
223: final List events = new ArrayList();
224:
225: // is the history invoked?
226: final String historyValue = request
227: .getParameter(this .historyParameterName);
228: if (historyValue != null && session != null) {
229: // get the history
230: final List history = (List) session
231: .getAttribute("portal-history");
232: if (history != null) {
233: final int index = Integer.parseInt(historyValue);
234: final List state = (List) history.get(index);
235: if (state != null) {
236: final Iterator iter = state.iterator();
237: while (iter.hasNext()) {
238: Mapping m = (Mapping) iter.next();
239: events.add(m.getEvent(service, null));
240: }
241: while (history.size() > index) {
242: history.remove(history.size() - 1);
243: }
244: }
245: }
246: }
247: Enumeration enumeration = request.getParameterNames();
248: while (enumeration.hasMoreElements()) {
249: String name = (String) enumeration.nextElement();
250: String value = request.getParameter(name);
251:
252: Mapping m = (Mapping) this .eventMap.get(name);
253: if (m != null) {
254: events.add(m.getEvent(service, value));
255: }
256: }
257: String uri = service.getComponentManager().getLinkService()
258: .getLinkURI(events);
259: result = new HashMap();
260: result.put("uri", uri.substring(uri.indexOf('?') + 1));
261:
262: } catch (ServiceException ce) {
263: throw new ProcessingException(
264: "Unable to lookup portal service.", ce);
265: } finally {
266: this .manager.release(service);
267: }
268:
269: if (this .getLogger().isDebugEnabled()) {
270: this .getLogger().debug("END act map={}");
271: }
272:
273: return result;
274: }
275:
276: }
|