/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Jetspeed" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache" or
* "Apache Jetspeed", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.jetspeed.portal.portlets.admin;
//Element Construction Set
import org.apache.ecs.html.A;
import org.apache.ecs.html.Center;
import org.apache.ecs.html.Form;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.Option;
import org.apache.ecs.html.P;
import org.apache.ecs.html.Select;
import org.apache.ecs.html.Table;
import org.apache.ecs.html.TextArea;
import org.apache.ecs.html.TD;
import org.apache.ecs.html.TR;
import org.apache.ecs.ConcreteElement;
import org.apache.ecs.ElementContainer;
import org.apache.ecs.StringElement;
//Jetspeed stuff
import org.apache.jetspeed.portal.PortletException;
import org.apache.jetspeed.portal.portlets.AbstractPortlet;
import org.apache.jetspeed.cache.disk.DiskCacheEntry;
import org.apache.jetspeed.cache.disk.JetspeedDiskCache;
//Jetspeed Content Markup support
import org.apache.jetspeed.xml.api.jcm.Content;
import org.apache.jetspeed.xml.api.jcm.Entry;
import org.apache.jetspeed.xml.api.jcm.Item;
//turbine
import org.apache.turbine.util.Log;
import org.apache.turbine.util.ParameterParser;
import org.apache.turbine.util.DynamicURI;
import org.apache.turbine.util.RunData;
import org.apache.jetspeed.services.resources.JetspeedResources;
//standard java stuff
import java.io.Reader;
import java.io.Writer;
import java.util.Hashtable;
import java.util.Vector;
/**
Handles enumerating Portlets that are also applications
@author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
@version $Id: JetspeedContentAdmin.java,v 1.25 2001/12/30 17:00:18 paulsp Exp $
*/
public class JetspeedContentAdmin extends AbstractPortlet {
/**
Used as the provider name key
*/
public static final String PROVIDER_NAME_KEY = "provider-name";
public static final String POST_ARTICLE = "Post Article";
private Hashtable content = new Hashtable();
/**
Get the content for this JCP Admin
*/
public ConcreteElement getContent( RunData rundata ) {
ParameterParser params = rundata.getParameters();
String provider = params.getString( PROVIDER_NAME_KEY );
if ( provider == null ) {
return this.getProviders( rundata );
} else if ( params.getString( POST_ARTICLE ) != null ) {
//post the article if the user has hit the submit button.
params.remove( PROVIDER_NAME_KEY );
params.remove( POST_ARTICLE );
return this.postArticle( provider, rundata );
} else {
//get the form if a provider is specified.
params.remove( PROVIDER_NAME_KEY );
return this.getForm( provider, rundata );
}
}
/**
*/
public String getURL( String provider ) {
return JetspeedResources.getString( "content.provider." + provider + ".url" );
}
/**
*/
public synchronized ConcreteElement postArticle( String provider, RunData rundata ) {
ElementContainer ec = new ElementContainer();
ParameterParser params = rundata.getParameters();
String topic = params.getString( "topic", "" );
String title = params.getString( "title", "" );
String link = params.getString( "link", "" );
String description = params.getString( "description", "" );
//create the JCM item
Item item = new Item();
item.setTopic( topic );
item.setTitle( title );
item.setLink( link );
item.setDescription( description );
Content content = null;
try {
content = this.getContentMarkup( this.getURL( provider ) ).getContent();
//BEGIN reorg of the item list so that the new entry begins at the top
Vector v = new Vector();
Item[] items = content.getChannel().getItem();
for ( int i = 0; i < items.length; ++i ) {
v.addElement( items[i] );
}
v.insertElementAt( item, 0 );
//now build this into a new array
Item[] newItems = new Item[ v.size() ];
v.copyInto( newItems );
content.getChannel().removeAllItem();
//now go through all the new items and add those
for ( int i = 0; i < newItems.length; ++i ) {
content.getChannel().addItem( newItems[i] );
}
//END reorg of the item list so that the new entry begins at the top
//save the portlet markup after you have made the changes.
this.getContentMarkup( this.getURL( provider ) ).save();
} catch ( Throwable t ) {
Log.error( t );
return new StringElement( "Can't use this provider: " + t.getMessage() );
}
ec.addElement( "Your article '" + title + "' has been posted within '" + topic + "'" );
return ec;
}
/**
Get a list of providers an provide a form for them.
*/
public ConcreteElement getProviders( RunData rundata ) {
ElementContainer root = new ElementContainer();
root.addElement( new P().addElement( "Select a content provider: " ) );
Vector v = JetspeedResources.getVector( JetspeedResources.CONTENT_PROVIDER_LIST_KEY );
for ( int i = 0; i < v.size(); ++i ) {
String provider = (String)v.elementAt( i );
String title = JetspeedResources.getString( "content.provider." + provider + ".title" );
DynamicURI uri = new DynamicURI( rundata );
uri.addQueryData( rundata.getParameters() );
uri.addQueryData( PROVIDER_NAME_KEY, provider );
P row = new P().addElement( new A( uri.toString() ).addElement( title ) )
.addElement( " ( " )
.addElement( new A( this.getBookmarklet( provider, rundata ) ).addElement( "Bookmarklet" ) )
.addElement( " ) " );
root.addElement( row );
}
return root;
}
/**
Return a form that refresh the feed daemon
@param provider The provider that you want to publish content to.
*/
private ConcreteElement getForm( String provider, RunData rundata ) {
DynamicURI duri = new DynamicURI( rundata );
Form form = new Form().setAction( duri.toString() );
Table table = new Table().setBorder(0);
form.addElement( table );
ParameterParser params = rundata.getParameters();
//get the default values if they were specified as params
String topic = params.getString( "topic", "" );
String title = params.getString( "title", "" );
String link = params.getString( "link", "" );
String description = params.getString( "description", "" );
//build a select box for adding topics to.
Content content = null;
try {
content = this.getContentMarkup( this.getURL( provider ) ).getContent();
} catch ( Exception e ) {
Log.error( e );
return new StringElement( "Can't use this provider: " + e.getMessage() );
}
Select select = new Select();
select.setName( "topic" );
//entry topics
Entry[] topics = content.getChannel().getTopics().getEntry();
//populate the select box
for ( int i = 0; i < topics.length; ++i ) {
String name = topics[i].getName();
select.addElement( new Option( name ).addElement( name ) );
}
//fix me... this needs to be a SELECT box
table.addElement( getRow( "Topic: ", select ) );
table.addElement( getRow( "Title: ", new Input().setType("text")
.setName("title")
.setValue( title ) ) );
table.addElement( getRow( "Link: ", new Input().setType("text")
.setName("link")
.setValue( link ) ) );
table.addElement( new TR().addElement( new TD().setColSpan(2)
.addElement( new TextArea().setName("description")
.setCols( 65 )
.setRows( 15 )
.addElement( description ) ) ) );
form.addElement( new Input().setType( "hidden" )
.setName( PROVIDER_NAME_KEY )
.setValue( provider ) );
form.addElement( new Input().setType( "submit" )
.setName( POST_ARTICLE )
.setValue( POST_ARTICLE ) );
return new Center( form );
}
/**
Get a row for adding it to a table.
*/
private TR getRow( String title, ConcreteElement ce ) {
int TITLE_WIDTH = 30;
TR tr = new TR().addElement( new TD().setWidth( TITLE_WIDTH )
.addElement( title ) )
.addElement( new TD().addElement( ce ) );
return tr;
}
/**
Get the jetspeed content from disk.
*/
public ContentMarkup getContentMarkup( String url ) throws Exception {
ContentMarkup cm = (ContentMarkup)this.content.get( url );
if ( cm == null ) {
cm = new ContentMarkup( url );
this.content.put( url, cm );
}
return cm;
}
/**
Init this
*/
public void init() throws PortletException {
this.setTitle("Jetspeed Content");
this.setDescription("Publish Jetspeed Content.");
}
/**
Get the content of a bookmarklet for the given provider.
*/
private String getBookmarklet( String provider, RunData rundata ) {
ParameterParser params = rundata.getParameters();
StringBuffer buff = new StringBuffer();
//create the JavaScript entry
buff.append( "JavaScript:" );
buff.append( "top.location = '" +
rundata.getServerScheme() +
"://" +
rundata.getServerName() +
(rundata.getServerPort() != 80 ? ":" +
rundata.getServerPort() : "") +
rundata.getScriptName() +
"select-panel=JetspeedContentAdmin" );
buff.append( "&provider-name=" + provider );
buff.append( "&title=' + escape( document.title ) + '&link=' + escape( top.location );" );
return buff.toString();
}
//required options so that this portlet looks like an admin portlet...
/**
*/
public boolean getAllowEdit( RunData rundata ) {
return false;
}
/**
*/
public boolean getAllowMaximize( RunData rundata ) {
return false;
}
}
/**
Class for abstracting Jetspeed content markup parsing. Handles updating the
content if it has been modified on disk.
@author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
@version $Id: JetspeedContentAdmin.java,v 1.25 2001/12/30 17:00:18 paulsp Exp $
*/
class ContentMarkup {
/**
The last modified date of this URL,
*/
private long lastModified;
/**
The Castor generated API.
*/
private Content content = null;
/**
The URL on which the JCM is based.
*/
private String url = null;
/**
Create a ContentMarkup and point it to the URL you want.
*/
public ContentMarkup( String url ) throws Exception {
System.err.println("Content Markup url => " + url );
this.url = url;
this.lastModified = JetspeedDiskCache.getInstance().getEntry( this.url ).getLastModified();
//now parse out this URL so that is now in memory
this.parse();
}
/**
Get the Castor generated content for this ContentMarkup
*/
public Content getContent() throws Exception {
long recent = JetspeedDiskCache.getInstance().getEntry( this.url ).getLastModified();
if ( recent == 0 || this.lastModified < recent ) {
this.parse();
}
return this.content;
}
/**
Save this JCM (hopefully updated JCM) to disk.
*/
public synchronized void save() throws Exception {
DiskCacheEntry pde = JetspeedDiskCache.getInstance()
.getEntry( this.url );
Writer filewriter = pde.getWriter();
this.content.marshal( filewriter );
filewriter.close();
}
/**
Parse out the JCM and store it in memory
*/
public synchronized void parse() throws Exception {
Reader stream = JetspeedDiskCache.getInstance()
.getEntry( this.url ).getReader();
this.content = Content.unmarshal( stream );
stream.close();
}
}