| /* |
| * 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.coplet.adapter.impl; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.util.Enumeration; |
| import java.util.Map; |
| |
| import org.apache.avalon.framework.service.ServiceException; |
| import org.apache.cocoon.ProcessingException; |
| import org.apache.cocoon.components.ContextHelper; |
| import org.apache.cocoon.environment.ObjectModelHelper; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.portal.coplet.CopletData; |
| import org.apache.cocoon.portal.coplet.CopletFactory; |
| import org.apache.cocoon.portal.coplet.CopletInstanceData; |
| import org.apache.cocoon.portal.event.CopletInstanceEvent; |
| import org.apache.cocoon.portal.event.impl.CopletLinkEvent; |
| import org.apache.cocoon.portal.layout.CompositeLayout; |
| import org.apache.cocoon.portal.layout.Item; |
| import org.apache.cocoon.portal.layout.LayoutFactory; |
| import org.apache.cocoon.portal.layout.NamedItem; |
| import org.apache.cocoon.portal.layout.impl.CopletLayout; |
| import org.apache.cocoon.portal.profile.ProfileManager; |
| import org.apache.cocoon.portal.transformation.ProxyTransformer; |
| import org.apache.cocoon.util.NetUtils; |
| import org.apache.cocoon.xml.XMLUtils; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * This coplet adapter is used to connect to external applications that are |
| * plugged into the portal. |
| * |
| * @author <a href="mailto:gerald.kahrer@rizit.at">Gerald Kahrer</a> |
| * |
| * @version CVS $Id$ |
| */ |
| public class ApplicationCopletAdapter extends CachingURICopletAdapter { |
| |
| /** |
| * @see org.apache.cocoon.portal.coplet.adapter.impl.URICopletAdapter#streamContent(org.apache.cocoon.portal.coplet.CopletInstanceData, java.lang.String, org.xml.sax.ContentHandler) |
| */ |
| public void streamContent(final CopletInstanceData coplet, |
| final String uri, |
| final ContentHandler contentHandler) |
| throws SAXException { |
| try { |
| super.streamContent(coplet, uri, contentHandler); |
| } catch (SAXException se) { |
| this.getLogger().error( |
| "ApplicationCopletAdapter: Exception while getting coplet resource", |
| se); |
| |
| this.renderErrorContent(coplet, contentHandler); |
| } |
| } |
| |
| /** |
| * This adapter listens for CopletLinkEvents. If it catches one the link uri is saved in |
| * the coplet instance data for further handling in the ProxyTransformer. |
| * There is a special CopletLinkEvent with the uri "createNewCopletInstance", which is the |
| * trigger to create a new instance of the one that is the target of the event. |
| */ |
| public void handleCopletInstanceEvent(CopletInstanceEvent e) { |
| super.handleCopletInstanceEvent(e); |
| |
| if ( e instanceof CopletLinkEvent ) { |
| CopletLinkEvent event = (CopletLinkEvent) e; |
| CopletInstanceData coplet = (CopletInstanceData) event.getTarget(); |
| String link = event.getLink(); |
| |
| if ("createNewCopletInstance".equals(link)) { |
| try { |
| createNewInstance(coplet); |
| } catch (ProcessingException ex) { |
| getLogger().error("Could not create new coplet instance", ex); |
| } |
| } else { |
| // this is a normal link event, so save the url in the instance data |
| // for ProxyTransformer |
| String linkValue = event.getLink(); |
| Boolean addParams = (Boolean)this.getConfiguration(coplet, "appendParameters", Boolean.FALSE); |
| if ( addParams.booleanValue() ) { |
| final StringBuffer uri = new StringBuffer(event.getLink()); |
| boolean hasParams = (uri.toString().indexOf("?") != -1); |
| |
| // append parameters - if any |
| final Map objectModel = ContextHelper.getObjectModel(this.context); |
| final Request r = ObjectModelHelper.getRequest(objectModel); |
| final Enumeration params = r.getParameterNames(); |
| while (params.hasMoreElements()) { |
| final String name = (String)params.nextElement(); |
| if (!name.startsWith("cocoon-portal-")) { |
| final String[] values = r.getParameterValues(name); |
| for(int i = 0; i < values.length; i++) { |
| if ( hasParams ) { |
| uri.append('&'); |
| } else { |
| uri.append('?'); |
| hasParams = true; |
| } |
| uri.append(name); |
| uri.append('='); |
| try { |
| uri.append(NetUtils.decode(values[i], "utf-8")); |
| } catch (UnsupportedEncodingException uee) { |
| // ignore this |
| } |
| } |
| } |
| } |
| linkValue = uri.toString(); |
| } |
| coplet.setTemporaryAttribute(ProxyTransformer.LINK, linkValue); |
| } |
| } |
| } |
| |
| /** |
| * Creates a new instance of the given coplet. Also a new named item in the tab layout is |
| * created to show the data of the new coplet instance in the portal. |
| * @param coplet the coplet instance data |
| * @trows ProcessingException if something fails in the creation process |
| */ |
| private void createNewInstance(CopletInstanceData coplet) |
| throws ProcessingException { |
| ProfileManager profileManager = null; |
| try { |
| profileManager = |
| (ProfileManager) this.manager.lookup(ProfileManager.ROLE); |
| |
| CopletData copletData = coplet.getCopletData(); |
| |
| LayoutFactory lfac = |
| (LayoutFactory) this.manager.lookup(LayoutFactory.ROLE); |
| |
| CopletLayout copletLayout = |
| (CopletLayout) lfac.newInstance("coplet"); |
| |
| CopletFactory cfac = |
| (CopletFactory) manager.lookup(CopletFactory.ROLE); |
| |
| CopletInstanceData newCoplet = cfac.newInstance(copletData); |
| |
| copletLayout.setCopletInstanceData(newCoplet); |
| profileManager.register(copletLayout); |
| |
| NamedItem newItem = new NamedItem(); |
| newItem.setLayout(copletLayout); |
| |
| CompositeLayout tabLayout = |
| (CompositeLayout) profileManager.getPortalLayout( |
| "portalApplications", null); |
| |
| newItem.setName(getNewInstanceTabName(tabLayout)); |
| tabLayout.addItem(newItem); |
| } catch (ServiceException ce) { |
| throw new ProcessingException( |
| "Unable to lookup profile manager.", |
| ce); |
| } catch (Exception e) { |
| throw new ProcessingException(e); |
| } finally { |
| this.manager.release(profileManager); |
| } |
| } |
| |
| /** |
| * Returns the name of the new named item in the tab layout |
| * @return String the name of the new item |
| */ |
| private String getNewInstanceTabName(CompositeLayout layout) { |
| Integer data = (Integer) layout.getAspectData("tab"); |
| Item selectedItem = layout.getItem(data.intValue()); |
| |
| if (selectedItem instanceof NamedItem) { |
| return ((NamedItem) selectedItem).getName(); |
| } |
| return ("New"); |
| } |
| |
| /** |
| * Render the error content for a coplet |
| * @param coplet |
| * @param handler |
| * @return True if the error content has been rendered, otherwise false |
| * @throws SAXException |
| */ |
| protected boolean renderErrorContent(CopletInstanceData coplet, |
| ContentHandler handler) |
| throws SAXException { |
| handler.startDocument(); |
| XMLUtils.startElement(handler, "p"); |
| XMLUtils.data( |
| handler, |
| "ApplicationCopletAdapter: Can't get content for coplet " |
| + coplet.getId() |
| + ". Look up the logs."); |
| XMLUtils.endElement(handler, "p"); |
| handler.endDocument(); |
| |
| return true; |
| } |
| |
| } |