KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > portal > coplet > adapter > impl > AbstractCopletAdapter


1 /*
2  * Copyright 1999-2002,2004-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.portal.coplet.adapter.impl;
17
18 import java.util.Iterator JavaDoc;
19 import java.util.Map JavaDoc;
20
21 import org.apache.avalon.framework.logger.AbstractLogEnabled;
22 import org.apache.avalon.framework.service.ServiceException;
23 import org.apache.avalon.framework.service.ServiceManager;
24 import org.apache.avalon.framework.service.Serviceable;
25 import org.apache.avalon.framework.thread.ThreadSafe;
26 import org.apache.cocoon.components.thread.RunnableManager;
27 import org.apache.cocoon.environment.CocoonRunnable;
28 import org.apache.cocoon.portal.coplet.CopletData;
29 import org.apache.cocoon.portal.coplet.CopletInstanceData;
30 import org.apache.cocoon.portal.coplet.adapter.CopletAdapter;
31 import org.apache.cocoon.xml.SaxBuffer;
32 import org.apache.cocoon.xml.XMLUtils;
33 import org.xml.sax.ContentHandler JavaDoc;
34 import org.xml.sax.SAXException JavaDoc;
35 import EDU.oswego.cs.dl.util.concurrent.CountDown;
36
37 /**
38  * This is the abstract base adapter to use pipelines as coplets
39  *
40  * <h2>Configuration</h2>
41  * <table><tbody>
42  * <tr>
43  * <th>buffer</th>
44  * <td>Shall the content of the coplet be buffered? If a coplet is
45  * buffered, errors local to the coplet are caught and a not
46  * availability notice is delivered instead. Buffering does not
47  * cache responses for subsequent requests.</td>
48  * <td></td>
49  * <td>boolean</td>
50  * <td><code>false</code></td>
51  * </tr>
52  * <tr>
53  * <th>timeout</th>
54  * <td>Max time in seconds content delivery may take. After a timeout,
55  * a not availability notice is delivered. Setting a timeout automatically
56  * turns on buffering.</td>
57  * <td></td>
58  * <td>int</td>
59  * <td><code>null</code></td>
60  * </tr>
61  * </tbody></table>
62  *
63  * @author <a HREF="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
64  * @author <a HREF="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
65  *
66  * @version CVS $Id: AbstractCopletAdapter.java 232769 2005-08-15 07:51:18Z cziegeler $
67  */

