/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.plugin.outputs;
import org.apache.commons.lang.exception.NestableRuntimeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.api.engine.IContentListener;
import org.pentaho.platform.api.repository.IContentItem;
import org.pentaho.platform.engine.core.output.BufferedContentItem;
import org.pentaho.platform.engine.services.outputhandler.BaseOutputHandler;
import org.pentaho.platform.plugin.services.messages.Messages;
import org.pentaho.platform.util.logging.Logger;
import org.pentaho.platform.util.messages.LocaleHelper;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;
import javax.jcr.lock.LockException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import java.io.InputStream;
import java.util.Calendar;
import java.util.StringTokenizer;
public abstract class JcrCmsOutputHandler extends BaseOutputHandler {
public abstract Repository getRepository();
private static final Log logger = LogFactory.getLog( JcrCmsOutputHandler.class );
public abstract Session getJcrSession( Repository repository );
@Override
public IContentItem getFileOutputContentItem() {
String contentName = getContentRef();
try {
Repository repository = getRepository();
if ( repository == null ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0001_GETTING_CMSREPO" ) ); //$NON-NLS-1$
return null;
}
Session jcrSession = getJcrSession( repository );
if ( jcrSession == null ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0002_GETTING_SESSION" ) ); //$NON-NLS-1$
return null;
}
// Use the root node as a starting point
Node root = jcrSession.getRootNode();
if ( root == null ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0003_GETTING_ROOT" ) ); //$NON-NLS-1$
return null;
}
Node node = root;
// parse the path
StringTokenizer tokenizer = new StringTokenizer( contentName, "/" ); //$NON-NLS-1$
int levels = tokenizer.countTokens();
for ( int idx = 0; idx < levels - 1; idx++ ) {
String folder = tokenizer.nextToken();
if ( !node.hasNode( folder ) ) {
// Create an unstructured node under which to import the XML
node = node.addNode( folder, "nt:folder" ); //$NON-NLS-1$
} else {
node = node.getNodes( folder ).nextNode();
}
}
// we should be at the right level now
String fileName = tokenizer.nextToken();
Node fileNode = null;
Node contentNode = null;
Version version = null;
if ( node.hasNode( fileName ) ) {
fileNode = node.getNode( fileName );
contentNode = fileNode.getNode( "jcr:content" ); //$NON-NLS-1$
if ( contentNode.isLocked() ) {
JcrCmsOutputHandler.logger.warn( Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0004_NODE_LOCKED", contentName ) ); //$NON-NLS-1$
return null;
}
if ( contentNode.isCheckedOut() ) {
JcrCmsOutputHandler.logger.warn( Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0005_NODE_CHECKED_OUT", contentName ) ); //$NON-NLS-1$
return null;
}
contentNode.checkout();
VersionHistory history = contentNode.getVersionHistory();
VersionIterator iterator = history.getAllVersions();
while ( iterator.hasNext() ) {
version = iterator.nextVersion();
JcrCmsOutputHandler.logger.trace( version.getPath()
+ "," + version.getName() + "," + version.getIndex() + "," + version.getCreated().toString() ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
} else {
fileNode = node.addNode( fileName, "nt:file" ); //$NON-NLS-1$
fileNode.addMixin( "mix:versionable" ); //$NON-NLS-1$
// create the mandatory child node - jcr:content
contentNode = fileNode.addNode( "jcr:content", "nt:resource" ); //$NON-NLS-1$ //$NON-NLS-2$
contentNode.addMixin( "mix:versionable" ); //$NON-NLS-1$
contentNode.addMixin( "mix:filename" ); //$NON-NLS-1$
contentNode.setProperty( "jcr:mimeType", getMimeType() ); //$NON-NLS-1$
contentNode.setProperty( "jcr:name", fileName ); //$NON-NLS-1$
contentNode.setProperty( "jcr:encoding", LocaleHelper.getSystemEncoding() ); //$NON-NLS-1$
}
CmsContentListener listener = new CmsContentListener( contentNode, jcrSession );
BufferedContentItem contentItem = new BufferedContentItem( listener );
listener.setContentItem( contentItem );
if ( false ) { // Disable faked search for now
search( "test", jcrSession ); //$NON-NLS-1$
}
return contentItem;
} catch ( LockException le ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0006_GETTING_OUTPUTHANDLER" ) + contentName, le ); //$NON-NLS-1$
} catch ( NestableRuntimeException nre ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0006_GETTING_OUTPUTHANDLER" ) + contentName, nre ); //$NON-NLS-1$
} catch ( RepositoryException re ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0006_GETTING_OUTPUTHANDLER" ) + contentName, re ); //$NON-NLS-1$
}
return null;
}
private void search( final String searchStr, final Session session ) {
try {
Workspace workspace = session.getWorkspace();
QueryManager queryManager = workspace.getQueryManager();
Query query = queryManager.createQuery( "//*[jcr:contains(., '" + searchStr + "')]", Query.XPATH ); //$NON-NLS-1$ //$NON-NLS-2$
QueryResult result = query.execute();
NodeIterator it = result.getNodes();
while ( it.hasNext() ) {
Node n = it.nextNode();
JcrCmsOutputHandler.logger.trace( n.getName() );
if ( n.getName().equals( "jcr:content" ) ) { //$NON-NLS-1$
if ( n.getProperty( "jcr:mimeType" ) != null ) { //$NON-NLS-1$
JcrCmsOutputHandler.logger.trace( "jcr:mimeType=" + n.getProperty( "jcr:mimeType" ).getString() );
//$NON-NLS-1$ //$NON-NLS-2$
}
}
}
} catch ( InvalidQueryException iqe ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0008_SEARCH_FAILED" ), iqe ); //$NON-NLS-1$
} catch ( RepositoryException re ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0008_SEARCH_FAILED" ), re ); //$NON-NLS-1$
}
}
private class CmsContentListener implements IContentListener {
private Node node;
private Session session;
private BufferedContentItem contentItem;
public CmsContentListener() {
}
public CmsContentListener( final Node node, final Session session ) {
this.node = node;
this.session = session;
}
public void close() {
try {
InputStream inputStream = contentItem.getInputStream();
node.setProperty( "jcr:data", inputStream ); //$NON-NLS-1$
Calendar lastModified = Calendar.getInstance();
node.setProperty( "jcr:lastModified", lastModified ); //$NON-NLS-1$
session.save();
node.checkin();
session.save();
} catch ( LockException le ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0007_SAVING_CONTENT" ), le ); //$NON-NLS-1$
} catch ( RepositoryException re ) {
Logger.error( JcrCmsOutputHandler.class.getName(), Messages.getInstance().getString(
"JcrCmsOutputHandler.ERROR_0007_SAVING_CONTENT" ), re ); //$NON-NLS-1$
}
}
public void setNode( final Node node ) {
this.node = node;
}
public void setSession( final Session session ) {
this.session = session;
}
public void setContentItem( final BufferedContentItem contentItem ) {
this.contentItem = contentItem;
}
public void setMimeType( final String mimeType ) {
}
public void setName( final String Name ) {
}
}
}