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