libreccm-legacy/ccm-cms/src/com/arsdigita/cms/publishToFile/LegacyInitializer.java.nolo...

405 lines
16 KiB
Plaintext
Executable File

/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.publishToFile;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.Template;
import com.arsdigita.initializer.Configuration;
import com.arsdigita.initializer.InitializationException;
import com.arsdigita.domain.DomainObject;
import com.arsdigita.domain.DomainObjectInstantiator;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.TransactionContext;
import com.arsdigita.persistence.metadata.MetadataRoot;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.runtime.CCMResourceManager;
import com.arsdigita.util.UncheckedWrapperException;
import org.apache.log4j.Logger;
import java.io.*;
// import java.io.File;
import java.util.List;
import java.util.Iterator;
/**
* Initializes the publish-to-file service. The configuration is described in
* the {@link com.arsdigita.cms.publishToFile} page.
*
* (pboy) ToDo: Adjusting the initialisation to the new configuration method
* without enterprise.init file.
*
* @author Jeff Teeters (teeters@arsdigita.com)
* @version $Revision: #24 $ $Date: 2004/08/17 $
*/
public class LegacyInitializer implements com.arsdigita.initializer.Initializer {
private static Logger s_log = Logger.getLogger(LegacyInitializer.class);
private final static String PUBLISH_DESTINATIONS = "destination";
private final static String PUBLISH_TO_FILE_LISTENER = "publishListener";
private final static String QUEUE_POLL_STARTUP_DELAY = "startupDelay";
private final static String QUEUE_POLL_DELAY = "pollDelay";
private final static String RETRY_DELAY = "retryDelay";
private final static String REQUEST_TIMEOUT = "requestTimeout";
private final static String BLOCK_SIZE = "blockSize";
private final static String BLOCK_SELECT_METHOD = "blockSelectMethod";
private final static String MAXIMUM_FAIL_COUNT = "maximumFailCount";
private Configuration m_conf = new Configuration();
public LegacyInitializer() throws InitializationException {
m_conf.initParameter(
PUBLISH_DESTINATIONS,
"List of publish destinations for content types" +
"Each element is a four-element list in the format " +
"'{ \"content type\", \"root directory\", \"shared storage\", " +
"\"url stub\" }'. " +
"Content type is the object type of the content type." +
"Root directory must be a path to a writable directory, relative" +
"to the webapp root. Shared storage must be true if the root " +
"directory is shared NFS storage, false otherwise. URL stub is " +
"must be the path component of the URL from which the live server " +
"will serve from this directory.",
List.class);
m_conf.initParameter(
PUBLISH_TO_FILE_LISTENER,
"Class which implements PublishToFileListener used to " +
"perform additional actions when publishing or unpublishing " +
"to the file system.",
String.class);
m_conf.initParameter(
QUEUE_POLL_STARTUP_DELAY,
"Time (in seconds) after system startup to wait before " +
"starting to monitor publishToFile queue. A value < 0 " +
"disables processing of the queue on this server.",
Integer.class, new Integer(30));
m_conf.initParameter(
QUEUE_POLL_DELAY,
"Time (in seconds) between checking if there are entries " +
"in the publishToFile queue. A value <= 0 disables processing " +
"the queue on this server.",
Integer.class, new Integer(1));
m_conf.initParameter(
RETRY_DELAY,
"Time to wait (seconds) before retrying to process a " +
"failed entry.",
Integer.class, new Integer(120));
m_conf.initParameter(
REQUEST_TIMEOUT,
"Time to wait (seconds) before aborting item request.",
Integer.class, new Integer(PublishToFile.DEFAULT_TIMEOUT));
m_conf.initParameter(
BLOCK_SIZE, "number of queue entries to process in one txn."
, Integer.class, new Integer(20));
m_conf.initParameter(
BLOCK_SELECT_METHOD,
"Method used to select entries for processing. " +
"'QueuedOrder'-in queued order. 'GroupByParent'-group " +
"entries according to parent when selecting items " +
"(allows optimizations if a listener task required for " +
"all elements in a folder can be done only once for the " +
"folder).",
String.class, "QueuedOrder");
m_conf.initParameter(
MAXIMUM_FAIL_COUNT,
"Maximum Fail Count for actions in Queue Manager. " +
"If Fail Count in Database is more than Specified " +
"Limit, Queue Manager will ignore the action. The " +
"Default Value -1 will ignore this parameter.",
Integer.class, new Integer(-1));
}
public Configuration getConfiguration() {
return m_conf;
}
public void startup() {
TransactionContext txn =
SessionManager.getSession().getTransactionContext();
txn.beginTxn();
setupPublishToFileSystem();
// QueueManager.requeueMissingFiles();
txn.commitTxn();
}
public void shutdown() {
QueueManager.stopWatchingQueue();
}
/**
* initialize source and destinations for publishing to the file system
*/
private void setupPublishToFileSystem() throws InitializationException {
DomainObjectInstantiator inst = new DomainObjectInstantiator() {
public DomainObject doNewInstance(DataObject dobj) {
return new PublishedFile(dobj);
}
};
DomainObjectFactory.registerInstantiator(
PublishedFile.BASE_DATA_OBJECT_TYPE,
inst);
// PublishToFileConfig ptfConf = PublishToFileConfig.getConfig();
// processDestination((List) m_conf.getParameter(PUBLISH_DESTINATIONS));
// processDestination((List) ptfConf.getPublishDestinations());
// setupQueueManager();
}
/**
* Prepare Queuemanager and start Queue processing.
*/
private void setupQueueManager(){
PublishToFileConfig ptfConf = PublishToFileConfig.getConfig();
// PublishToFile.setRequestTimeout(getInteger(REQUEST_TIMEOUT).intValue());
PublishToFile.setRequestTimeout(ptfConf.getRequestTimeout());
// QueueManager.setRetryDelay(getInteger(RETRY_DELAY));
QueueManager.setRetryDelay(ptfConf.getRetryDelay());
// QueueManager.setBlockSize(getInteger(BLOCK_SIZE));
QueueManager.setBlockSize(ptfConf.getBlockSize());
// QueueManager.setBlockSelectMethod(getString(BLOCK_SELECT_METHOD));
QueueManager.setBlockSelectMethod(ptfConf.getBlockSelectMethod());
// QueueManager.setMaximumFailCount(getInteger(MAXIMUM_FAIL_COUNT));
QueueManager.setMaximumFailCount(ptfConf.getMaximumFailCount());
// setup listener if specified
/* String listenerName = getString( PUBLISH_TO_FILE_LISTENER );
if (listenerName != null) {
PublishToFileListener listener = null;
Class listenerClass = null;
try {
listenerClass = Class.forName(listenerName);
} catch (ClassNotFoundException ex) {
invalidParam(PUBLISH_TO_FILE_LISTENER,
"could not find listener class " + listenerClass);
}
try {
listener = (PublishToFileListener)listenerClass.newInstance();
} catch (InstantiationException ex) {
invalidParam(PUBLISH_TO_FILE_LISTENER,
"could not find instantiate listener class " +
listenerClass + " (" + ex.getMessage() + ")");
} catch (IllegalAccessException ex) {
invalidParam(PUBLISH_TO_FILE_LISTENER,
"could not find instantiate listener class " +
listenerClass + " (" + ex.getMessage() + ")");
}
QueueManager.setListener(listener);
}
*/
// Just set the class implementing methods run when for publishing
// or unpublishing to file. No initialisation of the class here.
try {
QueueManager.setListener((PublishToFileListener)
ptfConf.getpublishListenerClass()
.newInstance());
} catch (InstantiationException ex) {
throw new UncheckedWrapperException
("Failed to instantiate the listener class", ex);
} catch (IllegalAccessException ex) {
throw new UncheckedWrapperException
("Couldn't access the listener class", ex);
}
// start thread for monitoring queue
// int startupDelay = getInteger(QUEUE_POLL_STARTUP_DELAY).intValue();
int startupDelay = ptfConf.getStartupDelay();
// int pollDelay = getInteger(QUEUE_POLL_DELAY).intValue();
int pollDelay = ptfConf.getPollDelay();
QueueManager.startWatchingQueue(startupDelay, pollDelay);
}
//
// Process publishing destinations
//
private static void processDestination(List dest)
throws InitializationException {
if (dest == null) {
invalidParam(PUBLISH_DESTINATIONS,
"publish destinations must not be null");
}
if (dest.size() < 1) {
invalidParam(PUBLISH_DESTINATIONS,
"publish destinations must contain at " +
"least one entry");
}
Iterator entries = dest.iterator();
while (entries.hasNext()) {
processDestinationEntry((List)entries.next());
}
}
private static void processDestinationEntry(List entry)
throws InitializationException {
if ( entry.size() != 4 ) {
invalidParam(PUBLISH_DESTINATIONS,
"publish destinations entry must contain " +
"four elements: '{ \n" +
" \"content type\",\n" +
" \"root directory\", \n" +
" \"is shared\", \n" +
" \"url stub\" \n" +
"};\n");
}
String contentType = (String)entry.get(0);
// destRoot is here relative to webapp root!
String destRoot = (String) entry.get(1);
Boolean sharedRoot = (Boolean) entry.get(2);
String destURL = (String) entry.get(3);
if ( contentType == null || contentType.trim().length() == 0) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination content type must not be null");
}
ObjectType type = MetadataRoot.getMetadataRoot().getObjectType(contentType);
if (type == null) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination content type cannot be found");
}
if (destRoot == null || destRoot.trim().length() == 0) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination root must not be null");
}
if (destRoot.endsWith("/")) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination root '" + destRoot +
"' must not end with a '/'");
}
// Does destRoot really now turns into an absolute fully pathname
destRoot = new File(CCMResourceManager.getBaseDirectory().getPath(),
destRoot).getPath();
s_log.info("Destination Root is set to : " + destRoot);
if (sharedRoot == null) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination shared flag must not be null");
}
if (destURL == null || "".equals(destURL.trim())) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination URL must not be null");
}
if (!destURL.startsWith("/")) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination URL '" + destURL +
"' must start with a '/'");
}
if (destURL.endsWith("/")) {
invalidParam(PUBLISH_DESTINATIONS,
"the destination URL '" + destURL +
"' must not end with a '/'");
}
DestinationStub dest = new DestinationStub(destRoot,
sharedRoot.booleanValue(),
destURL);
File file = dest.getFile();
if (!file.exists()) {
file.mkdirs();
s_log.info(file.getPath() + " created");
}
boolean writable = false;
FileWriter fl;
File fname = new File(file.getPath(),"placeholder.txt");
s_log.info("Try to create : " + destRoot);
try {
writable = file.canWrite() && file.isDirectory();
try {
fl = new FileWriter(fname.getPath());
fl.write("Location for the p2fs module to store static content. \n");
fl.close();
} catch ( IOException e ) {
// Will be reported as an initalization error
s_log.warn("Error creating file " + fname.getPath());
}
} catch ( SecurityException ex ) {
// Will be reported as an initalization error
}
if ( ! writable ) {
// HACK: Let's see if we can write to the config directory. If we can,
// then we're running as ccmadmin inside of ccm load, and there is no
// need to thrown an exception.
File conf = CCMResourceManager.getConfigDirectory();
if (conf.isDirectory() && conf.canWrite()) {
// we're ok
} else {
invalidParam(PUBLISH_DESTINATIONS, " the document root '" + file
+"' must be a writable directory");
}
}
if (Template.BASE_DATA_OBJECT_TYPE.equals(contentType) ||
!ContentSection.getConfig().getDisableItemPfs()) {
PublishToFile.addDestination(contentType,
dest);
}
}
private Integer getInteger(String paramName) {
return (Integer) m_conf.getParameter(paramName);
}
private String getString(String paramName) {
return (String) m_conf.getParameter(paramName);
}
private static void invalidParam(String param, String msg)
throws InitializationException {
throw new InitializationException(
"publishToFile: parameter " + param +": " + msg);
}
}