Merged DEV/3.1_ENTERPRISE_ONLY to HEAD

12465: Supporting changes for enterprise-only monitoring code.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12495 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2008-12-18 15:26:23 +00:00
parent d20db6284c
commit 6b3d327f64
29 changed files with 1123 additions and 83 deletions

View File

@@ -64,6 +64,12 @@
-->
<import resource="classpath*:alfresco/module-context.xml" />
<!--
Import Enterprise-Only Extensions
-->
<import resource="classpath*:alfresco/enterprise/*-context.xml"/>
<!--
Import of general extensions and bean overrides.

View File

@@ -383,6 +383,26 @@
</property>
</bean>
</property>
<property name="checkCommand">
<bean name="transformer.ImageMagick.CheckCommand" class="org.alfresco.util.exec.RuntimeExec">
<property name="commandsAndArguments">
<map>
<entry key="Windows.*">
<list>
<value>imconvert</value>
<value>-version</value>
</list>
</entry>
<entry key=".*">
<list>
<value>convert</value>
<value>-version</value>
</list>
</entry>
</map>
</property>
</bean>
</property>
</bean>
</beans>

View File

@@ -53,7 +53,9 @@
<!-- Custom MBeanServer -->
<bean id="alfrescoMBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
<bean id="alfrescoMBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true" />
</bean>
<bean id="registry"
class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
@@ -85,10 +87,7 @@
<property name="beans">
<map>
<!-- MBeans to register with alfrescoMBeanServer -->
<entry key="Alfresco:Name=VirtServerRegistry,Type=VirtServerRegistry" value-ref="VirtServerRegistry"/>
<entry key="Alfresco:Name=FileServerConfig,Type=FileServerConfig" value-ref="FileServerConfig"/>
<entry key="Alfresco:Name=Log4jHierarchy,Type=Log4JHierarchy" value-ref="log4jHierarchy"/>
<entry key="Alfresco:Name=RepoServerMgmt,Type=RepoServerMgmt" value-ref="RepoServerMgmt"/>
</map>
</property>
</bean>
@@ -131,7 +130,8 @@
<!-- Log4J Hierarchy -->
<bean id="log4jHierarchy" class="org.apache.log4j.jmx.HierarchyDynamicMBean"/>
<bean id="log4JHierarchyInit" class="org.alfresco.repo.admin.Log4JHierarchyInit" init-method="init">
<!-- This bean will attempt to export extra beans to log4jHierarchy's MBeanServer, so it's vital that the exporter has been initialised -->
<bean id="log4JHierarchyInit" class="org.alfresco.repo.admin.Log4JHierarchyInit" depends-on="exporter" init-method="init">
<property name="log4jHierarchy" ref="log4jHierarchy"/>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
@@ -197,6 +197,9 @@
<!-- Installed AMP modules -->
<value>classpath*:alfresco/module/*/log4j.properties</value>
<!-- Enterprise extensions -->
<value>classpath*:alfresco/enterprise/*-log4j.properties</value>
<!-- Other installed extensions -->
<value>classpath*:alfresco/extension/*-log4j.properties</value>

View File

@@ -3,6 +3,24 @@
<beans>
<bean id="resourceFinder" class="org.alfresco.util.ResourceFinder"/>
<bean id="schedulerResources" factory-bean="resourceFinder" factory-method="getResources">
<constructor-arg>
<list>
<value>classpath:alfresco/domain/quartz.properties</value>
<value>classpath*:alfresco/enterprise/*-quartz.properties</value>
<value>classpath*:alfresco/extension/*-quartz.properties</value>
</list>
</constructor-arg>
</bean>
<bean id="schedulerProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<ref bean="schedulerResources" />
</property>
</bean>
<!-- Task scheduler -->
<!-- Triggers should not appear here - the scheduler should be injected into the trigger definition -->
<!-- This bean should not need to apear else where in extension configuration -->
@@ -10,8 +28,8 @@
<property name="waitForJobsToCompleteOnShutdown">
<value>true</value>
</property>
<property name="configLocation">
<value>classpath:alfresco/domain/quartz.properties</value>
<property name="quartzProperties">
<ref bean="schedulerProperties" />
</property>
<property name="schedulerName">
<value>DefaultScheduler</value>

View File

@@ -40,7 +40,7 @@ import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Abstract base class that provides a set of tests for implementations
@@ -54,7 +54,7 @@ import org.springframework.context.ApplicationContext;
*/
public abstract class AbstractReadOnlyContentStoreTest extends TestCase
{
private static final ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
protected static final ConfigurableApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private static Log logger = LogFactory.getLog(AbstractReadOnlyContentStoreTest.class);

View File

@@ -69,6 +69,10 @@ import org.alfresco.util.Pair;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
/**
@@ -77,7 +81,7 @@ import org.apache.commons.logging.LogFactory;
*
* @author Derek Hulley
*/
public class RoutingContentService implements ContentService
public class RoutingContentService implements ContentService, ApplicationContextAware
{
private static Log logger = LogFactory.getLog(RoutingContentService.class);
@@ -85,6 +89,7 @@ public class RoutingContentService implements ContentService
private NodeService nodeService;
private AVMService avmService;
private RetryingTransactionHelper transactionHelper;
private ApplicationContext applicationContext;
/** a registry of all available content transformers */
private ContentTransformerRegistry transformerRegistry;
@@ -105,14 +110,6 @@ public class RoutingContentService implements ContentService
ClassPolicyDelegate<ContentServicePolicies.OnContentUpdatePolicy> onContentUpdateDelegate;
ClassPolicyDelegate<ContentServicePolicies.OnContentReadPolicy> onContentReadDelegate;
/**
* Default constructor sets up a temporary store
*/
public RoutingContentService()
{
this.tempStore = new FileContentStore(TempFileProvider.getTempDir().getAbsolutePath());
}
/**
* @deprecated Replaced by {@link #setRetryingTransactionHelper(RetryingTransactionHelper)}
*/
@@ -161,11 +158,24 @@ public class RoutingContentService implements ContentService
this.imageMagickContentTransformer = imageMagickContentTransformer;
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
/**
* Service initialise
*/
public void init()
{
// Set up a temporary store
this.tempStore = new FileContentStore((ConfigurableApplicationContext) this.applicationContext,
TempFileProvider.getTempDir().getAbsolutePath());
// Bind on update properties behaviour
this.policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"),

View File

@@ -65,13 +65,13 @@ public class RoutingContentStoreTest extends AbstractWritableContentStoreTest
File tempDir = TempFileProvider.getTempDir();
// Create a subdirectory for A
File storeADir = new File(tempDir, "A");
storeA = new FileContentStore(storeADir);
storeA = new FileContentStore(ctx, storeADir);
// Create a subdirectory for B
File storeBDir = new File(tempDir, "B");
storeB = new FileContentStore(storeBDir);
storeB = new FileContentStore(ctx, storeBDir);
// Create a subdirectory for C
File storeCDir = new File(tempDir, "C");
storeC = new DumbReadOnlyFileStore(new FileContentStore(storeCDir));
storeC = new DumbReadOnlyFileStore(new FileContentStore(ctx, storeCDir));
// No subdirectory for D
storeD = new SupportsNoUrlFormatStore();
// Create the routing store

View File

@@ -36,18 +36,23 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.Tenant;
import org.alfresco.repo.tenant.TenantDeployer;
import org.alfresco.repo.tenant.TenantService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Content Store that supports tenant routing, if multi-tenancy is enabled.
*
* Note: Need to initialise before the dictionary service, in the case that models are dynamically loaded for the tenant.
*/
public class TenantRoutingFileContentStore extends AbstractRoutingContentStore implements TenantDeployer
public class TenantRoutingFileContentStore extends AbstractRoutingContentStore implements TenantDeployer, ApplicationContextAware
{
Map<String, FileContentStore> tenantFileStores = new HashMap<String, FileContentStore>();
private String defaultRootDirectory;
private TenantService tenantService;
private ApplicationContext applicationContext;
public void setDefaultRootDir(String defaultRootDirectory)
@@ -60,6 +65,16 @@ public class TenantRoutingFileContentStore extends AbstractRoutingContentStore i
this.tenantService = tenantService;
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.
* ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
protected ContentStore selectWriteStore(ContentContext ctx)
{
return getTenantFileStore(tenantService.getCurrentUserDomain());
@@ -114,7 +129,8 @@ public class TenantRoutingFileContentStore extends AbstractRoutingContentStore i
tenantDomain = tenant.getTenantDomain();
}
putTenantFileStore(tenantDomain, new FileContentStore(new File(rootDir)));
putTenantFileStore(tenantDomain, new FileContentStore((ConfigurableApplicationContext) this.applicationContext,
new File(rootDir)));
}
public void destroy()

View File

@@ -29,6 +29,8 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import junit.framework.TestCase;
import org.alfresco.repo.avm.AVMNodeDAO;
import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.content.filestore.FileContentStore;
@@ -42,9 +44,7 @@ import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.TempFileProvider;
import org.springframework.context.ApplicationContext;
import junit.framework.TestCase;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @see org.alfresco.repo.content.cleanup.ContentStoreCleaner
@@ -53,7 +53,7 @@ import junit.framework.TestCase;
*/
public class ContentStoreCleanerTest extends TestCase
{
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private static ConfigurableApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private ContentStoreCleaner cleaner;
private ContentStore store;
@@ -71,7 +71,7 @@ public class ContentStoreCleanerTest extends TestCase
ContentUrlDAO contentUrlDAO = (ContentUrlDAO) ctx.getBean("contentUrlDAO");
// we need a store
store = new FileContentStore(TempFileProvider.getTempDir().getAbsolutePath());
store = new FileContentStore(ctx, TempFileProvider.getTempDir().getAbsolutePath());
// and a listener
listener = new DummyCleanerListener();
// initialise record of deleted URLs

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
@@ -43,6 +43,10 @@ import org.alfresco.util.GUID;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
/**
* Provides a store of node content directly to the file system. The writers
@@ -53,7 +57,7 @@ import org.apache.commons.logging.LogFactory;
*
* @author Derek Hulley
*/
public class FileContentStore extends AbstractContentStore
public class FileContentStore extends AbstractContentStore implements ApplicationListener
{
/**
* <b>store</b> is the new prefix for file content URLs
@@ -69,21 +73,24 @@ public class FileContentStore extends AbstractContentStore
private boolean readOnly;
/**
* @param rootDirectoryStr the root under which files will be stored.
* The directory will be created if it does not exist.
* Private: for Spring-constructed instances only.
*
* @param rootDirectoryStr
* the root under which files will be stored. The directory will be created if it does not exist.
* @see FileContentStore#FileContentStore(File)
*/
public FileContentStore(String rootDirectoryStr)
private FileContentStore(String rootDirectoryStr)
{
this(new File(rootDirectoryStr));
}
/**
* @param rootDirectory the root under which files will be stored.
* The directory will be created if it does not exist.
* Private: for Spring-constructed instances only.
*
* @param rootDirectory
* the root under which files will be stored. The directory will be created if it does not exist.
*/
public FileContentStore(File rootDirectory)
private FileContentStore(File rootDirectory)
{
if (!rootDirectory.exists())
{
@@ -98,6 +105,36 @@ public class FileContentStore extends AbstractContentStore
readOnly = false;
}
/**
* Public constructor for programmatic use.
*
* @param context
* application context through which events can be published
* @param rootDirectoryStr
* the root under which files will be stored. The directory will be created if it does not exist.
* @see FileContentStore#FileContentStore(File)
*/
public FileContentStore(ConfigurableApplicationContext context, String rootDirectoryStr)
{
this(rootDirectoryStr);
publishEvent(context);
}
/**
* Public constructor for programmatic use.
*
* @param context
* application context through which events can be published
* @param rootDirectory
* the root under which files will be stored. The directory will be created if it does not exist.
*/
public FileContentStore(ConfigurableApplicationContext context, File rootDirectory)
{
this(rootDirectory);
publishEvent(context);
}
public String toString()
{
StringBuilder sb = new StringBuilder(36);
@@ -358,6 +395,12 @@ public class FileContentStore extends AbstractContentStore
}
/**
* Returns a writer onto a location based on the date.
*
* @param existingContentReader
* the existing content reader
* @param newContentUrl
* the new content url
* @return Returns a writer onto a location based on the date
*/
public ContentWriter getWriterInternal(ContentReader existingContentReader, String newContentUrl)
@@ -396,6 +439,17 @@ public class FileContentStore extends AbstractContentStore
}
}
/**
* Gets the urls.
*
* @param createdAfter
* the created after date
* @param createdBefore
* the created before dat6e
* @param handler
* the handler
* @return the urls
*/
public void getUrls(Date createdAfter, Date createdBefore, ContentUrlHandler handler)
{
// recursively get all files within the root
@@ -409,11 +463,12 @@ public class FileContentStore extends AbstractContentStore
}
/**
* Returns a list of all files within the given directory and all subdirectories.
* @param directory the current directory to get the files from
* @param handler the callback to use for each URL
* @param createdAfter only get URLs for content create after this date
* @param createdBefore only get URLs for content created before this date
* @return Returns a list of all files within the given directory and all subdirectories
* @return a list of all files within the given directory and all subdirectories
*/
private void getUrls(File directory, ContentUrlHandler handler, Date createdAfter, Date createdBefore)
{
@@ -516,4 +571,41 @@ public class FileContentStore extends AbstractContentStore
// done
return newContentUrl;
}
/**
* Publishes an event to the application context that will notify any interested parties of the existence of this
* content store.
*
* @param context
* the application context
*/
private void publishEvent(ConfigurableApplicationContext context)
{
// If the context isn't running yet, we have to wait until the refresh event
try
{
// Neither context.isActive() or context.isRunning() seem to detect whether the refresh() has completed
context.publishEvent(new FileContentStoreCreatedEvent(this, rootDirectory));
}
catch (IllegalStateException e)
{
context.addApplicationListener(this);
}
}
/*
* (non-Javadoc)
* @see
* org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
// Once the context has been refreshed, we tell other interested beans about the existence of this content store
// (e.g. for monitoring purposes)
if (event instanceof ContextRefreshedEvent)
{
((ContextRefreshedEvent) event).getApplicationContext().publishEvent(
new FileContentStoreCreatedEvent(this, rootDirectory));
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.content.filestore;
import java.io.File;
import org.springframework.context.ApplicationEvent;
/**
* A class of event that notifies the listener of the existence of a {@link FileContentStore}. Useful for Monitoring
* purposes.
*
* @author dward
*/
public class FileContentStoreCreatedEvent extends ApplicationEvent
{
private static final long serialVersionUID = 7090069096441126707L;
/** The root directory of the store. */
private final File rootDirectory;
/**
* The Constructor.
*
* @param source
* the source content store
* @param rootDirectory
* the root directory
*/
public FileContentStoreCreatedEvent(FileContentStore source, File rootDirectory)
{
super(source);
this.rootDirectory = rootDirectory;
}
/**
* Gets the root directory.
*
* @return the root directory
*/
public File getRootDirectory()
{
return this.rootDirectory;
}
}

View File

@@ -52,7 +52,7 @@ public class FileContentStoreTest extends AbstractWritableContentStoreTest
// create a store that uses a subdirectory of the temp directory
File tempDir = TempFileProvider.getTempDir();
store = new FileContentStore(
store = new FileContentStore(ctx,
tempDir.getAbsolutePath() +
File.separatorChar +
getName());

View File

@@ -49,7 +49,7 @@ public class NoRandomAccessFileContentStoreTest extends AbstractWritableContentS
// create a store that uses a subdirectory of the temp directory
File tempDir = TempFileProvider.getTempDir();
store = new FileContentStore(
store = new FileContentStore(ctx,
tempDir.getAbsolutePath() +
File.separatorChar +
getName());

View File

@@ -50,7 +50,7 @@ public class ReadOnlyFileContentStoreTest extends AbstractReadOnlyContentStoreTe
// create a store that uses a subdirectory of the temp directory
File tempDir = TempFileProvider.getTempDir();
store = new FileContentStore(
store = new FileContentStore(ctx,
tempDir.getAbsolutePath() +
File.separatorChar +
getName());

View File

@@ -30,7 +30,6 @@ import java.util.Set;
import junit.framework.TestCase;
import org.alfresco.repo.content.AbstractContentStore;
import org.alfresco.repo.content.ContentContext;
import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.content.ContentStore.ContentUrlHandler;
@@ -38,6 +37,8 @@ import org.alfresco.repo.content.filestore.FileContentStore;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.GUID;
import org.alfresco.util.TempFileProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
/**
* Tests the content store replicator.
@@ -60,13 +61,17 @@ public class ContentStoreReplicatorTest extends TestCase
{
super.setUp();
// Create a dummy context for message broadcasting
StaticApplicationContext ctx = new StaticApplicationContext();
ctx.refresh();
File tempDir = TempFileProvider.getTempDir();
// create the source file store
String storeDir = tempDir.getAbsolutePath() + File.separatorChar + getName() + File.separatorChar + GUID.generate();
sourceStore = new FileContentStore(storeDir);
sourceStore = new FileContentStore(ctx, storeDir);
// create the target file store
storeDir = tempDir.getAbsolutePath() + File.separatorChar + getName() + File.separatorChar + GUID.generate();
targetStore = new FileContentStore(storeDir);
targetStore = new FileContentStore(ctx, storeDir);
// create the replicator
replicator = new ContentStoreReplicator();

View File

@@ -70,13 +70,13 @@ public class ReplicatingContentStoreTest extends AbstractWritableContentStoreTes
File tempDir = TempFileProvider.getTempDir();
// create a primary file store
String storeDir = tempDir.getAbsolutePath() + File.separatorChar + GUID.generate();
primaryStore = new FileContentStore(storeDir);
primaryStore = new FileContentStore(ctx, storeDir);
// create some secondary file stores
secondaryStores = new ArrayList<ContentStore>(3);
for (int i = 0; i < 4; i++)
{
storeDir = tempDir.getAbsolutePath() + File.separatorChar + GUID.generate();
FileContentStore store = new FileContentStore(storeDir);
FileContentStore store = new FileContentStore(ctx, storeDir);
secondaryStores.add(store);
// Only the first 3 are writable
if (i >= 3)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
@@ -32,6 +32,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -54,6 +55,12 @@ public class ImageMagickContentTransformer extends AbstractImageMagickContentTra
/** the system command executer */
private RuntimeExec executer;
/** the check command executer */
private RuntimeExec checkCommand;
/** the output from the check command */
private String versionString;
/**
* Default constructor
*/
@@ -80,6 +87,29 @@ public class ImageMagickContentTransformer extends AbstractImageMagickContentTra
this.executer = executer;
}
/**
* Sets the command that must be executed in order to retrieve version information from the converting executable
* and thus test that the executable itself is present.
*
* @param checkCommand
* command executer to retrieve version information
*/
public void setCheckCommand(RuntimeExec checkCommand)
{
this.checkCommand = checkCommand;
}
/**
* Gets the version string captured from the check command.
*
* @return the version string
*/
public String getVersionString()
{
return this.versionString;
}
/**
* Checks for the JMagick and ImageMagick dependencies, using the common
* {@link #transformInternal(File, File) transformation method} to check
@@ -92,6 +122,30 @@ public class ImageMagickContentTransformer extends AbstractImageMagickContentTra
throw new AlfrescoRuntimeException("System runtime executer not set");
}
super.init();
if (isAvailable())
{
try
{
ExecutionResult result = this.checkCommand.execute();
if (result.getSuccess())
{
this.versionString = result.getStdOut().trim();
}
else
{
setAvailable(false);
}
}
catch (Throwable e)
{
setAvailable(false);
logger.error(getClass().getSimpleName() + " not available: "
+ (e.getMessage() != null ? e.getMessage() : ""));
// debug so that we can trace the issue if required
logger.debug(e);
}
}
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -18,7 +18,7 @@
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
@@ -54,6 +54,9 @@ public class PDFToSWFContentTransformer extends AbstractContentTransformer2
/** Used to indicate whether the transformaer in available or not */
private boolean available = false;
/** Stores the output from the check command */
private String versionString;
/** Check and transform command */
private RuntimeExec checkCommand;
private RuntimeExec transformCommand;
@@ -130,15 +133,13 @@ public class PDFToSWFContentTransformer extends AbstractContentTransformer2
{
ExecutionResult result = getCheckCommand().execute();
// check the return code
this.available = result.getSuccess();
if (this.available == false)
if (this.available = result.getSuccess())
{
logger.error("Failed to start SWF2PDF transformer: \n" + result);
this.versionString = result.getStdOut().trim();
}
else
{
// no check - just assume it is available
this.available = true;
logger.error("Failed to start SWF2PDF transformer: \n" + result);
}
// call the base class to make sure that it gets registered
@@ -249,4 +250,24 @@ public class PDFToSWFContentTransformer extends AbstractContentTransformer2
return result;
}
/**
* Signals whether this transformer is available.
*
* @return true, if is available
*/
public boolean isAvailable()
{
return this.available;
}
/**
* Gets the version string captured from the check command.
*
* @return the version string
*/
public String getVersionString()
{
return this.versionString;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.descriptor;
import org.alfresco.service.descriptor.DescriptorService;
import org.springframework.context.ApplicationEvent;
/**
* A class of event that notifies the listener of the availability of the {@link DescriptorService}. Useful for
* Monitoring purposes.
*
* @author dward
*/
public class DescriptorServiceAvailableEvent extends ApplicationEvent
{
private static final long serialVersionUID = 8217523101300405165L;
/**
* The Constructor.
*
* @param source
* the source descriptor service
*/
public DescriptorServiceAvailableEvent(DescriptorService source)
{
super(source);
}
/**
* Gets the descriptor service that raised the event.
*
* @return the descriptor service
*/
public DescriptorService getDescriptorService()
{
return (DescriptorService) getSource();
}
}

View File

@@ -183,6 +183,8 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean implements Desc
};
installedRepoDescriptor = transactionService.getRetryingTransactionHelper().doInTransaction(
createDescriptorWork, transactionService.isReadOnly(), false);
((ApplicationContext)event.getSource()).publishEvent(new DescriptorServiceAvailableEvent(this));
}
/*

View File

@@ -70,7 +70,11 @@ import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
/**
* This class is resource manager LuceneIndexers and LuceneSearchers. It supports two phase commit inside XA
@@ -80,7 +84,8 @@ import org.springframework.beans.factory.InitializingBean;
* @author andyh
*/
public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneIndexerAndSearcher, XAResource
public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneIndexerAndSearcher, XAResource,
ApplicationContextAware
{
private static Log logger = LogFactory.getLog(AbstractLuceneIndexerAndSearcherFactory.class);
@@ -180,6 +185,8 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI
private boolean cacheEnabled = true;
private ConfigurableApplicationContext applicationContext;
/**
* Private constructor for the singleton TODO: FIt in with IOC
*/
@@ -189,6 +196,26 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI
super();
}
/*
* (non-Javadoc)
* @seeorg.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.
* ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.LuceneConfig#getApplicationContext()
*/
public ConfigurableApplicationContext getApplicationContext()
{
return this.applicationContext;
}
/**
* Set the directory that contains the indexes
*
@@ -995,7 +1022,6 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI
private Set<LuceneIndexerAndSearcher> factories;
@SuppressWarnings("unused")
private NodeService nodeService;
private String targetLocation;

View File

@@ -28,6 +28,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import org.alfresco.repo.domain.hibernate.BulkLoader;
import org.alfresco.repo.search.MLAnalysisMode;
import org.springframework.context.ConfigurableApplicationContext;
public interface LuceneConfig
{
@@ -208,4 +209,10 @@ public interface LuceneConfig
* @return
*/
public int getMaxLinkAspectCacheSize();
/**
* Gets the application context through which events can be broadcast
* @return
*/
public ConfigurableApplicationContext getApplicationContext();
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.search.impl.lucene.index;
import org.springframework.context.ApplicationEvent;
/**
* A class of event that notifies the listener of a significant event relating to a Lucene index. Useful for Monitoring
* purposes.
*
* @author dward
*/
public class IndexEvent extends ApplicationEvent
{
private static final long serialVersionUID = -4616231785087405506L;
/** The event description. */
private final String description;
/** Its instance count. */
private final int count;
/**
* The Constructor.
*
* @param source
* the source index monitor
* @param description
* the event description
* @param count
* its instance count
*/
public IndexEvent(IndexMonitor source, String description, int count)
{
super(source);
this.description = description;
this.count = count;
}
/**
* Gets the source index monitor.
*
* @return the index monitor
*/
public IndexMonitor getIndexMonitor()
{
return (IndexMonitor) getSource();
}
/**
* Gets the event description.
*
* @return the description
*/
public String getDescription()
{
return this.description;
}
/**
* Gets the event instance count.
*
* @return the count
*/
public int getCount()
{
return this.count;
}
}

View File

@@ -46,11 +46,13 @@ import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -84,6 +86,10 @@ import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.RAMDirectory;
import org.safehaus.uuid.UUID;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
/**
* The information that makes up an index. IndexInfoVersion Repeated information of the form
@@ -118,7 +124,7 @@ import org.safehaus.uuid.UUID;
*
* @author Andy Hind
*/
public class IndexInfo
public class IndexInfo implements IndexMonitor
{
public static final String MAIN_READER = "MainReader";
@@ -164,6 +170,11 @@ public class IndexInfo
*/
private File indexDirectory;
/**
* The directory relative to the root path
*/
private String relativePath;
/**
* The file holding the index information
*/
@@ -313,6 +324,8 @@ public class IndexInfo
private LuceneConfig config;
private List<ApplicationListener> applicationListeners = new LinkedList<ApplicationListener>();
static
{
// We do not require any of the lucene in-built locking.
@@ -426,6 +439,17 @@ public class IndexInfo
throw new AlfrescoRuntimeException("The index must be held in a directory");
}
// Work out the relative path of the index
try
{
String indexRoot = new File(config.getIndexRootLocation()).getCanonicalPath();
this.relativePath = this.indexDirectory.getCanonicalPath().substring(indexRoot.length() + 1);
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Failed to determine index relative path", e);
}
// Create the info files.
File indexInfoFile = new File(this.indexDirectory, INDEX_INFO);
File indexInfoBackupFile = new File(this.indexDirectory, INDEX_INFO_BACKUP);
@@ -628,6 +652,8 @@ public class IndexInfo
cleaner.schedule();
}
}, 0, 20000);
publishDiscoveryEvent();
}
private class DeleteUnknownGuidDirectories implements LockWork<Object>
@@ -1501,6 +1527,7 @@ public class IndexInfo
{
throw new IndexerException("Invalid transition for " + id + " from " + entry.getStatus() + " to " + TransactionStatus.COMMITTED);
}
notifyListeners("CommittedTransactions", 1);
}
public boolean requiresFileLock()
@@ -3221,6 +3248,8 @@ public class IndexInfo
dumpInfo();
notifyListeners("MergedDeletions", toDelete.size());
return null;
}
@@ -3230,6 +3259,7 @@ public class IndexInfo
}
});
}
finally
{
@@ -3475,6 +3505,8 @@ public class IndexInfo
registerReferenceCountingIndexReader(finalMergeTargetId, finalNewReader);
notifyListeners("MergedIndexes", toMerge.size());
dumpInfo();
writeStatus();
@@ -3634,9 +3666,200 @@ public class IndexInfo
return false;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getRelativePath()
*/
public String getRelativePath()
{
return this.relativePath;
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getStatusSnapshot()
*/
public Map<String, Integer> getStatusSnapshot()
{
Map<String, Integer> snapShot = new TreeMap<String, Integer>();
readWriteLock.writeLock().lock();
try
{
for (IndexEntry entry : indexEntries.values())
{
String stateKey = entry.getType() + "-" + entry.getStatus();
Integer count = snapShot.get(stateKey);
snapShot.put(stateKey, count == null ? 1 : count + 1);
}
return snapShot;
}
finally
{
readWriteLock.writeLock().unlock();
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getActualSize()
*/
public long getActualSize() throws IOException
{
getReadLock();
try
{
int size = 0;
for (IndexEntry entry : this.indexEntries.values())
{
File location = new File(this.indexDirectory, entry.getName()).getCanonicalFile();
File[] contents = location.listFiles();
for (File file : contents)
{
if (file.isFile())
{
size += file.length();
}
}
}
return size;
}
finally
{
releaseReadLock();
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getUsedSize()
*/
public long getUsedSize() throws IOException
{
getReadLock();
try
{
return sizeRecurse(this.indexDirectory);
}
finally
{
releaseReadLock();
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getNumberOfDocuments()
*/
public int getNumberOfDocuments() throws IOException
{
IndexReader reader = getMainIndexReferenceCountingReadOnlyIndexReader();
try
{
return reader.numDocs();
}
finally
{
reader.close();
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getNumberOfFields()
*/
public int getNumberOfFields() throws IOException
{
IndexReader reader = getMainIndexReferenceCountingReadOnlyIndexReader();
try
{
return reader.getFieldNames(IndexReader.FieldOption.ALL).size();
}
finally
{
reader.close();
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#getNumberOfIndexedFields()
*/
public int getNumberOfIndexedFields() throws IOException
{
IndexReader reader = getMainIndexReferenceCountingReadOnlyIndexReader();
try
{
return reader.getFieldNames(IndexReader.FieldOption.INDEXED).size();
}
finally
{
reader.close();
}
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.search.impl.lucene.index.IndexMonitor#addApplicationListener(org.springframework.context.
* ApplicationListener)
*/
public void addApplicationListener(ApplicationListener listener)
{
this.applicationListeners.add(listener);
}
private long sizeRecurse(File fileOrDir)
{
long size = 0;
if (fileOrDir.isDirectory())
{
File[] files = fileOrDir.listFiles();
for (File file : files)
{
size += sizeRecurse(file);
}
}
else
{
size = fileOrDir.length();
}
return size;
}
private void publishDiscoveryEvent()
{
final IndexEvent discoveryEvent = new IndexEvent(this, "Discovery", 1);
final ConfigurableApplicationContext applicationContext = this.config.getApplicationContext();
try
{
applicationContext.publishEvent(discoveryEvent);
}
catch (IllegalStateException e)
{
// There's a possibility that the application context hasn't fully refreshed yet, so register a listener
// that will fire when it has
applicationContext.addApplicationListener(new ApplicationListener()
{
public void onApplicationEvent(ApplicationEvent event)
{
if (event instanceof ContextRefreshedEvent)
{
applicationContext.publishEvent(discoveryEvent);
}
}
});
}
}
private void notifyListeners(String description, int count)
{
if (!this.applicationListeners.isEmpty())
{
IndexEvent event = new IndexEvent(this, description, count);
for (ApplicationListener listener : this.applicationListeners)
{
listener.onApplicationEvent(event);
}
}
}
interface Schedulable
{
void schedule();
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.search.impl.lucene.index;
import java.io.IOException;
import java.util.Map;
import org.springframework.context.ApplicationListener;
/**
* An interface that exposes information about a Lucene Index and that allows registration of a listener for event
* notifications.
*
* @author dward
*/
public interface IndexMonitor
{
/**
* Gets the relative path of the index directory.
*
* @return the relative path
*/
public String getRelativePath();
/**
* Gets a snapshot of the statuses of the individual entries in this index.
*
* @return a map of entry status names to entry counts
*/
public Map<String, Integer> getStatusSnapshot();
/**
* Gets the actual size of the index in bytes.
*
* @return the actual size in bytes
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public long getActualSize() throws IOException;
/**
* Gets the size used on disk by the index directory. A large discrepancy from the value returned by
* {@link #getActualSize()} may indicate that there are unused data files.
*
* @return the size on disk in bytes
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public long getUsedSize() throws IOException;
/**
* Gets the number of documents in the index.
*
* @return the number of documents
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public int getNumberOfDocuments() throws IOException;
/**
* Gets the number of fields known to the index.
*
* @return the number of fields
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public int getNumberOfFields() throws IOException;
/**
* Gets the number of indexed fields.
*
* @return the number of indexed fields
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public int getNumberOfIndexedFields() throws IOException;
/**
* Registers a listener for events on this index.
*
* @param listener
* the listener
*/
public void addApplicationListener(ApplicationListener listener);
}

View File

@@ -24,7 +24,7 @@
*/
package org.alfresco.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
@@ -46,7 +46,7 @@ public class ApplicationContextHelper
*
* @return Returns a new application context
*/
public synchronized static ApplicationContext getApplicationContext()
public synchronized static ConfigurableApplicationContext getApplicationContext()
{
if (instance != null)
{

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.util;
import java.util.Map;
import org.springframework.context.ApplicationEvent;
/**
* A class of event that notifies the listener of the status of the Open Office Connection. Useful for Monitoring
* purposes.
*
* @author dward
*/
public class OpenOfficeConnectionEvent extends ApplicationEvent
{
private static final long serialVersionUID = 8834274840220309384L;
/**
* The Constructor.
*
* @param metaData
* the meta data map
*/
public OpenOfficeConnectionEvent(Map<String, Object> metaData)
{
super(metaData);
}
/**
* Gets the meta data map.
*
* @return the meta data map
*/
@SuppressWarnings("unchecked")
public Map<String, Object> getMetaData()
{
return (Map<String, Object>) getSource();
}
}

View File

@@ -24,8 +24,12 @@
*/
package org.alfresco.util;
import java.lang.reflect.Method;
import java.net.ConnectException;
import java.util.Map;
import java.util.TreeMap;
import net.sf.jooreports.openoffice.connection.AbstractOpenOfficeConnection;
import net.sf.jooreports.openoffice.connection.OpenOfficeConnection;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -37,8 +41,14 @@ import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import com.sun.star.registry.RegistryValueType;
import com.sun.star.registry.XRegistryKey;
import com.sun.star.registry.XSimpleRegistry;
import com.sun.star.uno.UnoRuntime;
/**
* A bootstrap class that checks for the presence of a valid <b>OpenOffice</b> connection, as provided by the
* <code>net.sf.jooreports.openoffice.connection.OpenOfficeConnection</code> implementations.
@@ -47,6 +57,7 @@ import org.springframework.context.ApplicationEvent;
*/
public class OpenOfficeConnectionTester extends AbstractLifecycleBean
{
private static final String ATTRIBUTE_AVAILABLE = "available";
private static final String INFO_CONNECTION_VERIFIED = "system.openoffice.info.connection_verified";
private static final String ERR_CONNECTION_FAILED = "system.openoffice.err.connection_failed";
private static final String ERR_CONNECTION_LOST = "system.openoffice.err.connection_lost";
@@ -55,6 +66,7 @@ public class OpenOfficeConnectionTester extends AbstractLifecycleBean
private static Log logger = LogFactory.getLog(OpenOfficeConnectionTester.class);
private OpenOfficeConnection connection;
private Map<String, Object> openOfficeMetadata = new TreeMap<String, Object>();
private boolean strict;
public OpenOfficeConnectionTester()
@@ -87,6 +99,7 @@ public class OpenOfficeConnectionTester extends AbstractLifecycleBean
protected void onBootstrap(ApplicationEvent event)
{
checkConnection();
((ApplicationContext) event.getSource()).publishEvent(new OpenOfficeConnectionEvent(this.openOfficeMetadata));
}
/**
@@ -109,7 +122,7 @@ public class OpenOfficeConnectionTester extends AbstractLifecycleBean
* then a disconnected {@link #setConnection(OpenOfficeConnection) connection} will result in a
* runtime exception being generated.
*/
private synchronized void checkConnection()
private void checkConnection()
{
String connectedMessage = I18NUtil.getMessage(INFO_CONNECTION_VERIFIED);
boolean connected = testAndConnect();
@@ -134,26 +147,68 @@ public class OpenOfficeConnectionTester extends AbstractLifecycleBean
public boolean testAndConnect()
{
PropertyCheck.mandatory(this, "connection", connection);
if (connection.isConnected())
synchronized (this.openOfficeMetadata)
{
PropertyCheck.mandatory(this, "connection", connection);
if (!connection.isConnected())
{
// the connection is fine
return true;
}
// attempt to make the connection
try
{
connection.connect();
// that worked
return true;
}
catch (ConnectException e)
{
// No luck
this.openOfficeMetadata.clear();
this.openOfficeMetadata.put(ATTRIBUTE_AVAILABLE, Boolean.FALSE);
return false;
}
}
// Let's try to get at the version metadata
Boolean lastAvailability = (Boolean)this.openOfficeMetadata.get(ATTRIBUTE_AVAILABLE);
if (lastAvailability == null || !lastAvailability.booleanValue())
{
this.openOfficeMetadata.put(ATTRIBUTE_AVAILABLE, Boolean.TRUE);
try
{
// We have to peak inside the connection class to get the service we want!
Method getServiceMethod = AbstractOpenOfficeConnection.class.getDeclaredMethod("getService",
String.class);
getServiceMethod.setAccessible(true);
Object configurationRegistry = getServiceMethod.invoke(connection,
"com.sun.star.configuration.ConfigurationRegistry");
XSimpleRegistry registry = (XSimpleRegistry) UnoRuntime.queryInterface(
com.sun.star.registry.XSimpleRegistry.class, configurationRegistry);
registry.open("org.openoffice.Setup", true, false);
XRegistryKey root = registry.getRootKey();
XRegistryKey product = root.openKey("Product");
for (XRegistryKey key : product.openKeys())
{
switch (key.getValueType().getValue())
{
case RegistryValueType.LONG_value:
openOfficeMetadata.put(key.getKeyName(), key.getLongValue());
break;
case RegistryValueType.ASCII_value:
openOfficeMetadata.put(key.getKeyName(), key.getAsciiValue());
break;
case RegistryValueType.STRING_value:
openOfficeMetadata.put(key.getKeyName(), key.getStringValue());
break;
}
}
registry.close();
}
catch (Exception e)
{
logger.warn("Error trying to query Open Office version information", e);
}
}
}
return true;
}
/**
* Quartz job that checks an OpenOffice connection.
*

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.util;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
/**
* Can be used in Spring configuration to search for all resources matching an array of patterns.
*
* @author dward
*/
public class ResourceFinder extends PathMatchingResourcePatternResolver
{
/**
* Instantiates a new resource finder.
*/
public ResourceFinder()
{
}
/**
* The Constructor.
*
* @param classLoader
* the class loader
*/
public ResourceFinder(ClassLoader classLoader)
{
super(classLoader);
}
/**
* The Constructor.
*
* @param resourceLoader
* the resource loader
*/
public ResourceFinder(ResourceLoader resourceLoader)
{
super(resourceLoader);
}
/**
* Gets an array of resources matching the given location patterns.
*
* @param locationPatterns
* the location patterns
* @return the matching resources, ordered by locationPattern index and location in the classpath
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public Resource[] getResources(String[] locationPatterns) throws IOException
{
List<Resource> resources = new LinkedList<Resource>();
for (String locationPattern : locationPatterns)
{
resources.addAll(Arrays.asList(getResources(locationPattern)));
}
Resource[] resourceArray = new Resource[resources.size()];
resources.toArray(resourceArray);
return resourceArray;
}
}