blob: b960c5c5532abdbfbbaac4ad1e05971275d183ad [file] [log] [blame]
/*
* 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;
}
}