1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.portal.portlets.admin;
18
19
20 import org.apache.ecs.html.A;
21 import org.apache.ecs.html.Center;
22 import org.apache.ecs.html.Form;
23 import org.apache.ecs.html.Input;
24 import org.apache.ecs.html.Option;
25 import org.apache.ecs.html.P;
26 import org.apache.ecs.html.Select;
27 import org.apache.ecs.html.Table;
28 import org.apache.ecs.html.TextArea;
29 import org.apache.ecs.html.TD;
30 import org.apache.ecs.html.TR;
31 import org.apache.ecs.ConcreteElement;
32 import org.apache.ecs.ElementContainer;
33 import org.apache.ecs.StringElement;
34
35
36 import org.apache.jetspeed.portal.PortletException;
37 import org.apache.jetspeed.portal.portlets.AbstractPortlet;
38 import org.apache.jetspeed.cache.disk.DiskCacheEntry;
39 import org.apache.jetspeed.cache.disk.JetspeedDiskCache;
40 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
41 import org.apache.jetspeed.services.logging.JetspeedLogger;
42
43
44 import org.apache.jetspeed.xml.api.jcm.Content;
45 import org.apache.jetspeed.xml.api.jcm.Entry;
46 import org.apache.jetspeed.xml.api.jcm.Item;
47
48
49 import org.apache.turbine.util.ParameterParser;
50 import org.apache.turbine.util.DynamicURI;
51 import org.apache.turbine.util.RunData;
52 import org.apache.jetspeed.services.resources.JetspeedResources;
53
54
55 import java.io.Reader;
56 import java.io.Writer;
57 import java.util.Hashtable;
58 import java.util.Vector;
59
60 /***
61 Handles enumerating Portlets that are also applications
62
63 @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
64 @version $Id: JetspeedContentAdmin.java,v 1.28 2004/02/23 03:26:19 jford Exp $
65 */
66 public class JetspeedContentAdmin extends AbstractPortlet
67 {
68 /***
69 * Static initialization of the logger for this class
70 */
71 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedContentAdmin.class.getName());
72
73 /***
74 Used as the provider name key
75 */
76 public static final String PROVIDER_NAME_KEY = "provider-name";
77
78 public static final String POST_ARTICLE = "Post Article";
79
80 private Hashtable content = new Hashtable();
81
82 /***
83 Get the content for this JCP Admin
84 */
85 public ConcreteElement getContent( RunData rundata ) {
86
87 ParameterParser params = rundata.getParameters();
88
89 String provider = params.getString( PROVIDER_NAME_KEY );
90
91 if ( provider == null ) {
92 return this.getProviders( rundata );
93 } else if ( params.getString( POST_ARTICLE ) != null ) {
94
95 params.remove( PROVIDER_NAME_KEY );
96 params.remove( POST_ARTICLE );
97 return this.postArticle( provider, rundata );
98 } else {
99
100 params.remove( PROVIDER_NAME_KEY );
101 return this.getForm( provider, rundata );
102 }
103
104 }
105
106 /***
107 */
108 public String getURL( String provider ) {
109
110 return JetspeedResources.getString( "content.provider." + provider + ".url" );
111
112 }
113
114 /***
115 */
116 public synchronized ConcreteElement postArticle( String provider, RunData rundata ) {
117 ElementContainer ec = new ElementContainer();
118
119 ParameterParser params = rundata.getParameters();
120
121 String topic = params.getString( "topic", "" );
122 String title = params.getString( "title", "" );
123 String link = params.getString( "link", "" );
124 String description = params.getString( "description", "" );
125
126
127 Item item = new Item();
128 item.setTopic( topic );
129 item.setTitle( title );
130 item.setLink( link );
131 item.setDescription( description );
132
133
134 Content content = null;
135 try {
136 content = this.getContentMarkup( this.getURL( provider ) ).getContent();
137
138
139
140 Vector v = new Vector();
141
142 Item[] items = content.getChannel().getItem();
143
144 for ( int i = 0; i < items.length; ++i ) {
145 v.addElement( items[i] );
146 }
147
148 v.insertElementAt( item, 0 );
149
150
151
152 Item[] newItems = new Item[ v.size() ];
153 v.copyInto( newItems );
154
155 content.getChannel().removeAllItem();
156
157
158 for ( int i = 0; i < newItems.length; ++i ) {
159 content.getChannel().addItem( newItems[i] );
160 }
161
162
163
164
165 this.getContentMarkup( this.getURL( provider ) ).save();
166
167 } catch ( Throwable t ) {
168 logger.error("Throwable", t);
169 return new StringElement( "Can't use this provider: " + t.getMessage() );
170 }
171
172 ec.addElement( "Your article '" + title + "' has been posted within '" + topic + "'" );
173
174 return ec;
175 }
176
177 /***
178 Get a list of providers an provide a form for them.
179 */
180 public ConcreteElement getProviders( RunData rundata ) {
181
182 ElementContainer root = new ElementContainer();
183
184 root.addElement( new P().addElement( "Select a content provider: " ) );
185
186 Vector v = JetspeedResources.getVector( JetspeedResources.CONTENT_PROVIDER_LIST_KEY );
187
188 for ( int i = 0; i < v.size(); ++i ) {
189
190 String provider = (String)v.elementAt( i );
191
192 String title = JetspeedResources.getString( "content.provider." + provider + ".title" );
193
194 DynamicURI uri = new DynamicURI( rundata );
195 uri.addQueryData( rundata.getParameters() );
196 uri.addQueryData( PROVIDER_NAME_KEY, provider );
197
198 P row = new P().addElement( new A( uri.toString() ).addElement( title ) )
199 .addElement( " ( " )
200 .addElement( new A( this.getBookmarklet( provider, rundata ) ).addElement( "Bookmarklet" ) )
201 .addElement( " ) " );
202
203 root.addElement( row );
204
205
206 }
207
208 return root;
209
210 }
211
212
213 /***
214 Return a form that refresh the feed daemon
215
216 @param provider The provider that you want to publish content to.
217 */
218 private ConcreteElement getForm( String provider, RunData rundata ) {
219
220 DynamicURI duri = new DynamicURI( rundata );
221
222 Form form = new Form().setAction( duri.toString() );
223
224 Table table = new Table().setBorder(0);
225 form.addElement( table );
226
227
228 ParameterParser params = rundata.getParameters();
229
230
231 String topic = params.getString( "topic", "" );
232 String title = params.getString( "title", "" );
233 String link = params.getString( "link", "" );
234 String description = params.getString( "description", "" );
235
236
237
238
239 Content content = null;
240 try {
241 content = this.getContentMarkup( this.getURL( provider ) ).getContent();
242 } catch ( Exception e ) {
243 logger.error("Exception", e);
244 return new StringElement( "Can't use this provider: " + e.getMessage() );
245 }
246
247 Select select = new Select();
248 select.setName( "topic" );
249
250
251 Entry[] topics = content.getChannel().getTopics().getEntry();
252
253
254 for ( int i = 0; i < topics.length; ++i ) {
255 String name = topics[i].getName();
256 select.addElement( new Option( name ).addElement( name ) );
257 }
258
259
260
261 table.addElement( getRow( "Topic: ", select ) );
262
263 table.addElement( getRow( "Title: ", new Input().setType("text")
264 .setName("title")
265 .setValue( title ) ) );
266
267 table.addElement( getRow( "Link: ", new Input().setType("text")
268 .setName("link")
269 .setValue( link ) ) );
270
271 table.addElement( new TR().addElement( new TD().setColSpan(2)
272 .addElement( new TextArea().setName("description")
273 .setCols( 65 )
274 .setRows( 15 )
275 .addElement( description ) ) ) );
276
277 form.addElement( new Input().setType( "hidden" )
278 .setName( PROVIDER_NAME_KEY )
279 .setValue( provider ) );
280
281 form.addElement( new Input().setType( "submit" )
282 .setName( POST_ARTICLE )
283 .setValue( POST_ARTICLE ) );
284
285 return new Center( form );
286
287 }
288
289 /***
290 Get a row for adding it to a table.
291 */
292 private TR getRow( String title, ConcreteElement ce ) {
293
294 int TITLE_WIDTH = 30;
295
296 TR tr = new TR().addElement( new TD().setWidth( TITLE_WIDTH )
297 .addElement( title ) )
298 .addElement( new TD().addElement( ce ) );
299 return tr;
300
301 }
302
303 /***
304 Get the jetspeed content from disk.
305 */
306 public ContentMarkup getContentMarkup( String url ) throws Exception {
307
308 ContentMarkup cm = (ContentMarkup)this.content.get( url );
309
310 if ( cm == null ) {
311
312 cm = new ContentMarkup( url );
313 this.content.put( url, cm );
314
315 }
316
317 return cm;
318
319 }
320
321 /***
322 Init this
323 */
324 public void init() throws PortletException {
325 this.setTitle("Jetspeed Content");
326 this.setDescription("Publish Jetspeed Content.");
327 }
328
329 /***
330 Get the content of a bookmarklet for the given provider.
331 */
332 private String getBookmarklet( String provider, RunData rundata ) {
333
334 ParameterParser params = rundata.getParameters();
335
336 StringBuffer buff = new StringBuffer();
337
338
339
340 buff.append( "JavaScript:" );
341 buff.append( "top.location = '" +
342 rundata.getServerScheme() +
343 "://" +
344 rundata.getServerName() +
345 (rundata.getServerPort() != 80 ? ":" +
346 rundata.getServerPort() : "") +
347 rundata.getScriptName() +
348 "?select-panel=JetspeedContentAdmin" );
349 buff.append( "&provider-name=" + provider );
350 buff.append( "&title=' + escape( document.title ) + '&link=' + escape( top.location );" );
351
352
353 return buff.toString();
354 }
355
356
357
358 /***
359 */
360 public boolean getAllowEdit( RunData rundata ) {
361 return false;
362 }
363
364 /***
365 */
366 public boolean getAllowMaximize( RunData rundata ) {
367 return false;
368 }
369
370
371 }
372
373
374 /***
375 Class for abstracting Jetspeed content markup parsing. Handles updating the
376 content if it has been modified on disk.
377
378 @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
379 @version $Id: JetspeedContentAdmin.java,v 1.28 2004/02/23 03:26:19 jford Exp $
380 */
381 class ContentMarkup {
382
383 /***
384 The last modified date of this URL,
385 */
386 private long lastModified;
387
388 /***
389 The Castor generated API.
390 */
391 private Content content = null;
392
393 /***
394 The URL on which the JCM is based.
395 */
396 private String url = null;
397
398 /***
399 Create a ContentMarkup and point it to the URL you want.
400 */
401 public ContentMarkup( String url ) throws Exception {
402 System.err.println("Content Markup url => " + url );
403 this.url = url;
404
405 this.lastModified = JetspeedDiskCache.getInstance().getEntry( this.url ).getLastModified();
406
407
408 this.parse();
409
410 }
411
412 /***
413 Get the Castor generated content for this ContentMarkup
414 */
415 public Content getContent() throws Exception {
416
417 long recent = JetspeedDiskCache.getInstance().getEntry( this.url ).getLastModified();
418
419 if ( recent == 0 || this.lastModified < recent ) {
420 this.parse();
421 }
422
423 return this.content;
424 }
425
426 /***
427 Save this JCM (hopefully updated JCM) to disk.
428 */
429 public synchronized void save() throws Exception {
430
431 DiskCacheEntry pde = JetspeedDiskCache.getInstance()
432 .getEntry( this.url );
433 Writer filewriter = pde.getWriter();
434 this.content.marshal( filewriter );
435 filewriter.close();
436
437 }
438
439 /***
440 Parse out the JCM and store it in memory
441 */
442 public synchronized void parse() throws Exception {
443
444 Reader stream = JetspeedDiskCache.getInstance()
445 .getEntry( this.url ).getReader();
446 this.content = Content.unmarshal( stream );
447 stream.close();
448
449 }
450
451 }