| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.cocoon.portal.acting; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.configuration.Configuration; |
| import org.apache.avalon.framework.configuration.ConfigurationException; |
| import org.apache.avalon.framework.configuration.SAXConfigurationHandler; |
| import org.apache.avalon.framework.parameters.ParameterException; |
| import org.apache.avalon.framework.parameters.Parameterizable; |
| import org.apache.avalon.framework.parameters.Parameters; |
| import org.apache.avalon.framework.service.ServiceException; |
| import org.apache.avalon.framework.thread.ThreadSafe; |
| import org.apache.cocoon.ProcessingException; |
| import org.apache.cocoon.acting.ServiceableAction; |
| import org.apache.cocoon.components.source.SourceUtil; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.Redirector; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.environment.Session; |
| import org.apache.cocoon.environment.SourceResolver; |
| import org.apache.cocoon.portal.PortalService; |
| import org.apache.cocoon.portal.acting.helpers.CopletMapping; |
| import org.apache.cocoon.portal.acting.helpers.FullScreenMapping; |
| import org.apache.cocoon.portal.acting.helpers.LayoutMapping; |
| import org.apache.cocoon.portal.acting.helpers.Mapping; |
| import org.apache.excalibur.source.Source; |
| import org.apache.excalibur.source.SourceValidity; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * This action helps you in creating bookmarks |
| * |
| * The definition file is: |
| * <bookmarks> |
| * <events> |
| * <event type="jxpath" id="ID"> |
| * <targetid>tagetId</targetid> |
| * <targettype>layout|coplet</targettype> |
| * <path/> |
| * </event> |
| * <event type="fullscreen" id="ID"> |
| * <targetid>copletId</targetid> |
| * <layoutid>layoutId</layoutid> |
| * </event> |
| * </events> |
| * </bookmarks> |
| * |
| * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a> |
| * @version CVS $Id$ |
| */ |
| public class BookmarkAction |
| extends ServiceableAction |
| implements ThreadSafe, Parameterizable { |
| |
| protected Map eventMap = new HashMap(); |
| |
| protected String historyParameterName; |
| |
| protected String configurationFile; |
| |
| protected SourceValidity oldValidity; |
| |
| protected boolean reloadCheck = true; |
| |
| /** |
| * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters) |
| */ |
| public void parameterize(Parameters parameters) throws ParameterException { |
| this.historyParameterName = parameters.getParameter("history-parameter-name", "history"); |
| this.reloadCheck = parameters.getParameterAsBoolean("check-reload", this.reloadCheck); |
| this.configurationFile = parameters.getParameter("src", null); |
| if ( this.configurationFile == null ) return; |
| |
| // The "lazy-load" parameter allows to defer loading of the config from "src" at |
| // the first call to act. This is for now undocumented until |
| // That was needed in the case of a dynamic source ("cocoon://blah") produced by the sitemap where |
| // the action is defined. Loading immediately in that case leads to an infinite loop where the sitemap |
| // is constantly reloaded. |
| if (!parameters.getParameterAsBoolean("lazy-load", false)) { |
| loadConfig(); |
| } |
| } |
| |
| private void loadConfig() throws ParameterException { |
| Configuration config; |
| org.apache.excalibur.source.SourceResolver resolver = null; |
| Source source = null; |
| try { |
| try { |
| resolver = (org.apache.excalibur.source.SourceResolver) this.manager.lookup(org.apache.excalibur.source.SourceResolver.ROLE); |
| source = resolver.resolveURI(configurationFile); |
| } catch (IOException ioe) { |
| throw new ParameterException("Unable to read configuration from " + configurationFile, ioe); |
| } catch (ServiceException se) { |
| throw new ParameterException("Unable to lookup source resolver.", se); |
| } |
| SourceValidity newValidity = source.getValidity(); |
| if ( this.oldValidity == null |
| || this.oldValidity.isValid() == SourceValidity.INVALID |
| || this.oldValidity.isValid(newValidity) == SourceValidity.INVALID) { |
| this.oldValidity = newValidity; |
| try { |
| SAXConfigurationHandler handler = new SAXConfigurationHandler(); |
| SourceUtil.toSAX(source, handler); |
| config = handler.getConfiguration(); |
| } catch (ProcessingException se) { |
| throw new ParameterException("Unable to read configuration from " + configurationFile, se); |
| } catch (SAXException se) { |
| throw new ParameterException("Unable to read configuration from " + configurationFile, se); |
| } catch (IOException ioe) { |
| throw new ParameterException("Unable to read configuration from " + configurationFile, ioe); |
| } |
| Configuration[] events = config.getChild("events").getChildren("event"); |
| |
| if ( events != null ) { |
| for(int i=0; i<events.length;i++) { |
| try { |
| final String type = events[i].getAttribute("type"); |
| final String id = events[i].getAttribute("id"); |
| if ( "jxpath".equals(type) ) { |
| if ( this.eventMap.containsKey(id)) { |
| throw new ParameterException("The id for the event " + id + " is not unique."); |
| } |
| final String targetType = events[i].getChild("targettype").getValue(); |
| final String targetId = events[i].getChild("targetid").getValue(); |
| final String path = events[i].getChild("path").getValue(); |
| if ( "layout".equals(targetType) ) { |
| LayoutMapping mapping = new LayoutMapping(); |
| mapping.layoutId = targetId; |
| mapping.path = path; |
| this.eventMap.put(id, mapping); |
| } else if ( "coplet".equals(targetType) ) { |
| CopletMapping mapping = new CopletMapping(); |
| mapping.copletId = targetId; |
| mapping.path = path; |
| this.eventMap.put(id, mapping); |
| } else { |
| throw new ParameterException("Unknown target type " + targetType); |
| } |
| } else if ( "fullscreen".equals(type) ) { |
| if ( this.eventMap.containsKey(id)) { |
| throw new ParameterException("The id for the event " + id + " is not unique."); |
| } |
| final String targetId = events[i].getChild("targetid").getValue(); |
| final String layoutId = events[i].getChild("layoutid").getValue(); |
| FullScreenMapping mapping = new FullScreenMapping(); |
| mapping.copletId = targetId; |
| mapping.layoutId = layoutId; |
| this.eventMap.put(id, mapping); |
| } else { |
| throw new ParameterException("Unknown event type for event " + id + ": " + type); |
| } |
| } catch (ConfigurationException ce) { |
| throw new ParameterException("Configuration exception" ,ce); |
| } |
| } |
| } |
| } |
| } finally { |
| if (resolver != null) { |
| resolver.release(source); |
| } |
| if (resolver != null) { |
| this.manager.release(resolver); |
| } |
| } |
| if ( !this.reloadCheck ) { |
| this.configurationFile = null; |
| } |
| } |
| |
| /** |
| * @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) |
| */ |
| public Map act(Redirector redirector, |
| SourceResolver resolver, |
| Map objectModel, |
| String source, |
| Parameters par) |
| throws Exception { |
| if (this.getLogger().isDebugEnabled() ) { |
| this.getLogger().debug("BEGIN act resolver="+resolver+ |
| ", objectModel="+objectModel+ |
| ", source="+source+ |
| ", par="+par); |
| } |
| |
| if (this.configurationFile != null) { |
| this.loadConfig(); |
| } |
| |
| Map result; |
| PortalService service = null; |
| try { |
| service = (PortalService)this.manager.lookup(PortalService.ROLE); |
| |
| service.getComponentManager().getPortalManager().process(); |
| |
| final Request request = ObjectModelHelper.getRequest(objectModel); |
| final Session session = request.getSession(false); |
| final List events = new ArrayList(); |
| |
| // is the history invoked? |
| final String historyValue = request.getParameter(this.historyParameterName); |
| if ( historyValue != null && session != null) { |
| // get the history |
| final List history = (List)session.getAttribute("portal-history"); |
| if ( history != null ) { |
| final int index = Integer.parseInt(historyValue); |
| final List state = (List)history.get(index); |
| if ( state != null ) { |
| final Iterator iter = state.iterator(); |
| while ( iter.hasNext() ) { |
| Mapping m = (Mapping)iter.next(); |
| events.add(m.getEvent(service, null)); |
| } |
| while (history.size() > index ) { |
| history.remove(history.size()-1); |
| } |
| } |
| } |
| } |
| Enumeration enumeration = request.getParameterNames(); |
| while (enumeration.hasMoreElements()) { |
| String name = (String)enumeration.nextElement(); |
| String value = request.getParameter(name); |
| |
| Mapping m = (Mapping) this.eventMap.get(name); |
| if ( m != null ) { |
| events.add(m.getEvent(service, value)); |
| } |
| } |
| String uri = service.getComponentManager().getLinkService().getLinkURI(events); |
| result = new HashMap(); |
| result.put("uri", uri.substring(uri.indexOf('?')+1)); |
| |
| } catch (ServiceException ce) { |
| throw new ProcessingException("Unable to lookup portal service.", ce); |
| } finally { |
| this.manager.release(service); |
| } |
| |
| if (this.getLogger().isDebugEnabled() ) { |
| this.getLogger().debug("END act map={}"); |
| } |
| |
| return result; |
| } |
| |
| } |