68 public abstract class AbstractCopletAdapter
69     extends AbstractLogEnabled
70     implements CopletAdapter, ThreadSafe, Serviceable {
71     
72     /** The service manager */
73     protected ServiceManager manager;
74
75     /* (non-Javadoc)
76      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
77      */

78     public void service(ServiceManager manager) throws ServiceException {
79         this.manager = manager;
80     }
81
82     /**
83      * Get a configuration value
84      * First the coplet data is queried and if it doesn't provide an
85      * attribute with the given name, the coplet base data is used.
86      */

87     protected Object JavaDoc getConfiguration(CopletInstanceData coplet, String JavaDoc key) {
88         CopletData copletData = coplet.getCopletData();
89         Object JavaDoc data = copletData.getAttribute( key );
90         if ( data == null) {
91             data = copletData.getCopletBaseData().getCopletConfig().get( key );
92         }
93         return data;
94     }
95     
96     /**
97      * Get a configuration value
98      * First the coplet data is queried and if it doesn't provide an
99      * attribute with the given name, the coplet base data is used.
100      * If no value is found the default value is returned.
101      */

102     protected Object JavaDoc getConfiguration(CopletInstanceData coplet,
103                                       String JavaDoc key,
104                                       Object JavaDoc defaultValue) {
105         Object JavaDoc data = this.getConfiguration(coplet, key);
106         if ( data == null ) {
107             data = defaultValue;
108         }
109         return data;
110     }
111
112     /**
113      * Implement this and not toSAX()
114      */

115     public abstract void streamContent(CopletInstanceData coplet,
116                                          ContentHandler JavaDoc contentHandler)
117     throws SAXException JavaDoc;
118     
119     /**
120      * This method streams the content of a coplet instance data.
121      * It handles buffering and timeout setting and calls
122      * {@link #streamContent(CopletInstanceData, ContentHandler)}
123      * for creating the content.
124      *
125      * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#toSAX(org.apache.cocoon.portal.coplet.CopletInstanceData, org.xml.sax.ContentHandler)
126      */

127     public void toSAX(CopletInstanceData coplet, ContentHandler JavaDoc contentHandler)
128     throws SAXException JavaDoc {
129         final long startTime = System.currentTimeMillis();
130         Boolean JavaDoc bool = (Boolean JavaDoc) this.getConfiguration( coplet, "buffer" );
131         Integer JavaDoc timeout = (Integer JavaDoc) this.getConfiguration( coplet, "timeout");
132         if ( timeout != null ) {
133             // if timeout is set we have to buffer!
134
bool = Boolean.TRUE;
135         }
136         
137         if ( bool != null && bool.booleanValue() ) {
138             boolean read = false;
139             SaxBuffer buffer = new SaxBuffer();
140             Exception JavaDoc error = null;
141             try {
142                 
143                 if ( timeout != null ) {
144                     final int milli = timeout.intValue() * 1000;
145                     LoaderThread loader = new LoaderThread(this, coplet, buffer);
146                     final RunnableManager runnableManager = (RunnableManager)this.manager.lookup( RunnableManager.ROLE );
147                     try {
148                         runnableManager.execute( new CocoonRunnable(loader) );
149                     } finally {
150                         this.manager.release( runnableManager );
151                     }
152                     try {
153                         read = loader.join( milli );
154                     } catch (InterruptedException JavaDoc ignore) {
155                         // ignored
156
}
157                     error = loader.exception;
158                     if ( error != null && this.getLogger().isWarnEnabled() ) {
159                         this.getLogger().warn("Unable to get content of coplet: " + coplet.getId(), error);
160                     }
161                 } else {
162                     this.streamContent( coplet, buffer );
163                     read = true;
164                 }
165             } catch (Exception JavaDoc exception ) {
166                 error = exception;
167                 this.getLogger().warn("Unable to get content of coplet: " + coplet.getId(), exception);
168             }
169             
170             if ( read ) {
171                 buffer.toSAX( contentHandler );
172             } else {
173                 if ( !this.renderErrorContent(coplet, contentHandler, error)) {
174                     // FIXME - get correct error message
175
contentHandler.startDocument();
176                     XMLUtils.startElement( contentHandler, "p");
177                     XMLUtils.data( contentHandler, "The coplet " + coplet.getId() + " is currently not available.");
178                     XMLUtils.endElement(contentHandler, "p");
179                     contentHandler.endDocument();
180                 }
181             }
182         } else {
183             this.streamContent( coplet, contentHandler );
184         }
185         if ( this.getLogger().isInfoEnabled() ) {
186             final long msecs = System.currentTimeMillis() - startTime;
187             this.getLogger().info("Streamed coplet " + coplet.getCopletData().getId() +
188                                   " (instance " + coplet.getId() + ") in " + msecs + "ms.");
189         }
190     }
191     
192     /* (non-Javadoc)
193      * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#init(org.apache.cocoon.portal.coplet.CopletInstanceData)
194      */

195     public void init(CopletInstanceData coplet) {
196         // nothing to do here, can be overwritten in subclasses
197
}
198     
199     /* (non-Javadoc)
200      * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#destroy(org.apache.cocoon.portal.coplet.CopletInstanceData)
201      */

202     public void destroy(CopletInstanceData coplet) {
203         // nothing to do here, can be overwritten in subclasses
204
}
205
206     /* (non-Javadoc)
207      * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#login(org.apache.cocoon.portal.coplet.CopletInstanceData)
208      */

209     public void login(CopletInstanceData coplet) {
210         // copy temporary attributes from the coplet data
211
Iterator JavaDoc iter = coplet.getCopletData().getAttributes().entrySet().iterator();
212         while ( iter.hasNext() ) {
213             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iter.next();
214             if ( entry.getKey().toString().startsWith("temporary:") ) {
215                 coplet.setTemporaryAttribute(entry.getKey().toString().substring(10),
216                         entry.getValue());
217             }
218         }
219     }
220         
221     /* (non-Javadoc)
222      * @see org.apache.cocoon.portal.coplet.adapter.CopletAdapter#logout(org.apache.cocoon.portal.coplet.CopletInstanceData)
223      */

224     public void logout(CopletInstanceData coplet) {
225         // nothing to do here, can be overwritten in subclasses
226
}
227     
228     /**
229      * Render the error content for a coplet
230      * @param coplet The coplet instance data
231      * @param handler The content handler
232      * @param error The exception that occured
233      * @return True if the error content has been rendered, otherwise false
234      * @throws SAXException
235      */

236     protected boolean renderErrorContent(CopletInstanceData coplet,
237                                          ContentHandler JavaDoc handler,
238                                          Exception JavaDoc error)
239     throws SAXException JavaDoc {
240         return false;
241     }
242 }
243
244 final class LoaderThread implements Runnable JavaDoc {
245     
246     private final AbstractCopletAdapter adapter;
247     private final ContentHandler JavaDoc handler;
248     private final CopletInstanceData coplet;
249     private final CountDown finished;
250     Exception JavaDoc exception;
251
252     public LoaderThread(AbstractCopletAdapter adapter,
253                          CopletInstanceData coplet,
254                          ContentHandler JavaDoc handler) {
255         this.adapter = adapter;
256         this.coplet = coplet;
257         this.handler = handler;
258         this.finished = new CountDown( 1 );
259     }
260     
261     public void run() {
262         try {
263             adapter.streamContent( this.coplet, this.handler );
264         } catch (Exception JavaDoc local) {
265             this.exception = local;
266         } finally {
267             this.finished.release();
268         }
269     }
270     
271     boolean join( final long milis )
272     throws InterruptedException JavaDoc {
273         return this.finished.attempt( milis );
274     }
275     
276 }
277
Popular Tags