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.coplet.adapter.impl;
018:
019: import java.io.UnsupportedEncodingException;
020: import java.util.Enumeration;
021: import java.util.Map;
022:
023: import org.apache.avalon.framework.service.ServiceException;
024: import org.apache.cocoon.ProcessingException;
025: import org.apache.cocoon.components.ContextHelper;
026: import org.apache.cocoon.environment.ObjectModelHelper;
027: import org.apache.cocoon.environment.Request;
028: import org.apache.cocoon.portal.coplet.CopletData;
029: import org.apache.cocoon.portal.coplet.CopletFactory;
030: import org.apache.cocoon.portal.coplet.CopletInstanceData;
031: import org.apache.cocoon.portal.event.CopletInstanceEvent;
032: import org.apache.cocoon.portal.event.impl.CopletLinkEvent;
033: import org.apache.cocoon.portal.layout.CompositeLayout;
034: import org.apache.cocoon.portal.layout.Item;
035: import org.apache.cocoon.portal.layout.LayoutFactory;
036: import org.apache.cocoon.portal.layout.NamedItem;
037: import org.apache.cocoon.portal.layout.impl.CopletLayout;
038: import org.apache.cocoon.portal.profile.ProfileManager;
039: import org.apache.cocoon.portal.transformation.ProxyTransformer;
040: import org.apache.cocoon.util.NetUtils;
041: import org.apache.cocoon.xml.XMLUtils;
042: import org.xml.sax.ContentHandler;
043: import org.xml.sax.SAXException;
044:
045: /**
046: * This coplet adapter is used to connect to external applications that are
047: * plugged into the portal.
048: *
049: * @author <a href="mailto:gerald.kahrer@rizit.at">Gerald Kahrer</a>
050: *
051: * @version CVS $Id: ApplicationCopletAdapter.java 433543 2006-08-22 06:22:54Z crossley $
052: */
053: public class ApplicationCopletAdapter extends CachingURICopletAdapter {
054:
055: /**
056: * @see org.apache.cocoon.portal.coplet.adapter.impl.URICopletAdapter#streamContent(org.apache.cocoon.portal.coplet.CopletInstanceData, java.lang.String, org.xml.sax.ContentHandler)
057: */
058: public void streamContent(final CopletInstanceData coplet,
059: final String uri, final ContentHandler contentHandler)
060: throws SAXException {
061: try {
062: super .streamContent(coplet, uri, contentHandler);
063: } catch (SAXException se) {
064: this
065: .getLogger()
066: .error(
067: "ApplicationCopletAdapter: Exception while getting coplet resource",
068: se);
069:
070: this .renderErrorContent(coplet, contentHandler);
071: }
072: }
073:
074: /**
075: * This adapter listens for CopletLinkEvents. If it catches one the link uri is saved in
076: * the coplet instance data for further handling in the ProxyTransformer.
077: * There is a special CopletLinkEvent with the uri "createNewCopletInstance", which is the
078: * trigger to create a new instance of the one that is the target of the event.
079: */
080: public void handleCopletInstanceEvent(CopletInstanceEvent e) {
081: super .handleCopletInstanceEvent(e);
082:
083: if (e instanceof CopletLinkEvent) {
084: CopletLinkEvent event = (CopletLinkEvent) e;
085: CopletInstanceData coplet = (CopletInstanceData) event
086: .getTarget();
087: String link = event.getLink();
088:
089: if ("createNewCopletInstance".equals(link)) {
090: try {
091: createNewInstance(coplet);
092: } catch (ProcessingException ex) {
093: getLogger().error(
094: "Could not create new coplet instance", ex);
095: }
096: } else {
097: // this is a normal link event, so save the url in the instance data
098: // for ProxyTransformer
099: String linkValue = event.getLink();
100: Boolean addParams = (Boolean) this .getConfiguration(
101: coplet, "appendParameters", Boolean.FALSE);
102: if (addParams.booleanValue()) {
103: final StringBuffer uri = new StringBuffer(event
104: .getLink());
105: boolean hasParams = (uri.toString().indexOf("?") != -1);
106:
107: // append parameters - if any
108: final Map objectModel = ContextHelper
109: .getObjectModel(this .context);
110: final Request r = ObjectModelHelper
111: .getRequest(objectModel);
112: final Enumeration params = r.getParameterNames();
113: while (params.hasMoreElements()) {
114: final String name = (String) params
115: .nextElement();
116: if (!name.startsWith("cocoon-portal-")) {
117: final String[] values = r
118: .getParameterValues(name);
119: for (int i = 0; i < values.length; i++) {
120: if (hasParams) {
121: uri.append('&');
122: } else {
123: uri.append('?');
124: hasParams = true;
125: }
126: uri.append(name);
127: uri.append('=');
128: try {
129: uri.append(NetUtils.decode(
130: values[i], "utf-8"));
131: } catch (UnsupportedEncodingException uee) {
132: // ignore this
133: }
134: }
135: }
136: }
137: linkValue = uri.toString();
138: }
139: coplet.setTemporaryAttribute(ProxyTransformer.LINK,
140: linkValue);
141: }
142: }
143: }
144:
145: /**
146: * Creates a new instance of the given coplet. Also a new named item in the tab layout is
147: * created to show the data of the new coplet instance in the portal.
148: * @param coplet the coplet instance data
149: * @trows ProcessingException if something fails in the creation process
150: */
151: private void createNewInstance(CopletInstanceData coplet)
152: throws ProcessingException {
153: ProfileManager profileManager = null;
154: try {
155: profileManager = (ProfileManager) this .manager
156: .lookup(ProfileManager.ROLE);
157:
158: CopletData copletData = coplet.getCopletData();
159:
160: LayoutFactory lfac = (LayoutFactory) this .manager
161: .lookup(LayoutFactory.ROLE);
162:
163: CopletLayout copletLayout = (CopletLayout) lfac
164: .newInstance("coplet");
165:
166: CopletFactory cfac = (CopletFactory) manager
167: .lookup(CopletFactory.ROLE);
168:
169: CopletInstanceData newCoplet = cfac.newInstance(copletData);
170:
171: copletLayout.setCopletInstanceData(newCoplet);
172: profileManager.register(copletLayout);
173:
174: NamedItem newItem = new NamedItem();
175: newItem.setLayout(copletLayout);
176:
177: CompositeLayout tabLayout = (CompositeLayout) profileManager
178: .getPortalLayout("portalApplications", null);
179:
180: newItem.setName(getNewInstanceTabName(tabLayout));
181: tabLayout.addItem(newItem);
182: } catch (ServiceException ce) {
183: throw new ProcessingException(
184: "Unable to lookup profile manager.", ce);
185: } catch (Exception e) {
186: throw new ProcessingException(e);
187: } finally {
188: this .manager.release(profileManager);
189: }
190: }
191:
192: /**
193: * Returns the name of the new named item in the tab layout
194: * @return String the name of the new item
195: */
196: private String getNewInstanceTabName(CompositeLayout layout) {
197: Integer data = (Integer) layout.getAspectData("tab");
198: Item selectedItem = layout.getItem(data.intValue());
199:
200: if (selectedItem instanceof NamedItem) {
201: return ((NamedItem) selectedItem).getName();
202: }
203: return ("New");
204: }
205:
206: /**
207: * Render the error content for a coplet
208: * @param coplet
209: * @param handler
210: * @return True if the error content has been rendered, otherwise false
211: * @throws SAXException
212: */
213: protected boolean renderErrorContent(CopletInstanceData coplet,
214: ContentHandler handler) throws SAXException {
215: handler.startDocument();
216: XMLUtils.startElement(handler, "p");
217: XMLUtils.data(handler,
218: "ApplicationCopletAdapter: Can't get content for coplet "
219: + coplet.getId() + ". Look up the logs.");
220: XMLUtils.endElement(handler, "p");
221: handler.endDocument();
222:
223: return true;
224: }
225:
226: }
|