CCM NG: Current status
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3498 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
7f2da80e81
commit
9a2c98cbe0
|
|
@ -48,6 +48,30 @@
|
||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>hibernate-validator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Dependencies for log4j 2 including adapter for the log4j 1.2 API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
|
<artifactId>log4j-1.2-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-beanutils</groupId>
|
||||||
|
<artifactId>commons-beanutils</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>oro</groupId>
|
||||||
|
<artifactId>oro</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002-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.kernel;
|
||||||
|
|
||||||
|
import com.arsdigita.runtime.AbstractConfig;
|
||||||
|
import com.arsdigita.util.parameter.BooleanParameter;
|
||||||
|
import com.arsdigita.util.parameter.EnumerationParameter;
|
||||||
|
import com.arsdigita.util.parameter.Parameter;
|
||||||
|
import com.arsdigita.util.parameter.StringParameter;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Justin Ross
|
||||||
|
* @see com.arsdigita.kernel.Kernel
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class KernelConfig extends AbstractConfig {
|
||||||
|
|
||||||
|
/** A logger instance. */
|
||||||
|
private static final Logger s_log = Logger.getLogger(KernelConfig.class);
|
||||||
|
|
||||||
|
/** Singelton config object. */
|
||||||
|
private static KernelConfig s_conf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gain a KernelConfig object.
|
||||||
|
*
|
||||||
|
* Singelton pattern, don't instantiate a KernelConfig object using the
|
||||||
|
* constructor directly!
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static synchronized KernelConfig getConfig() {
|
||||||
|
if (s_conf == null) {
|
||||||
|
s_conf = new KernelConfig();
|
||||||
|
s_conf.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TODO: should be renamed waf.kernel.debug" */
|
||||||
|
private static Parameter m_debug = new BooleanParameter
|
||||||
|
("waf.debug", Parameter.REQUIRED, Boolean.FALSE);
|
||||||
|
/** Whether WEB development support should be activated (true) or not. */
|
||||||
|
// Handled in OLD initializer c.ad.webdevsupport.LegacyInitializer
|
||||||
|
private static Parameter m_webdevSupport = new BooleanParameter
|
||||||
|
("waf.webdev_support", Parameter.REQUIRED, Boolean.FALSE);
|
||||||
|
private final Parameter m_permissions = new BooleanParameter
|
||||||
|
("waf.kernel.data_permission_check_enabled", Parameter.REQUIRED,
|
||||||
|
Boolean.TRUE);
|
||||||
|
/** User Login by screen name or email address */
|
||||||
|
private final EnumerationParameter m_identifier = new EnumerationParameter
|
||||||
|
("waf.kernel.primary_user_identifier", Parameter.REQUIRED,
|
||||||
|
"email");
|
||||||
|
/**
|
||||||
|
* */
|
||||||
|
private final Parameter m_SSO = new BooleanParameter
|
||||||
|
("waf.kernel.sso_login", Parameter.REQUIRED, Boolean.FALSE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* */
|
||||||
|
private final Parameter m_remember = new BooleanParameter
|
||||||
|
("waf.kernel.remember_login", Parameter.REQUIRED, Boolean.TRUE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* */
|
||||||
|
private final Parameter m_secureLogin = new BooleanParameter
|
||||||
|
("waf.kernel.secure_login", Parameter.REQUIRED, Boolean.FALSE);
|
||||||
|
|
||||||
|
/** String containing the supported languages.
|
||||||
|
The first one is considered default. */
|
||||||
|
private final Parameter m_supportedLanguages = new StringParameter
|
||||||
|
("waf.kernel.supported_languages", Parameter.REQUIRED,
|
||||||
|
"en,de,fr,nl,it,pt,es");
|
||||||
|
private final Parameter m_languageIndependentItems = new BooleanParameter
|
||||||
|
("waf.kernel.language_independent_items", Parameter.REQUIRED, Boolean.FALSE);
|
||||||
|
private final Parameter m_languageIndependentCode = new StringParameter
|
||||||
|
("waf.kernel.language_independent_code", Parameter.OPTIONAL,
|
||||||
|
"--");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public KernelConfig() {
|
||||||
|
|
||||||
|
// Add recognised Login user identification to enumeration parameter
|
||||||
|
m_identifier.put("email", "email");
|
||||||
|
m_identifier.put("screen_name", "screenName");
|
||||||
|
|
||||||
|
|
||||||
|
register(m_debug);
|
||||||
|
register(m_webdevSupport);
|
||||||
|
register(m_permissions);
|
||||||
|
register(m_identifier);
|
||||||
|
register(m_SSO);
|
||||||
|
register(m_remember);
|
||||||
|
register(m_secureLogin);
|
||||||
|
register(m_supportedLanguages);
|
||||||
|
register(m_languageIndependentItems);
|
||||||
|
register(m_languageIndependentCode);
|
||||||
|
|
||||||
|
loadInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final boolean isDebugEnabled() {
|
||||||
|
return ((Boolean) get(m_debug)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true, if WEB developer support should be activated.
|
||||||
|
*/
|
||||||
|
public final boolean isWebdevSupportActive() {
|
||||||
|
return ((Boolean) get(m_webdevSupport)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isDataPermissionCheckEnabled() {
|
||||||
|
return ((Boolean) get(m_permissions)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getPrimaryUserIdentifier() {
|
||||||
|
return (String) get(m_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean emailIsPrimaryIdentifier() {
|
||||||
|
return "email".equals(get(m_identifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean screenNameIsPrimaryIdentifier() {
|
||||||
|
return !emailIsPrimaryIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isSSOenabled() {
|
||||||
|
return ((Boolean) get(m_SSO)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Move this to WebConfig.
|
||||||
|
public final boolean isLoginRemembered() {
|
||||||
|
return ((Boolean) get(m_remember)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isSecureLoginRequired() {
|
||||||
|
return ((Boolean) get(m_secureLogin)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the defaultLanguage flag.
|
||||||
|
*/
|
||||||
|
public final String getDefaultLanguage() {
|
||||||
|
return ((String) get(m_supportedLanguages)).trim().substring(0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the supportedLanguages as String.
|
||||||
|
*/
|
||||||
|
public final String getSupportedLanguages() {
|
||||||
|
return (String) get(m_supportedLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the supportedLanguages as StringTokenizer.
|
||||||
|
*/
|
||||||
|
public final StringTokenizer getSupportedLanguagesTokenizer() {
|
||||||
|
return new StringTokenizer(this.getSupportedLanguages(), ",", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the languagesIndependentCode as String.
|
||||||
|
*/
|
||||||
|
public final String getLanguagesIndependentCode() {
|
||||||
|
return (String) get(m_languageIndependentCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true, if language lang is part of supported langs
|
||||||
|
*/
|
||||||
|
public final boolean hasLanguage(String lang) {
|
||||||
|
return ((String) get(m_supportedLanguages)).contains(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean languageIndependentItems() {
|
||||||
|
return ((Boolean) get(m_languageIndependentItems)).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.runtime;
|
||||||
|
|
||||||
|
import com.arsdigita.util.parameter.AbstractParameterContext;
|
||||||
|
import com.arsdigita.util.parameter.ErrorList;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbstractConfig is a base class for groups of customizable
|
||||||
|
* configuration {@link com.arsdigita.util.parameter parameters}. A
|
||||||
|
* CCM Developer wishing to add a new group of configuration
|
||||||
|
* parameters to his application will extend this class and provide a
|
||||||
|
* public noargs constructer that registers his parameters with the
|
||||||
|
* superclass. For example:
|
||||||
|
*
|
||||||
|
* <blockquote><pre>
|
||||||
|
* package com.arsdigita.exampleApp;
|
||||||
|
*
|
||||||
|
* public final class ExampleConfig extends AbstractConfig {
|
||||||
|
*
|
||||||
|
* private Parameter m_string = new StringParameter
|
||||||
|
* ("example.string", Parameter.OPTIONAL, "default");
|
||||||
|
* private Parameter m_integer = new IntegerParameter
|
||||||
|
* ("example.integer", Parameter.OPTIONAL, new Integer(0));
|
||||||
|
* private Parameter m_boolean = new BooleanParameter
|
||||||
|
* ("example.boolean", Parameter.OPTIONAL, Boolean.TRUE);
|
||||||
|
*
|
||||||
|
* public ExampleConfig() {
|
||||||
|
* register(m_string);
|
||||||
|
* register(m_integer);
|
||||||
|
* register(m_boolean);
|
||||||
|
* loadInfo();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public String getString() {
|
||||||
|
* return (String) get(m_string);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public int getInteger() {
|
||||||
|
* return ((Integer) get(m_integer)).intValue();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public boolean getBoolean() {
|
||||||
|
* return Boolean.TRUE.equals(get(m_boolean));
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* </pre></blockquote>
|
||||||
|
*
|
||||||
|
* When this pattern is followed, the resulting subclass of abstract
|
||||||
|
* config may be used by developers writing java code to access the
|
||||||
|
* values of customizable configuration parameters in a convenient and
|
||||||
|
* type safe manner. In addition, the very same class is also usable
|
||||||
|
* by the ccm configuration tools to allow customization and
|
||||||
|
* validation of the new parameters.
|
||||||
|
*
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public abstract class AbstractConfig extends AbstractParameterContext {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(AbstractConfig.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for subclasses.
|
||||||
|
*/
|
||||||
|
protected AbstractConfig() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads this AbstractConfig object with values from the default
|
||||||
|
* configuration registry. Any errors encountered during
|
||||||
|
* unmarshaling and loading of configuration values are added to
|
||||||
|
* the <code>errors</code> ErrorList. This method should not be
|
||||||
|
* called from the constructor of a config object since the ccm
|
||||||
|
* configuration tools need to be able to construct empty config
|
||||||
|
* objects.
|
||||||
|
*
|
||||||
|
* @param errors The ErrorList used to record errors during
|
||||||
|
* unmarshaling and loading.
|
||||||
|
*
|
||||||
|
* @see ConfigRegistry
|
||||||
|
*/
|
||||||
|
public final void load(ErrorList errors) {
|
||||||
|
ConfigRegistry reg = new ConfigRegistry();
|
||||||
|
reg.load(this, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the {@link #load(ErrorList)} method with a new and
|
||||||
|
* empty ErrorList for accumulating errors, and returns that
|
||||||
|
* ErrorList. This method can be used in combination with the
|
||||||
|
* {@link ErrorList#check()} method to load and assert that this
|
||||||
|
* configuration object is valid in one simple idiom. For example:
|
||||||
|
*
|
||||||
|
* <blockquote><pre>
|
||||||
|
* ExampleConfig conf = new ExampleConfig();
|
||||||
|
* conf.load().check();
|
||||||
|
* ...
|
||||||
|
* </pre></blockquote>
|
||||||
|
*
|
||||||
|
* @return Errors that may have been encountered during
|
||||||
|
* configuration loading.
|
||||||
|
*
|
||||||
|
* @see #load(ErrorList)
|
||||||
|
*/
|
||||||
|
public final ErrorList load() {
|
||||||
|
ErrorList errs = new ErrorList();
|
||||||
|
load(errs);
|
||||||
|
return errs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use @{link #load()} instead.
|
||||||
|
*/
|
||||||
|
public final ErrorList load(final String resource) {
|
||||||
|
return load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use @{link #load()} instead.
|
||||||
|
*/
|
||||||
|
public final ErrorList require(final String resource) {
|
||||||
|
return load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat Inc. All Rights Reserved.
|
||||||
|
* Copyright (C) 2009 Peter Boy (pb@zes.uni-bremen.de) 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.runtime;
|
||||||
|
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>CCMResourceManager Runtime environment repository object, stores essential
|
||||||
|
* properties of the runtime environment and provides them on request.</p>
|
||||||
|
*
|
||||||
|
* <p>Currently, is is limited to the </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>base directory of the running webapp</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>It provides public methods to make the properties available.</p>
|
||||||
|
*
|
||||||
|
* <p>The singleton is initialised</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>either during startup of the container (called by
|
||||||
|
* @see com.arsdigita.web.CCMApplicationContextListener (must be configured in
|
||||||
|
* web.xml)</li>
|
||||||
|
* <li>or by the command line system at the beginning of the processing (esp.
|
||||||
|
* package @see com.arsdigita.packaging.Mastertool).</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>Currently as a fall back mechanism the environmant Variable CCM_HOME is
|
||||||
|
* evaluated and used a last resort, if no initialisation has been done when
|
||||||
|
* a getter is first called.</p>
|
||||||
|
*
|
||||||
|
* <p>It is essential for the proper working of CCM that CCMResourceManager is
|
||||||
|
* initialised before any operation starts, as it is the case with the Startup
|
||||||
|
* class of the runtime package, which is responsible for organising database
|
||||||
|
* access.</p>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p><b>Subject to change!</b></p>
|
||||||
|
*
|
||||||
|
* A similiar task is performed by com.arsdigita.util.ResourceManager
|
||||||
|
*
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* rewritten by
|
||||||
|
* @author pboy <pboy@barkhof.uni-bremen.de>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class CCMResourceManager {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(CCMResourceManager.class);
|
||||||
|
|
||||||
|
private static CCMResourceManager s_ccm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full Pathname of the application base directory
|
||||||
|
* (document root in apache terminology)
|
||||||
|
*/
|
||||||
|
private static File m_baseDir;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Location of the registry in the applications directory tree
|
||||||
|
* as offset from the base directory
|
||||||
|
*/
|
||||||
|
// currently not used, should be refactored as File object for the sake of
|
||||||
|
// operating system independency!
|
||||||
|
// public static final String registryPath = "/WEB-INF/conf/registry";
|
||||||
|
// public static final File registryPath = null; // currently not used, work in progress
|
||||||
|
|
||||||
|
/* ************ Section singleton handlers ***************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the singleton configuration property for the runtime
|
||||||
|
* environment.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static final synchronized void setBaseDirectory(String baseDirName) {
|
||||||
|
if (s_ccm == null) {
|
||||||
|
s_ccm = new CCMResourceManager();
|
||||||
|
s_ccm.storeBaseDir(baseDirName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// baseDir already set, silently discard
|
||||||
|
s_log.info("baseDir already set as " + m_baseDir + ". Discarded.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the singleton configuration property for the runtime
|
||||||
|
* environment.
|
||||||
|
*
|
||||||
|
* @return The <code>RuntimeConfig</code> record; it cannot be null
|
||||||
|
*/
|
||||||
|
public static final synchronized File getBaseDirectory() {
|
||||||
|
if (s_ccm == null) {
|
||||||
|
// should never happen, setBaseDirectory has to be executed first
|
||||||
|
// we try to resolve the problem in fetchBaseDir by search for
|
||||||
|
// a runtime environment variable (the old way).
|
||||||
|
s_ccm = new CCMResourceManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_ccm.fetchBaseDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************ Section singleton handlers END ************** */
|
||||||
|
|
||||||
|
|
||||||
|
/* ************ Constructors Section ************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Following the singleton pattern: Private constructor to prevent other
|
||||||
|
* clients from instantiating the class (and the compiler from generating
|
||||||
|
* a default public constructor).
|
||||||
|
*/
|
||||||
|
private CCMResourceManager() { }
|
||||||
|
|
||||||
|
/* ************ Constructors Section END ************** */
|
||||||
|
|
||||||
|
|
||||||
|
/* ************ Public getter/setter Section *************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the homeDir as URL.
|
||||||
|
*
|
||||||
|
* Note! API changed. @see getHomeDirectory()
|
||||||
|
* <b>May be removed in the future!</b>
|
||||||
|
*
|
||||||
|
* @return Directory location in the servers file system as URL object.
|
||||||
|
*/
|
||||||
|
public static final URL getHomeURL() {
|
||||||
|
try {
|
||||||
|
return CCMResourceManager.getHomeDirectory().toURL();
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new UncheckedWrapperException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the homeDir, which is the location of the servlet server's
|
||||||
|
* servlet container directory in the file system of the server machine,
|
||||||
|
* as File object.
|
||||||
|
*
|
||||||
|
* <b>Note! API changed!</b>
|
||||||
|
*
|
||||||
|
* Originally it is used to determine all file object locations of a
|
||||||
|
* CCM installation, during the installation step as well as
|
||||||
|
* while running the application inside a servlet container. The CCM installation
|
||||||
|
* of a servlet container used to use a non-standard layout. It is based upon a
|
||||||
|
* system wide environment variable CCM_HOME to determine the home directory.
|
||||||
|
*
|
||||||
|
* The dependency from a system wide environment variable prevents a servlet
|
||||||
|
* container to run multiple instances of CCM. In addition to it CCM will
|
||||||
|
* be migrated to be installable in a standard way to a standard container.
|
||||||
|
* Therefore all file locations will be given relative to the applications
|
||||||
|
* directory (the baseDirectory @see m_baseDir).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Method getHomeDirectory() is preserved during the transition phase.
|
||||||
|
* <b>It may be removed in the future!</b> Or it may be moved to
|
||||||
|
* c.ad.packaging for assistence of the installation step only.
|
||||||
|
*
|
||||||
|
* MODIFIED:
|
||||||
|
* CCM_HOME is now interpreted as the path to the applications base
|
||||||
|
* directory (web application context).
|
||||||
|
*
|
||||||
|
* @return Directory location in the servers file system as File object.
|
||||||
|
*/
|
||||||
|
static final File getHomeDirectory() {
|
||||||
|
|
||||||
|
String home = System.getProperty("ccm.home");
|
||||||
|
|
||||||
|
if (home == null) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("The ccm.home system property is null or not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a guess, wether it is old style (i.e. referring to the containers
|
||||||
|
// base directory and therefor does not contain the webapps part) or
|
||||||
|
// new style referring to the apps base directory (and therefor containing
|
||||||
|
// the webapps part)
|
||||||
|
if (home.indexOf("webapps") > 0 ){
|
||||||
|
// should be new style
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// presumably old style, add path to standard context name
|
||||||
|
home += "/webapps/ROOT";
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(home);
|
||||||
|
|
||||||
|
// No need to require that home exists (indeed, during install it will not).
|
||||||
|
// Should be created by invoking method if not.
|
||||||
|
// if (!file.exists()) {
|
||||||
|
// throw new IllegalStateException
|
||||||
|
// ("The file given in the ccm.home system property " +
|
||||||
|
// "does not exist");
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!file.isDirectory()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("The file: " + home + " given in the ccm.home system property"
|
||||||
|
+ " is not a directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide the configDirectory as URL.
|
||||||
|
*
|
||||||
|
* @see getConfigDirectory() for details.
|
||||||
|
*
|
||||||
|
* <b>Note! API changed!</b>
|
||||||
|
*
|
||||||
|
* @return Directory location in the servers file system as URL object.
|
||||||
|
*/
|
||||||
|
public static final URL getConfigURL() {
|
||||||
|
try {
|
||||||
|
return CCMResourceManager.getConfigDirectory().toURL();
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new UncheckedWrapperException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the configDir, which is the location of the configuration
|
||||||
|
* database root (registry) in the file system tree of the server machine,
|
||||||
|
* as File object.
|
||||||
|
|
||||||
|
*
|
||||||
|
* @return Directory location in the servers file system as File object.
|
||||||
|
*/
|
||||||
|
public static final File getConfigDirectory() {
|
||||||
|
|
||||||
|
// Keep this in sync with informational attribut @see registryPath !
|
||||||
|
File confdir = new File(new File(new File(CCMResourceManager.getBaseDirectory(),
|
||||||
|
"WEB-INF"),"conf"), "registry");
|
||||||
|
|
||||||
|
if (!confdir.exists()) {
|
||||||
|
if (!confdir.mkdirs()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Could not create configuration directory: " + confdir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!confdir.isDirectory()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Configuration directory value is not a directory: " + confdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return confdir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getWorkDirectory retrieves and eventually creates an internal directory
|
||||||
|
* in the servlet container for temporary files (work files), where subsystems
|
||||||
|
* may create subdirectories for internal use (e.g. Lucene search enginge or
|
||||||
|
* the PublishToFile machinery).
|
||||||
|
*
|
||||||
|
* The containers work file directory could be used as well, but may be
|
||||||
|
* inappropriate in case of confidential data.
|
||||||
|
*
|
||||||
|
* @return Directory location in the servers file system as File object.
|
||||||
|
*/
|
||||||
|
public static final File getWorkDirectory() {
|
||||||
|
File file = new File(new File(CCMResourceManager.getBaseDirectory(),
|
||||||
|
"WEB-INF"),"work");
|
||||||
|
if (!file.exists()) {
|
||||||
|
if (!file.mkdirs()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Could not create work directory: " + file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!file.isDirectory()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Work directory value is not a directory: " + file);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************ Public getter/setter Section END *************** */
|
||||||
|
|
||||||
|
|
||||||
|
/* ************ Private Worker Section *************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the passed in String as File object.
|
||||||
|
*
|
||||||
|
* @param baseDirName String containing the path, must not be null
|
||||||
|
*/
|
||||||
|
private final void storeBaseDir(String baseDirName) {
|
||||||
|
|
||||||
|
s_log.debug("storeBaseDir: BaseDir name is given as " + baseDirName );
|
||||||
|
m_baseDir = new File(baseDirName);
|
||||||
|
|
||||||
|
// eventually: check if dir exists, create it if not.
|
||||||
|
if (!m_baseDir.exists()) {
|
||||||
|
if (!m_baseDir.mkdirs()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Could not create base directory: " + m_baseDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m_baseDir.isDirectory()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Base directory value is not a directory: " + m_baseDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the stored BaseDir File object.
|
||||||
|
*
|
||||||
|
* @return Base directory location in the servers file system as File object.
|
||||||
|
*/
|
||||||
|
private final File fetchBaseDir() {
|
||||||
|
|
||||||
|
if (m_baseDir == null) {
|
||||||
|
// should never happen, but we try to cope with it anyway by
|
||||||
|
// falling back to getHomeDirectory() and the system wide
|
||||||
|
// environment variable.
|
||||||
|
// During transition phase only! Must be removed when the new
|
||||||
|
// standard compliant installation method is fully in place
|
||||||
|
// MODIFIED
|
||||||
|
// HomeDirectory now specifies the applications context dir.
|
||||||
|
m_baseDir = CCMResourceManager.getHomeDirectory();
|
||||||
|
|
||||||
|
// eventually: check if dir exists, create it if not.
|
||||||
|
if (!m_baseDir.exists()) {
|
||||||
|
if (!m_baseDir.mkdirs()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Could not create base directory: " + m_baseDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m_baseDir.isDirectory()) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Base directory value is not a directory: " + m_baseDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_baseDir;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************ Private Worker Section END *************** */
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,348 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.runtime;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Classes;
|
||||||
|
import com.arsdigita.util.JavaPropertyReader;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.util.parameter.ErrorList;
|
||||||
|
import com.arsdigita.util.parameter.ParameterContext;
|
||||||
|
import com.arsdigita.util.parameter.ParameterReader;
|
||||||
|
import com.arsdigita.xml.XML;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ConfigRegistry class maps between config classes (subclasses of
|
||||||
|
* {@link com.arsdigita.runtime.AbstractConfig}), and a location used
|
||||||
|
* for persisting the values in a config class.
|
||||||
|
*
|
||||||
|
* The ConfigRegistry also stores the set of configured packages for a
|
||||||
|
* particular CCMResourceManager instance.
|
||||||
|
* Additionally it stores a list of URLs for parent configurations that are
|
||||||
|
* used for defaulting values not present in the local configuration.
|
||||||
|
* This mapping is maintained and extended by CCMResourceManager developers through
|
||||||
|
* the use of an XML configuration file placed in the src tree for a
|
||||||
|
* particular package. If a particular package is configured, the
|
||||||
|
* ConfigRegistry class will look in the classpath for a registry
|
||||||
|
* configuration file named <i>package-key</i>.config, and parse the
|
||||||
|
* file according to the following specification:
|
||||||
|
*
|
||||||
|
* <blockquite><pre>
|
||||||
|
* <?xml version="1.0" encoding="utf-8"?>
|
||||||
|
* <registry>
|
||||||
|
* ...
|
||||||
|
* <config class="CLASSNAME"
|
||||||
|
* storage="FILENAME"/>
|
||||||
|
* ...
|
||||||
|
* </registry>
|
||||||
|
* </pre></blockquite>
|
||||||
|
*
|
||||||
|
* The mappings stored by this ConfigRegistry will then be extended to include
|
||||||
|
* the classes and storage locations specified in the configuration file. These
|
||||||
|
* mappings are then used by the ConfigRegistry instance to load config objects.
|
||||||
|
*
|
||||||
|
* @author Rafael H. Schloming <rhs@mit.edu>
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @version $Id$
|
||||||
|
**/
|
||||||
|
public class ConfigRegistry {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(ConfigRegistry.class);
|
||||||
|
/**
|
||||||
|
* Base url for registry location(s).
|
||||||
|
* (i.e. $CATALINA_HOME/webapps/$context/WEB-INF/conf/registry in a
|
||||||
|
* standard installation)
|
||||||
|
*/
|
||||||
|
private URL m_url;
|
||||||
|
private ClassLoader m_loader;
|
||||||
|
private List m_packages = new ArrayList();
|
||||||
|
private List m_contexts = new ArrayList();
|
||||||
|
private Map m_storage = new HashMap();
|
||||||
|
private List m_loaders = new ArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new config registry that will resolve all
|
||||||
|
* locations relative to <code>url</code>, and use
|
||||||
|
* <code>loader</code> when searching the classpath for registry
|
||||||
|
* configuration files.
|
||||||
|
*
|
||||||
|
* @param url The base url for registry locations.
|
||||||
|
* @param loader The ClassLoader to use for retrieving registry
|
||||||
|
* configuration files.
|
||||||
|
**/
|
||||||
|
public ConfigRegistry(URL url, ClassLoader loader) {
|
||||||
|
m_url = url;
|
||||||
|
m_loader = loader;
|
||||||
|
addContext(RegistryConfig.class, "registry.properties");
|
||||||
|
initialize(m_url, new ErrorList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience class which invokes {@link #ConfigRegistry(URL, ClassLoader)}
|
||||||
|
* defaulting the loader to the current context class loader.
|
||||||
|
*
|
||||||
|
* @see Thread#getContextClassLoader()
|
||||||
|
*
|
||||||
|
* @param url The base url for registry locations.
|
||||||
|
*/
|
||||||
|
public ConfigRegistry(URL url) {
|
||||||
|
this(url, Thread.currentThread().getContextClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience class which invokes {@link #ConfigRegistry(URL, ClassLoader)}
|
||||||
|
* defaulting the URL to
|
||||||
|
* <code>new File(System.getProperty("ccm.conf")).toURL()</code>. The value
|
||||||
|
* of the ccm.conf system property may or may not include a trailing slash.
|
||||||
|
*
|
||||||
|
* @param loader The ClassLoader to use when searching for
|
||||||
|
* registry configuration files.
|
||||||
|
*/
|
||||||
|
public ConfigRegistry(ClassLoader loader) {
|
||||||
|
this(CCMResourceManager.getConfigURL(), loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes {@link #ConfigRegistry(URL)} defaulting the URL to <code>new
|
||||||
|
* File(System.getProperty("ccm.conf")).toURL()</code>. The value of the
|
||||||
|
* ccm.conf system property may or may not include a trailing slash.
|
||||||
|
*/
|
||||||
|
public ConfigRegistry() {
|
||||||
|
this(CCMResourceManager.getConfigURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param url Base url for registry location(s).
|
||||||
|
* @param errs Errorlist
|
||||||
|
*/
|
||||||
|
private void initialize(URL url, ErrorList errs) {
|
||||||
|
|
||||||
|
ClassLoader ldr = new URLClassLoader(new URL[]{url}, null);
|
||||||
|
|
||||||
|
RegistryConfig rc = new RegistryConfig();
|
||||||
|
load(rc, errs, ldr);
|
||||||
|
|
||||||
|
String[] packages = rc.getPackages();
|
||||||
|
URL[] parents = rc.getParents();
|
||||||
|
|
||||||
|
for (int i = 0; i < packages.length; i++) {
|
||||||
|
if (!m_packages.contains(packages[i])) {
|
||||||
|
initialize(packages[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = parents.length - 1; i >= 0; i--) {
|
||||||
|
initialize(parents[i], errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_loaders.add(ldr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is <strong>not</strong> supported API.
|
||||||
|
*/
|
||||||
|
public final void initialize(String key) {
|
||||||
|
s_log.debug(String.format("Initalizing for key '%s'", key));
|
||||||
|
if (m_packages.contains(key)) {
|
||||||
|
throw new IllegalArgumentException("already loaded: " + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = m_loader.getResourceAsStream(key + ".config");
|
||||||
|
if (is != null) {
|
||||||
|
try {
|
||||||
|
XML.parse(is, new ConfigRegistryParser());
|
||||||
|
m_packages.add(key);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedWrapperException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of configured packages for this ConfigRegistry.
|
||||||
|
*
|
||||||
|
* @return A list of package keys represented as Strings.
|
||||||
|
**/
|
||||||
|
public List getPackages() {
|
||||||
|
return m_packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of config classes for this ConfigRegistry.
|
||||||
|
*
|
||||||
|
* @return A list of Class objects.
|
||||||
|
**/
|
||||||
|
public List getContexts() {
|
||||||
|
return m_contexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the relative location used to store values for the
|
||||||
|
* given config class.
|
||||||
|
*
|
||||||
|
* @param context a subclass of {@link
|
||||||
|
* com.arsdigita.runtime.AbstractConfig}
|
||||||
|
*
|
||||||
|
* @return the relative storage location for <code>context</code>
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if this ConfigRegistry does
|
||||||
|
* not contain a mapping for <code>context</code>
|
||||||
|
**/
|
||||||
|
public String getStorage(Class context) {
|
||||||
|
if (!m_contexts.contains(context)) {
|
||||||
|
throw new IllegalArgumentException("no such context: " + context
|
||||||
|
+ "; available contexts="
|
||||||
|
+ m_contexts
|
||||||
|
+ "; context->storage map: "
|
||||||
|
+ m_storage);
|
||||||
|
}
|
||||||
|
return (String) m_storage.get(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addContext(Class context, String storage) {
|
||||||
|
s_log.debug(String.format("Adding context '%s', storage '%s'...",
|
||||||
|
context.getName(), storage));
|
||||||
|
m_contexts.add(context);
|
||||||
|
m_storage.put(context, storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this ConfigRegistry contains a mapping for
|
||||||
|
* <code>context</code>
|
||||||
|
*
|
||||||
|
* @param context a subclass of {@link
|
||||||
|
* com.arsdigita.runtime.AbstractConfig}
|
||||||
|
*
|
||||||
|
* @return true if this ConfigRegistry contains a mapping for
|
||||||
|
* <code>context</code>
|
||||||
|
**/
|
||||||
|
public boolean isConfigured(Class context) {
|
||||||
|
return m_contexts.contains(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given config object from the correct location based
|
||||||
|
* on its class. Defaults all values based on the value of the
|
||||||
|
* <code>waf.config.parents</code> parameter. Any errors
|
||||||
|
* encountered during loading are reported in the given ErrorList.
|
||||||
|
*
|
||||||
|
* @param ctx the config object to load
|
||||||
|
* @param errs used to accumulate errors during loading
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if this ConfigRegistry does
|
||||||
|
* not contain a mapping for <code>ctx.getClass()</code>
|
||||||
|
**/
|
||||||
|
public void load(ParameterContext ctx, ErrorList errs) {
|
||||||
|
for (Iterator it = m_loaders.iterator(); it.hasNext();) {
|
||||||
|
ClassLoader ldr = (ClassLoader) it.next();
|
||||||
|
load(ctx, errs, ldr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches through this ConfigRegistry and its parents for the
|
||||||
|
* given resource. If it is not found it is also searched for in
|
||||||
|
* the classpath specified by the loader passed to this
|
||||||
|
* ConfigRegistry on construction. This may be used to load
|
||||||
|
* configuration information that is not stored in a config
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param resource the path to the resource
|
||||||
|
*
|
||||||
|
* @return an input stream containing the contents of the resource
|
||||||
|
* or null if the resource is not found
|
||||||
|
*/
|
||||||
|
public InputStream load(String resource) {
|
||||||
|
for (int i = m_loaders.size() - 1; i >= 0; i--) {
|
||||||
|
ClassLoader ldr = (ClassLoader) m_loaders.get(i);
|
||||||
|
InputStream is = ldr.getResourceAsStream(resource);
|
||||||
|
if (is != null) {
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_loader.getResourceAsStream(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load(ParameterContext ctx, ErrorList errs, ClassLoader ldr) {
|
||||||
|
Properties props = getProperties(ldr, getStorage(ctx.getClass()));
|
||||||
|
ParameterReader reader = new JavaPropertyReader(props);
|
||||||
|
ctx.load(reader, errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties getProperties(ClassLoader ldr, String resource) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
InputStream is = ldr.getResourceAsStream(resource);
|
||||||
|
if (is != null) {
|
||||||
|
try {
|
||||||
|
props.load(is);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedWrapperException(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedWrapperException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ConfigRegistryParser extends DefaultHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qn,
|
||||||
|
Attributes attrs) {
|
||||||
|
if (localName.equals("config")) {
|
||||||
|
String klass = attrs.getValue(uri, "class");
|
||||||
|
String storage = attrs.getValue(uri, "storage");
|
||||||
|
// XXX: Is there a better way to handle errors that
|
||||||
|
// includes line number information?
|
||||||
|
if ((klass == null) || (storage == null)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"class and storage attributes are required");
|
||||||
|
}
|
||||||
|
|
||||||
|
Class context = Classes.loadClass(klass);
|
||||||
|
addContext(context, storage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.runtime;
|
||||||
|
|
||||||
|
// import com.arsdigita.runtime.AbstractConfig;
|
||||||
|
import com.arsdigita.util.StringUtils;
|
||||||
|
import com.arsdigita.util.parameter.ErrorList;
|
||||||
|
import com.arsdigita.util.parameter.Parameter;
|
||||||
|
import com.arsdigita.util.parameter.ParameterError;
|
||||||
|
import com.arsdigita.util.parameter.StringParameter;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A config class used by the registry itself.
|
||||||
|
*
|
||||||
|
* Contains the parameters:
|
||||||
|
* waf.config.packages: comma separated package-key list of installed packages
|
||||||
|
* waf.config.parents :
|
||||||
|
*
|
||||||
|
* @author Rafael H. Schloming <rhs@mit.edu>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class RegistryConfig extends AbstractConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to unmarshal parameter values.
|
||||||
|
* @param str A String of comma separated values
|
||||||
|
* @return StringArray of the values
|
||||||
|
*/
|
||||||
|
private static String[] array(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return StringUtils.split(str, ',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of installed packages.
|
||||||
|
*
|
||||||
|
* Provided as a comma separated package-key list of installed packages.
|
||||||
|
* The parameter overwrites the default marshal and unmarshal methods to
|
||||||
|
* allow the String parameter to hold a list of values.
|
||||||
|
*
|
||||||
|
* TODO: Replace the type String parameter by StringArray parameter which
|
||||||
|
* provides exactly the required functionality (doesn't it?).
|
||||||
|
*/
|
||||||
|
private Parameter m_packages = new StringParameter
|
||||||
|
("waf.config.packages", Parameter.OPTIONAL, new String[0]) {
|
||||||
|
@Override
|
||||||
|
protected Object unmarshal(String value, ErrorList errs) {
|
||||||
|
return array(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String marshal(Object obj) {
|
||||||
|
return StringUtils.join((String[]) obj, ',');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of parameter values, purpose currently unkown.
|
||||||
|
*
|
||||||
|
* The parameter overwrites the default marshal and unmarshal methods to
|
||||||
|
* allow the String parameter to hold a list of values.
|
||||||
|
*/
|
||||||
|
private Parameter m_parents = new StringParameter
|
||||||
|
("waf.config.parents", Parameter.OPTIONAL, new URL[0]) {
|
||||||
|
@Override
|
||||||
|
protected Object unmarshal(String value, ErrorList errs) {
|
||||||
|
String[] strs = array(value);
|
||||||
|
URL[] result = new URL[strs.length];
|
||||||
|
for (int i = 0; i < result.length; i++) {
|
||||||
|
try {
|
||||||
|
result[i] = new URL(strs[i]);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
errs.add(new ParameterError(this, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!errs.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String marshal(Object obj) {
|
||||||
|
URL[] urls = (URL[]) obj;
|
||||||
|
String[] strs = new String[urls.length];
|
||||||
|
for (int i = 0; i < strs.length; i++) {
|
||||||
|
strs[i] = urls[i].toExternalForm();
|
||||||
|
}
|
||||||
|
return StringUtils.join(strs, ',');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new and empty config object.
|
||||||
|
*/
|
||||||
|
public RegistryConfig() {
|
||||||
|
register(m_packages);
|
||||||
|
register(m_parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the waf.config.packages parameter.
|
||||||
|
*
|
||||||
|
* @return the value of the waf.config.packages parameter
|
||||||
|
*/
|
||||||
|
public String[] getPackages() {
|
||||||
|
return (String[]) get(m_packages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the waf.config.parents parameter.
|
||||||
|
*
|
||||||
|
* @return the value of the waf.config.parents parameter
|
||||||
|
*/
|
||||||
|
public URL[] getParents() {
|
||||||
|
return (URL[]) get(m_parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,716 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility functions for assertions.
|
||||||
|
*
|
||||||
|
* <p>The static methods in this class provide a standard way of
|
||||||
|
* asserting certain conditions.</p>
|
||||||
|
*
|
||||||
|
* <p>Though it is not right now, this class <em>should</em> be final.
|
||||||
|
* Do not subclass it. In a future revision of this software, this
|
||||||
|
* class will be made final.</p>
|
||||||
|
*
|
||||||
|
* @author David Lutterkort <dlutter@redhat.com>
|
||||||
|
* @author Uday Mathur
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class Assert {
|
||||||
|
|
||||||
|
/** Class specific logger instance. */
|
||||||
|
private static final Logger s_log = Logger.getLogger(Assert.class);
|
||||||
|
|
||||||
|
private static final String DEFAULT_MESSAGE = "Assertion failure";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration by a system wide / servlet container wide environment
|
||||||
|
* variable is evil and no longer supported API.
|
||||||
|
* Currently Assertion is set alway on. The non-deprecated methods of this
|
||||||
|
* class don't check for isEnabled anyway. So there is no effect.
|
||||||
|
* If configurability is really needed, configuration by config registry
|
||||||
|
* during system setup (eg. @link com.arsdigita.runtime.CCMResourceManager)
|
||||||
|
* has to be implemented
|
||||||
|
*/
|
||||||
|
private static boolean s_enabled = true;
|
||||||
|
// private static boolean s_enabled;
|
||||||
|
//
|
||||||
|
// static {
|
||||||
|
// final String enabled = System.getProperty
|
||||||
|
// (Assert.class.getName() + ".enabled");
|
||||||
|
//
|
||||||
|
// if (enabled == null) {
|
||||||
|
// //s_enabled = false;
|
||||||
|
// //default value is true
|
||||||
|
// s_enabled = true;
|
||||||
|
// } else {
|
||||||
|
// // s_enabled = enabled.equals("true");
|
||||||
|
// // Test: set to true anyway.
|
||||||
|
// // TODO: read from config registry, any dependency from a
|
||||||
|
// // environment variable is deprecated!
|
||||||
|
// s_enabled = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether asserts are turned on. Use this to wrap code
|
||||||
|
* that should be optimized away if assertions are disabled.
|
||||||
|
*
|
||||||
|
* By default, assertions are disabled
|
||||||
|
*/
|
||||||
|
public static final boolean isEnabled() {
|
||||||
|
return s_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final void setEnabled(final boolean enabled) {
|
||||||
|
s_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an error.
|
||||||
|
*
|
||||||
|
* @param message A <code>String</code> describing the failure
|
||||||
|
* condition
|
||||||
|
* @throws AssertionError
|
||||||
|
*/
|
||||||
|
public static final void fail(final String message) {
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an error.
|
||||||
|
*
|
||||||
|
* @throws AssertionError
|
||||||
|
*/
|
||||||
|
public static final void fail() {
|
||||||
|
error(DEFAULT_MESSAGE);
|
||||||
|
|
||||||
|
throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is true and throws an
|
||||||
|
* error with message <code>message</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @param message An error message
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
*/
|
||||||
|
public static final void isTrue(final boolean condition,
|
||||||
|
final String message) {
|
||||||
|
if (!condition) {
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is true and throws an
|
||||||
|
* error with message <code>message</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @param message An error message
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
* @deprecated use Assert.isTrue(condition, message) instead
|
||||||
|
* (we will follow the standard naming scheme)
|
||||||
|
*/
|
||||||
|
public static final void truth(final boolean condition,
|
||||||
|
final String message) {
|
||||||
|
Assert.isTrue(condition, message);
|
||||||
|
|
||||||
|
|
||||||
|
// if (!condition) {
|
||||||
|
// error(message);
|
||||||
|
//
|
||||||
|
// throw new AssertionError(message);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is true and throws an
|
||||||
|
* error with message <code>message</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
*/
|
||||||
|
public static final void isTrue(final boolean condition) {
|
||||||
|
if (!condition) {
|
||||||
|
error(DEFAULT_MESSAGE);
|
||||||
|
|
||||||
|
throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is true and throws an
|
||||||
|
* error with message <code>message</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
* @deprecated use Assert.isTrue(final boolean condition) instead
|
||||||
|
* (we will follow the standard naming scheme)
|
||||||
|
*/
|
||||||
|
public static final void truth(final boolean condition) {
|
||||||
|
Assert.isTrue(condition);
|
||||||
|
|
||||||
|
// if (!condition) {
|
||||||
|
// error(DEFAULT_MESSAGE);
|
||||||
|
//
|
||||||
|
// throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is false and throws an
|
||||||
|
* error if the condition is true.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @param message An error message
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
*/
|
||||||
|
public static final void isFalse(final boolean condition,
|
||||||
|
final String message) {
|
||||||
|
if (condition) {
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is false and throws an
|
||||||
|
* error if the condition is true.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
*/
|
||||||
|
public static final void isFalse(final boolean condition) {
|
||||||
|
if (condition) {
|
||||||
|
error(DEFAULT_MESSAGE);
|
||||||
|
|
||||||
|
throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an object is not null.
|
||||||
|
*
|
||||||
|
* @param object The object that must not be null
|
||||||
|
* @param clacc The <code>Class</code> of parameter
|
||||||
|
* <code>object</code>
|
||||||
|
* @throws AssertionError if the object is null
|
||||||
|
*/
|
||||||
|
public static void exists(final Object object,
|
||||||
|
final Class clacc) {
|
||||||
|
if (object == null) {
|
||||||
|
final String message = clacc.getName() + " is null";
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an object is not null.
|
||||||
|
*
|
||||||
|
* @param object The <code>Object</code> that must not be null
|
||||||
|
* @param label A text to describe <code>Object</code>
|
||||||
|
*
|
||||||
|
* @throws AssertionError if the object is null
|
||||||
|
*/
|
||||||
|
public static void exists(final Object object,
|
||||||
|
final String label) {
|
||||||
|
if (object == null) {
|
||||||
|
final String message =
|
||||||
|
label != null && label.trim().length() > 0
|
||||||
|
? "Value of " + label + " is null."
|
||||||
|
: DEFAULT_MESSAGE ;
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an object is not null.
|
||||||
|
*
|
||||||
|
* @param object The object that must not be null
|
||||||
|
* @throws AssertionError if the object is null
|
||||||
|
*/
|
||||||
|
public static final void exists(final Object object) {
|
||||||
|
if (object == null) {
|
||||||
|
error(DEFAULT_MESSAGE);
|
||||||
|
|
||||||
|
throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that <code>Lockable</code> is locked and throws an
|
||||||
|
* error if it is not.
|
||||||
|
*
|
||||||
|
* @param lockable The object that must be locked
|
||||||
|
* @see com.arsdigita.util.Lockable
|
||||||
|
*/
|
||||||
|
public static final void isLocked(final Lockable lockable) {
|
||||||
|
if (lockable != null && !lockable.isLocked()) {
|
||||||
|
final String message = "Illegal access: " + lockable +
|
||||||
|
" is not locked";
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that <code>lockable</code> is <em>not</em> locked and
|
||||||
|
* throws an error if it is.
|
||||||
|
*
|
||||||
|
* @param lockable The object that must not be locked
|
||||||
|
* @see com.arsdigita.util.Lockable
|
||||||
|
*/
|
||||||
|
public static final void isUnlocked(final Lockable lockable) {
|
||||||
|
if (lockable != null && lockable.isLocked()) {
|
||||||
|
final String message = "Illegal access: " + lockable + " is locked.";
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that two values are equal (according to their equals
|
||||||
|
* method, unless <code>value1</code> is null, then according to
|
||||||
|
* <code>==</code>).
|
||||||
|
*
|
||||||
|
* @param value1 The first value to be compared
|
||||||
|
* @param value2 The second
|
||||||
|
* @throws AssertionError if the arguments are unequal
|
||||||
|
*/
|
||||||
|
public static final void isEqual(final Object value1,
|
||||||
|
final Object value2) {
|
||||||
|
if (value1 == null) {
|
||||||
|
if (value1 != value2) {
|
||||||
|
final String message = value1 + " does not equal " + value2;
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!value1.equals(value2)) {
|
||||||
|
final String message = value1 + " does not equal " + value2;
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that two values are equal (according to their equals
|
||||||
|
* method, unless <code>value1</code> is null, then according to
|
||||||
|
* <code>==</code>).
|
||||||
|
*
|
||||||
|
* @param value1 The first value to be compared
|
||||||
|
* @param value2 The second
|
||||||
|
* @throws AssertionError if the arguments are unequal
|
||||||
|
*/
|
||||||
|
public static final void isEqual(final Object value1,
|
||||||
|
final Object value2,
|
||||||
|
final String message) {
|
||||||
|
if (value1 == null) {
|
||||||
|
if (value1 != value2) {
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!value1.equals(value2)) {
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that two values are not equal (according to their
|
||||||
|
* equals method, unless <code>value1</code> is null, then
|
||||||
|
* according to <code>==</code>).
|
||||||
|
*
|
||||||
|
* @param value1 The first value to be compared
|
||||||
|
* @param value2 The second
|
||||||
|
* @throws AssertionError if the arguments are isNotEqual
|
||||||
|
*/
|
||||||
|
public static final void isNotEqual(final Object value1,
|
||||||
|
final Object value2) {
|
||||||
|
if (value1 == null) {
|
||||||
|
if (value1 == value2) {
|
||||||
|
final String message = value1 + " equals " + value2;
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value1.equals(value2)) {
|
||||||
|
final String message = value1 + " equals " + value2;
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility methods
|
||||||
|
|
||||||
|
private static void error(final String message) {
|
||||||
|
// Log the stack trace too, since we still have code that
|
||||||
|
// manages to hide exceptions.
|
||||||
|
s_log.error(message, new AssertionError(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// The methods below are all deprecated. //
|
||||||
|
// //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated in favor of {@link #isEnabled()}
|
||||||
|
*
|
||||||
|
* pboy Jan.09: not used by any package in trunk
|
||||||
|
*/
|
||||||
|
// public static final boolean ASSERT_ON = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates state of the ASSERT_ON flag.
|
||||||
|
*
|
||||||
|
* pboy Jan.09: not used by any package in trunk
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #isEnabled()} instead
|
||||||
|
*/
|
||||||
|
// public static final boolean isAssertOn() {
|
||||||
|
// return isEnabled();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Tells whether asserts are turned on. Use this to wrap code
|
||||||
|
// * that should be optimized away if asserts are disabled.
|
||||||
|
// *
|
||||||
|
// * @deprecated Use {@link #isEnabled()} instead
|
||||||
|
// */
|
||||||
|
// public static final boolean isAssertEnabled() {
|
||||||
|
// return isEnabled();
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that an arbitrary condition is true, and throw an
|
||||||
|
* exception if the condition is false.
|
||||||
|
*
|
||||||
|
* @param cond condition to assert
|
||||||
|
* @throws java.lang.IllegalStateException condition was false
|
||||||
|
* @deprecated Use {@link #truth(boolean, String)} instead
|
||||||
|
*/
|
||||||
|
/* public static final void isTrue(boolean cond) {
|
||||||
|
isTrue(cond, "");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Assert that an arbitrary condition is true, and throw an
|
||||||
|
* exception with message <code>msg</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param cond condition to assert
|
||||||
|
* @param msg failure message
|
||||||
|
* @throws java.lang.IllegalStateException condition was false
|
||||||
|
* @deprecated Use {@link #truth(boolean,String)} instead
|
||||||
|
*/
|
||||||
|
/* public static final void assertTrue(boolean cond, String msg) {
|
||||||
|
if (!cond) {
|
||||||
|
error(msg);
|
||||||
|
|
||||||
|
throw new IllegalStateException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is true and throws an
|
||||||
|
* error with message <code>message</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @param message An error message
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
* @deprecated use Assert.isTrue(condition, message) instead
|
||||||
|
* (we will follow the standard naming scheme)
|
||||||
|
*/
|
||||||
|
/* public static final void truth(final boolean condition,
|
||||||
|
final String message) {
|
||||||
|
Assert.isTrue(condition, message);
|
||||||
|
|
||||||
|
// if (!condition) {
|
||||||
|
// error(message);
|
||||||
|
//
|
||||||
|
// throw new AssertionError(message);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is true and throws an
|
||||||
|
* error with message <code>message</code> if the condition is
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
* @deprecated use Assert.isTrue(final boolean condition) instead
|
||||||
|
* (we will follow the standard naming scheme)
|
||||||
|
*/
|
||||||
|
/* public static final void truth(final boolean condition) {
|
||||||
|
Assert.isTrue(condition);
|
||||||
|
|
||||||
|
// if (!condition) {
|
||||||
|
// error(DEFAULT_MESSAGE);
|
||||||
|
//
|
||||||
|
// throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is false and throws an
|
||||||
|
* error if the condition is true.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @param message An error message
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
*/
|
||||||
|
/* public static final void falsity(final boolean condition,
|
||||||
|
final String message) {
|
||||||
|
if (condition) {
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that an arbitrary condition is false and throws an
|
||||||
|
* error if the condition is true.
|
||||||
|
*
|
||||||
|
* @param condition The condition asserted
|
||||||
|
* @throws AssertionError if the condition is false
|
||||||
|
*/
|
||||||
|
/* public static final void falsity(final boolean condition) {
|
||||||
|
if (condition) {
|
||||||
|
error(DEFAULT_MESSAGE);
|
||||||
|
|
||||||
|
throw new AssertionError(DEFAULT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Verify that a parameter is not null and throw a runtime
|
||||||
|
* exception if so.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #exists(Object)} instead
|
||||||
|
*/
|
||||||
|
/* public static final void assertNotNull(Object o) {
|
||||||
|
assertNotNull(o, "");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Verify that a parameter is not null and throw a runtime
|
||||||
|
* exception if so.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #exists(Object,String)} instead
|
||||||
|
*/
|
||||||
|
/* public static final void assertNotNull(Object o, String label) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
isTrue(o != null, "Value of " + label + " is null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// /**
|
||||||
|
// * Verify that a string is not empty and throw a runtime exception
|
||||||
|
// * if so. A parameter is considered empty if it is null, or if it
|
||||||
|
// * does not contain any characters that are non-whitespace.
|
||||||
|
// *
|
||||||
|
// * @deprecated with no replacement
|
||||||
|
// */
|
||||||
|
// public static final void assertNotEmpty(String s) {
|
||||||
|
// assertNotEmpty(s, "");
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that a string is not empty and throw a runtime exception
|
||||||
|
* if so. A parameter is considered empty if it is null, or if it
|
||||||
|
* does not contain any characters that are non-whitespace.
|
||||||
|
*
|
||||||
|
* @deprecated with no replacement
|
||||||
|
*/
|
||||||
|
public static final void assertNotEmpty(String s, String label) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
isTrue(s != null && s.trim().length() > 0,
|
||||||
|
"Value of " + label + " is empty.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that two values are equal (according to their equals method,
|
||||||
|
* unless expected is null, then according to ==).
|
||||||
|
*
|
||||||
|
* @param expected Expected value.
|
||||||
|
* @param actual Actual value.
|
||||||
|
* @throws java.lang.IllegalStateException condition was false
|
||||||
|
* @deprecated Use {@link #isEqual(Object,Object)} instead
|
||||||
|
*/
|
||||||
|
public static final void assertEquals(Object expected, Object actual) {
|
||||||
|
assertEquals(expected, actual, "expected", "actual");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that two values are equal (according to their equals method,
|
||||||
|
* unless expected is null, then according to ==).
|
||||||
|
*
|
||||||
|
* @param expected Expected value.
|
||||||
|
* @param actual Actual value.
|
||||||
|
* @param expectedLabel Label for first (generally expected) value.
|
||||||
|
* @param actualLabel Label for second (generally actual) value.
|
||||||
|
* @throws java.lang.IllegalStateException condition was false
|
||||||
|
*/
|
||||||
|
public static final void assertEquals(Object expected, Object actual,
|
||||||
|
String expectedLabel,
|
||||||
|
String actualLabel) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
if (expected == null) {
|
||||||
|
isTrue(expected == actual,
|
||||||
|
"Values not equal, " +
|
||||||
|
expectedLabel + " '" + expected + "', " +
|
||||||
|
actualLabel + " '" + actual + "'");
|
||||||
|
} else {
|
||||||
|
isTrue(expected.equals(actual),
|
||||||
|
"Values not equal, " +
|
||||||
|
expectedLabel + " '" + expected + "', " +
|
||||||
|
actualLabel + " '" + actual + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that two values are equal.
|
||||||
|
*
|
||||||
|
* @param expected Expected value.
|
||||||
|
* @param actual Actual value.
|
||||||
|
* @throws java.lang.IllegalStateException condition was false
|
||||||
|
* @deprecated Use {@link #truth(boolean, String)} instead
|
||||||
|
*/
|
||||||
|
public static final void assertEquals(int expected, int actual) {
|
||||||
|
assertEquals(expected, actual, "expected", "actual");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that two values are equal.
|
||||||
|
*
|
||||||
|
* @param expected Expected value.
|
||||||
|
* @param actual Actual value.
|
||||||
|
* @param expectedLabel Label for first (generally expected) value.
|
||||||
|
* @param actualLabel Label for second (generally actual) value.
|
||||||
|
* @throws java.lang.IllegalStateException condition was false
|
||||||
|
* @deprecated Use {@link #truth(boolean, String)} instead
|
||||||
|
*/
|
||||||
|
public static final void assertEquals(int expected, int actual,
|
||||||
|
String expectedLabel,
|
||||||
|
String actualLabel) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
isTrue(expected == actual,
|
||||||
|
"Values not equal, " +
|
||||||
|
expectedLabel + " '" + expected + "', " +
|
||||||
|
actualLabel + " '" + actual + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that the model is locked and throw a runtime exception
|
||||||
|
* if it is not locked.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #isLocked(Lockable)} instead
|
||||||
|
*/
|
||||||
|
/* public static void assertLocked(Lockable l) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
isTrue(l.isLocked(),
|
||||||
|
"Illegal access to an unlocked " +
|
||||||
|
l.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Verify that the model is locked and throw a runtime exception
|
||||||
|
* if it is locked.
|
||||||
|
*
|
||||||
|
// * @deprecated Use {@link #isUnlocked(Lockable)} instead
|
||||||
|
*/
|
||||||
|
/* public static void assertUnlocked(Lockable l) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
isTrue(!l.isLocked(),
|
||||||
|
"Illegal access to a isLocked " +
|
||||||
|
l.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Verifies that <code>lockable</code> is <em>not</em> isLocked and
|
||||||
|
* throws an error if it is.
|
||||||
|
*
|
||||||
|
* @param lockable The object that must not be isLocked
|
||||||
|
* @see com.arsdigita.util.Lockable
|
||||||
|
// * @deprecated use isUnlocked(Lockable) instead
|
||||||
|
*/
|
||||||
|
/* public static final void unlocked(final Lockable lockable) {
|
||||||
|
if (lockable != null && lockable.isLocked()) {
|
||||||
|
final String message = "Illegal access: " + lockable + " is isLocked.";
|
||||||
|
|
||||||
|
error(message);
|
||||||
|
|
||||||
|
throw new AssertionError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of static utility methods for dealing with Java
|
||||||
|
* classes.
|
||||||
|
*
|
||||||
|
* @author Justin Ross
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class Classes {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(Classes.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a class from its fully qualified string name.
|
||||||
|
*
|
||||||
|
* @param clacc A fully qualified <code>String</code> naming
|
||||||
|
* the class to be loaded
|
||||||
|
*/
|
||||||
|
public static final Class loadClass(final String clacc) {
|
||||||
|
Assert.exists(clacc, String.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Class.forName(clacc);
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new UncheckedWrapperException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of a class using the given
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* @param clacc The <code>Class</code> of which to make a new
|
||||||
|
* instance
|
||||||
|
* @param params A <code>Class[]</code> representing the arguments
|
||||||
|
* of the desired constructor
|
||||||
|
* @param values An <code>Object[]</code> of values to fill the
|
||||||
|
* parameters
|
||||||
|
*/
|
||||||
|
public static final Object newInstance(final Class clacc,
|
||||||
|
final Class[] params,
|
||||||
|
final Object[] values) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(clacc, Class.class);
|
||||||
|
Assert.exists(params, Class.class);
|
||||||
|
Assert.exists(values, Object.class);
|
||||||
|
Assert.isTrue(params.length == values.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Constructor constructor = clacc.getConstructor(params);
|
||||||
|
|
||||||
|
return constructor.newInstance(values);
|
||||||
|
} catch (NoSuchMethodException ex) {
|
||||||
|
throw new UncheckedWrapperException
|
||||||
|
(message(clacc, params, values), ex);
|
||||||
|
} catch (IllegalAccessException ex) {
|
||||||
|
throw new UncheckedWrapperException
|
||||||
|
(message(clacc, params, values), ex);
|
||||||
|
} catch (InvocationTargetException ex) {
|
||||||
|
throw new UncheckedWrapperException
|
||||||
|
(message(clacc, params, values), ex);
|
||||||
|
} catch (InstantiationException ex) {
|
||||||
|
throw new UncheckedWrapperException
|
||||||
|
(message(clacc, params, values), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String message(Class klass, Class[] params,
|
||||||
|
Object[] values) {
|
||||||
|
return "class = " + klass +
|
||||||
|
", params = " + message(params) +
|
||||||
|
", values = " + message(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String message(Object[] array) {
|
||||||
|
if (array == null) {
|
||||||
|
return "" + null;
|
||||||
|
} else {
|
||||||
|
return Arrays.asList(array).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of the class referred to by
|
||||||
|
* <code>clacc</code>.
|
||||||
|
*
|
||||||
|
* @param clacc The fully qualified <code>String</code>
|
||||||
|
* clacc of the object you wish to instantiate
|
||||||
|
* @param params A <code>Class[]</code> representing the arguments
|
||||||
|
* of the desired constructor
|
||||||
|
* @param values An <code>Object[]</code> of values to fill the
|
||||||
|
* parameters
|
||||||
|
*/
|
||||||
|
public static final Object newInstance(final String clacc,
|
||||||
|
final Class[] params,
|
||||||
|
final Object[] values) {
|
||||||
|
return newInstance(loadClass(clacc), params, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of <code>clacc</code> using its no-args
|
||||||
|
* constructor. If the class has no such constructor, it throws a
|
||||||
|
* runtime exception.
|
||||||
|
*
|
||||||
|
* @param clacc The class of which to create a new instance
|
||||||
|
*/
|
||||||
|
public static final Object newInstance(final Class clacc) {
|
||||||
|
return newInstance(clacc, new Class[0], new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of the class represented by
|
||||||
|
* <code>clacc</code> using its no-args constructor. If the class
|
||||||
|
* has no such constructor, it throws a runtime exception.
|
||||||
|
*
|
||||||
|
* @param clacc The fully-qualified <code>String</code> name of
|
||||||
|
* the class
|
||||||
|
*/
|
||||||
|
public static final Object newInstance(final String clacc) {
|
||||||
|
return newInstance(loadClass(clacc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util;
|
||||||
|
|
||||||
|
|
||||||
|
public interface ExceptionUnwrapper {
|
||||||
|
Throwable unwrap(Throwable t);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
public class Exceptions {
|
||||||
|
|
||||||
|
private static Logger s_log = Logger.getLogger(Exceptions.class);
|
||||||
|
|
||||||
|
private static Map s_unwrappers = new HashMap();
|
||||||
|
|
||||||
|
public static Throwable[] unwrap(Throwable t) {
|
||||||
|
Assert.exists(t, Throwable.class);
|
||||||
|
|
||||||
|
List exceptions = new ArrayList();
|
||||||
|
|
||||||
|
exceptions.add(t);
|
||||||
|
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Trying to unwrap " + t.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
Throwable current = t;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
Throwable inner = null;
|
||||||
|
ExceptionUnwrapper unwrapper = findUnwrapper(current.getClass());
|
||||||
|
|
||||||
|
if (unwrapper != null) {
|
||||||
|
inner = unwrapper.unwrap(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inner == null) {
|
||||||
|
Assert.exists(current, Throwable.class);
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Returning exception " + current.getClass());
|
||||||
|
}
|
||||||
|
return (Throwable[])exceptions.toArray(
|
||||||
|
new Throwable[exceptions.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Inner exception is " + inner.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
exceptions.add(inner);
|
||||||
|
|
||||||
|
current = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unreachable
|
||||||
|
//throw new RuntimeException("this cannot happen");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void registerUnwrapper(Class exception,
|
||||||
|
ExceptionUnwrapper unwrapper) {
|
||||||
|
s_unwrappers.put(exception, unwrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unregisterUnwrapper(Class exception) {
|
||||||
|
s_unwrappers.remove(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExceptionUnwrapper getUnwrapper(Class exception) {
|
||||||
|
return (ExceptionUnwrapper)s_unwrappers.get(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExceptionUnwrapper findUnwrapper(Class exception) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Finding unwrapper for " + exception.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Class current = exception;
|
||||||
|
ExceptionUnwrapper unwrapper = null;
|
||||||
|
while (unwrapper == null &&
|
||||||
|
current != null) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Trying class " + current.getName());
|
||||||
|
}
|
||||||
|
unwrapper = (ExceptionUnwrapper)s_unwrappers.get(current);
|
||||||
|
current = current.getSuperclass();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Got unwrapper " +
|
||||||
|
(unwrapper != null ? unwrapper.getClass() : null));
|
||||||
|
}
|
||||||
|
return unwrapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util;
|
||||||
|
|
||||||
|
import com.arsdigita.util.parameter.ErrorList;
|
||||||
|
import com.arsdigita.util.parameter.Parameter;
|
||||||
|
import com.arsdigita.util.parameter.ParameterReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of <code>ParameterReader</code> that uses
|
||||||
|
* standard Java properties to retrieve values.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see com.arsdigita.util.parameter.ParameterReader
|
||||||
|
* @see JavaPropertyWriter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class JavaPropertyReader implements ParameterReader {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(JavaPropertyReader.class);
|
||||||
|
|
||||||
|
private final Properties m_props;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parameter reader that uses <code>props</code>.
|
||||||
|
*
|
||||||
|
* @param props The <code>Properties</code> object that stores
|
||||||
|
* property values; it cannot be null
|
||||||
|
*/
|
||||||
|
public JavaPropertyReader(final Properties props) {
|
||||||
|
Assert.exists(props, Properties.class);
|
||||||
|
|
||||||
|
m_props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the internal <code>Properties</code> object using
|
||||||
|
* <code>in</code>.
|
||||||
|
*
|
||||||
|
* @param in The <code>InputStream</code> that has the source
|
||||||
|
* properties; it cannot be null
|
||||||
|
*/
|
||||||
|
public final void load(final InputStream in) {
|
||||||
|
Assert.exists(in, InputStream.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_props.load(in);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UncheckedWrapperException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a <code>String</code> value back for a
|
||||||
|
* <code>param</code>.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value is
|
||||||
|
* requested; it cannot be null
|
||||||
|
* @param errors An <code>ErrorList</code> to trap any errors
|
||||||
|
* encountered when reading; it cannot be null
|
||||||
|
* @return The <code>String</code> value for <code>param</code>;
|
||||||
|
* it can be null
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final String read(final Parameter param, final ErrorList errors) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Reading " + param + " from " + m_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
Assert.exists(errors, ErrorList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_props.getProperty(param.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a <code>String</code> representation of this object.
|
||||||
|
*
|
||||||
|
* @return super.toString() + "," + properties.size()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString() + "," + m_props.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util;
|
||||||
|
|
||||||
|
import com.arsdigita.util.parameter.Parameter;
|
||||||
|
import com.arsdigita.util.parameter.ParameterWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* An implementation of <code>ParameterWriter</code> that uses
|
||||||
|
* standard Java properties to store values.
|
||||||
|
*
|
||||||
|
* @see com.arsdigita.util.parameter.ParameterWriter
|
||||||
|
* @see JavaPropertyReader
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class JavaPropertyWriter implements ParameterWriter {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(JavaPropertyWriter.class);
|
||||||
|
|
||||||
|
private static final String s_header =
|
||||||
|
" Generated by " + JavaPropertyWriter.class.getName();
|
||||||
|
|
||||||
|
private final Properties m_props;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parameter writer that uses <code>props</code>.
|
||||||
|
*
|
||||||
|
* @param props The <code>Properties</code> object that stores
|
||||||
|
* property values; it cannot be null
|
||||||
|
*/
|
||||||
|
public JavaPropertyWriter(final Properties props) {
|
||||||
|
Assert.exists(props, Properties.class);
|
||||||
|
|
||||||
|
m_props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells the internal property object to store its values to
|
||||||
|
* <code>out</code>.
|
||||||
|
*
|
||||||
|
* @param out The <code>OutputStream</code> to send the saved
|
||||||
|
* parameters to; it cannot be null
|
||||||
|
*/
|
||||||
|
public final void store(final OutputStream out) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Storing " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.exists(out, OutputStream.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_props.store(out, s_header);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UncheckedWrapperException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a <code>String</code> value back for a
|
||||||
|
* <code>param</code>.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value is
|
||||||
|
* to be written; it cannot be null
|
||||||
|
* @param value The <code>String</code> value to write out; it can
|
||||||
|
* be null
|
||||||
|
*/
|
||||||
|
public final void write(final Parameter param, final String value) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Writing " + param + " with value " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: Properties objects blow up when you try to put null
|
||||||
|
// values in them. This null check fixes it for now, but it
|
||||||
|
// doesn't let us explicitly write out a null value if that's
|
||||||
|
// what we actually want to store. I.e. our property store
|
||||||
|
// doesn't know the difference between a parameter being
|
||||||
|
// unspecified and a parameter being explicitly set to null.
|
||||||
|
if (value != null) {
|
||||||
|
m_props.setProperty(param.getName(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a <code>String</code> representation of this object.
|
||||||
|
*
|
||||||
|
* @return super.toString() + "," + properties.size()
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return super.toString() + "," + m_props.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common interface for all lockable parts of ACS. The locking mechanism makes
|
||||||
|
* it possible to safely split all data structures that are used inside a web
|
||||||
|
* server into ones that are constant across all requests and those that may
|
||||||
|
* change during a request.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The distinction betwen static and request-specific data helps in optimizing
|
||||||
|
* the amount of memory that needs to be allocated for each request. Data
|
||||||
|
* structures that are static can be allocated and initialized ahead of time,
|
||||||
|
* e.g., in the <code>init</code> method of a servlet. The initialized data
|
||||||
|
* structures are then <em>locked</em> to make them immutable. This mechanism
|
||||||
|
* ensures that static structures that are supposed to be shared by many
|
||||||
|
* requests, often even concurrently, do not change and are not "polluted" by
|
||||||
|
* request-specific data.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* There is no automatic mechanism that makes an object immutable by itself. The
|
||||||
|
* right checks and operations need to be implemented by each class implementing
|
||||||
|
* <code>Lockable</code>.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Bebop parameters are a good example of how one logical structure is split
|
||||||
|
* into two classes: the class {@link
|
||||||
|
* com.arsdigita.bebop.parameters.ParameterModel} is <code>Lockable</code> and
|
||||||
|
* only contains the description of the parameter in an HTTP request that is
|
||||||
|
* static and does not change on a per-request basis, such as the name of the
|
||||||
|
* parameter and the (Java) type that the parameter value should be converted
|
||||||
|
* to. The class {@link
|
||||||
|
* com.arsdigita.bebop.parameters.ParameterData} contains all the
|
||||||
|
* request-specific information for a parameter, such as the value of the
|
||||||
|
* parameter.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Any class that implements <code>Lockable</code> is expected to be fully
|
||||||
|
* modifiable until its {@link #lock} method is called. From that point on, it
|
||||||
|
* is read-only and should throw exceptions whenever an attempt is made to
|
||||||
|
* modify it.
|
||||||
|
*
|
||||||
|
* @author David Lutterkort
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface Lockable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock an object. Locked objects are to be considered immutable. Any
|
||||||
|
* attempt to modify them, e.g., through a <code>setXXX</code> method should
|
||||||
|
* lead to an exception.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Most lockable Bebop classes throw an {@link
|
||||||
|
* java.lang.IllegalStateException} if an attempt is made to modify a locked
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether an object is locked and thus immutable, or can still be
|
||||||
|
* modified.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean isLocked();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic implementation of the Lockable interface.
|
||||||
|
*
|
||||||
|
* @see Lockable
|
||||||
|
*
|
||||||
|
* @author Michael Bryzek
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class LockableImpl implements Lockable {
|
||||||
|
|
||||||
|
private boolean m_locked = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock an object. Locked objetcs are to be considered immutable. Any
|
||||||
|
* attempt to modify them, e.g., through a <code>setXXX</code> method should
|
||||||
|
* lead to an exception.
|
||||||
|
*
|
||||||
|
* @see Lockable#lock()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// must not be final so cms.ui.Grid.GridModelBuilder can override it.
|
||||||
|
@Override
|
||||||
|
public void lock() {
|
||||||
|
m_locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether an object is locked and thus immutable, or can still be
|
||||||
|
* modified.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @see Lockable#isLocked()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// must not be final so cms.ui.PropertySheet.PSTMBAdapter can override it.
|
||||||
|
@Override
|
||||||
|
public boolean isLocked() {
|
||||||
|
return m_locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* 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.util;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper exception that can be used to rethrow another
|
||||||
|
* exception.
|
||||||
|
*
|
||||||
|
* TODO: This should become a skeleton when/if we switch to Java 1.4.
|
||||||
|
* http://java.sun.com/j2se/1.4/docs/guide/lang/chained-exceptions.html
|
||||||
|
*
|
||||||
|
* The basic exception methods are overridden with methods that
|
||||||
|
* combine this wrapper and its root cause, so it can be
|
||||||
|
* treated just like any normal exception in actual use.
|
||||||
|
*
|
||||||
|
* Note that it is not necessary to provide a string along
|
||||||
|
* with a root cause; in particular, the following usage:
|
||||||
|
* <tt>new UncheckedWrapperException(e);</tt> is more correct than
|
||||||
|
* <tt>new UncheckedWrapperException(e.getMessage(), e);</tt>
|
||||||
|
*
|
||||||
|
* @author David Eison
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class UncheckedWrapperException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(
|
||||||
|
UncheckedWrapperException.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
logger.debug("Static initalizer starting...");
|
||||||
|
Exceptions.registerUnwrapper(
|
||||||
|
UncheckedWrapperException.class,
|
||||||
|
new ExceptionUnwrapper() {
|
||||||
|
|
||||||
|
public Throwable unwrap(Throwable t) {
|
||||||
|
UncheckedWrapperException ex =
|
||||||
|
(UncheckedWrapperException) t;
|
||||||
|
return ex.getRootCause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
logger.debug("Static initalizer finished.");
|
||||||
|
}
|
||||||
|
Throwable m_rootCause;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor which only takes a msg, which will cause this
|
||||||
|
* UncheckedWrapperException to behave like a normal RuntimeException.
|
||||||
|
* While it doesn't seem to make a lot of sense to have a wrapper
|
||||||
|
* exception that doesn't wrap anything, this is needed so that it
|
||||||
|
* can be used as a direct replacement for RuntimeException.
|
||||||
|
*/
|
||||||
|
public UncheckedWrapperException(String msg) {
|
||||||
|
this(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor which takes a root cause
|
||||||
|
* that this exception will be wrapping.
|
||||||
|
*/
|
||||||
|
public UncheckedWrapperException(Throwable rootCause) {
|
||||||
|
this(null, rootCause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor which takes a message string and a root cause
|
||||||
|
* that this exception will be wrapping. The message string
|
||||||
|
* should be something different than rootCause.getMessage()
|
||||||
|
* would normally provide.
|
||||||
|
*/
|
||||||
|
public UncheckedWrapperException(String s, Throwable rootCause) {
|
||||||
|
super(s);
|
||||||
|
this.m_rootCause = rootCause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an UncheckedWrapperException, and ensurs that it is logged at ERROR priority.
|
||||||
|
*
|
||||||
|
* @param source Class having the error. For Log4J reporting
|
||||||
|
* @param msg Error message
|
||||||
|
* @param rootCause The root cause exception
|
||||||
|
*
|
||||||
|
* @throws UncheckedWrapperException
|
||||||
|
*/
|
||||||
|
public static void throwLoggedException(Class source, String msg,
|
||||||
|
Throwable rootCause) throws
|
||||||
|
UncheckedWrapperException {
|
||||||
|
Logger log = Logger.getLogger(source);
|
||||||
|
log.error(msg, rootCause);
|
||||||
|
|
||||||
|
throw new UncheckedWrapperException(msg, rootCause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if this exception has a root cause.
|
||||||
|
*/
|
||||||
|
public boolean hasRootCause() {
|
||||||
|
return m_rootCause != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the root cause of this exception.
|
||||||
|
*/
|
||||||
|
public Throwable getRootCause() {
|
||||||
|
return m_rootCause;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All further methods override normal throwable behavior to
|
||||||
|
// combine information w/ the root cause.
|
||||||
|
/**
|
||||||
|
* Get a string representing this exception and the root cause.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toString(this.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string representing this exception and the root cause.
|
||||||
|
*
|
||||||
|
* Functions like normal toString, except that the name of the
|
||||||
|
* provided class will be used instead of the name of the
|
||||||
|
* unchecked wrapper exception. Useful when another exception
|
||||||
|
* class is using an unchecked wrapper exception to delegate
|
||||||
|
* to.
|
||||||
|
*/
|
||||||
|
public String toString(Class delegatingClass) {
|
||||||
|
// default toString calls getMessage, so we don't want to rely on it
|
||||||
|
// here.
|
||||||
|
StringBuffer b = new StringBuffer(delegatingClass.getName());
|
||||||
|
String superMsg = super.getMessage();
|
||||||
|
if (superMsg != null) {
|
||||||
|
b.append(": ").append(superMsg);
|
||||||
|
}
|
||||||
|
if (m_rootCause != null) {
|
||||||
|
b.append(" (root cause: ").append(m_rootCause.toString());
|
||||||
|
b.append(")");
|
||||||
|
}
|
||||||
|
return b.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception's message and the root cause's.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
if (m_rootCause != null) {
|
||||||
|
return super.getMessage() + " (root cause: " + m_rootCause.
|
||||||
|
getMessage() + ")";
|
||||||
|
} else {
|
||||||
|
return super.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stack trace for the root cause.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void printStackTrace() {
|
||||||
|
super.printStackTrace();
|
||||||
|
if (m_rootCause != null) {
|
||||||
|
System.err.print("Root cause: ");
|
||||||
|
m_rootCause.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stack trace for the root cause.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void printStackTrace(java.io.PrintStream s) {
|
||||||
|
super.printStackTrace(s);
|
||||||
|
if (m_rootCause != null) {
|
||||||
|
s.println("Root cause: ");
|
||||||
|
m_rootCause.printStackTrace(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stack trace for the root cause.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void printStackTrace(java.io.PrintWriter s) {
|
||||||
|
super.printStackTrace(s);
|
||||||
|
if (m_rootCause != null) {
|
||||||
|
s.println("Root cause: ");
|
||||||
|
m_rootCause.printStackTrace(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,339 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import org.apache.commons.beanutils.ConversionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base implementation of the <code>Parameter</code> interface.
|
||||||
|
*
|
||||||
|
* It offers subclasses use of the Apache BeanUtils framework, should
|
||||||
|
* they opt to use it.
|
||||||
|
*
|
||||||
|
* Methods of the form <code>doXXX</code> are extension points for subclasses.
|
||||||
|
* The <code>isRequired()</code> and <code>getDefaultValue()</code>
|
||||||
|
* methods may also be overriden.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public abstract class AbstractParameter implements Parameter {
|
||||||
|
|
||||||
|
private final String m_name;
|
||||||
|
private final Class m_type;
|
||||||
|
private final int m_multiplicity;
|
||||||
|
private final Object m_default;
|
||||||
|
private ParameterInfo m_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new parameter with the default value
|
||||||
|
* <code>defaalt</code> and using the beanutils converter
|
||||||
|
* registered for <code>type</code>.
|
||||||
|
*
|
||||||
|
* @param name The name of the parameter; it cannot be null
|
||||||
|
* @param multiplicity The multiplicity type of the parameter
|
||||||
|
* @param defaalt The default value to use if the value is unset
|
||||||
|
* or is null
|
||||||
|
* @param type The <code>Class</code> whose beanutils converter
|
||||||
|
* will be used to unmarshal literal values
|
||||||
|
*/
|
||||||
|
protected AbstractParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt,
|
||||||
|
final Class type) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_name = name;
|
||||||
|
m_type = type;
|
||||||
|
m_multiplicity = multiplicity;
|
||||||
|
m_default = defaalt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new parameter with the default value
|
||||||
|
* <code>defaalt</code>.
|
||||||
|
*
|
||||||
|
* @param name The name of the parameter; it cannot be null
|
||||||
|
* @param multiplicity The multiplicity type of the parameter
|
||||||
|
* @param defaalt The default value to use if the value is unset
|
||||||
|
* or is null
|
||||||
|
*/
|
||||||
|
protected AbstractParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
// XXX Get rid of this constructor?
|
||||||
|
this(name, multiplicity, defaalt, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new parameter using the beanutils converter for
|
||||||
|
* type <code>type</code>. By default, the parameter is required
|
||||||
|
* and has no default.
|
||||||
|
*
|
||||||
|
* @param name The name of the parameter; it cannot be null
|
||||||
|
* @param type The <code>Class</code> whose beanutils converter
|
||||||
|
* will be used to unmarshal literal values
|
||||||
|
*/
|
||||||
|
protected AbstractParameter(final String name,
|
||||||
|
final Class type) {
|
||||||
|
this(name, Parameter.REQUIRED, null, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter users may override this method to make the multiplicity of
|
||||||
|
* the parameter dependent on the multiplicity of related parameters.
|
||||||
|
*
|
||||||
|
* @see Parameter#isRequired()
|
||||||
|
*/
|
||||||
|
public boolean isRequired() {
|
||||||
|
return m_multiplicity == Parameter.REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Parameter#getName()
|
||||||
|
*/
|
||||||
|
public final String getName() {
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter users may override this method to achieve dynamic
|
||||||
|
* defaulting.
|
||||||
|
*
|
||||||
|
* @see Parameter#getDefaultValue()
|
||||||
|
*/
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
return m_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Parameter#getInfo()
|
||||||
|
*/
|
||||||
|
public final ParameterInfo getInfo() {
|
||||||
|
return m_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Parameter#setInfo(ParameterInfo)
|
||||||
|
*/
|
||||||
|
public final void setInfo(final ParameterInfo info) {
|
||||||
|
m_info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lifecycle events
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parameter value as a Java object.
|
||||||
|
*
|
||||||
|
* The value will have a specific runtime type and so may be
|
||||||
|
* appropriately cast.
|
||||||
|
*
|
||||||
|
* Reading typically follows the following procedure:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Read the literal string value associated with the
|
||||||
|
* parameter from <code>reader</code></li>
|
||||||
|
*
|
||||||
|
* <li>Convert the literal string value into an approprite Java
|
||||||
|
* object</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* If at any point in the process an error is encountered, it is
|
||||||
|
* added to <code>errors</code>. Callers of this method will
|
||||||
|
* typically construct an <code>ErrorList</code> in which to
|
||||||
|
* collect errors.
|
||||||
|
* Actually calls {@link #doRead(ParameterReader,ErrorList)} (as an
|
||||||
|
* extension point for subclasses).
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> from which to
|
||||||
|
* recover a string literal value; it cannot be null
|
||||||
|
* @param errors The <code>ErrorList</code> in which to collect
|
||||||
|
* any errors encountered; it cannot be null
|
||||||
|
* @return The Java object value of the parameter
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final Object read(final ParameterReader reader,
|
||||||
|
final ErrorList errors) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(reader, ParameterReader.class);
|
||||||
|
Assert.exists(errors, ErrorList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
return doRead(reader, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension point to read the value of the parameter from <code>reader</code>.
|
||||||
|
*
|
||||||
|
* It unmarshals the value, and returns it. If any errors are encountered,
|
||||||
|
* they are added to <code>errors</code>.
|
||||||
|
*
|
||||||
|
* If the literal string value from <code>reader</code> is not null,
|
||||||
|
* this method delegates to {@link #unmarshal(String,ErrorList)}.
|
||||||
|
*
|
||||||
|
* This implementation is suited to a parameter with a singular
|
||||||
|
* scalar value. Subclasses that are compound parameters should
|
||||||
|
* override this method to delegate to child parameters.
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> that will supply
|
||||||
|
* the literal stored value for this parameter; it cannot be null
|
||||||
|
* @param errors The <code>ErrorList</code> that will trap any
|
||||||
|
* errors encountered; it cannot be null
|
||||||
|
*/
|
||||||
|
protected Object doRead(final ParameterReader reader,
|
||||||
|
final ErrorList errors) {
|
||||||
|
final String string = reader.read(this, errors);
|
||||||
|
|
||||||
|
if (string == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return unmarshal(string, errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a literal <code>String</code> value,
|
||||||
|
* <code>value</code>, to a Java object, which is returned.
|
||||||
|
*
|
||||||
|
* @param value The <code>String</code> value to convert from; it
|
||||||
|
* cannot be null
|
||||||
|
* @param errors An <code>ErrorList</code> that holds any errors
|
||||||
|
* encountered during unmarshaling; it cannot be null
|
||||||
|
*/
|
||||||
|
protected Object unmarshal(final String value, final ErrorList errors) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(value, String.class);
|
||||||
|
Assert.exists(errors, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Converters.convert(m_type, value);
|
||||||
|
} catch (ConversionException ce) {
|
||||||
|
errors.add(new ParameterError(this, ce));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link #doValidate(Object,ErrorList)} if
|
||||||
|
* <code>value</code> is not null. Otherwise, if the value is
|
||||||
|
* <em>required and null</em>, an error is added to
|
||||||
|
* <code>errors</code> and <code>doValidate</code> is not called.
|
||||||
|
*
|
||||||
|
* @see Parameter#validate(Object,ErrorList)
|
||||||
|
*/
|
||||||
|
public final void validate(final Object value, final ErrorList errors) {
|
||||||
|
Assert.exists(errors, ErrorList.class);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
// If the value is null, validation stops here.
|
||||||
|
|
||||||
|
if (isRequired()) {
|
||||||
|
final ParameterError error = new ParameterError
|
||||||
|
(this, "The value must not be null");
|
||||||
|
errors.add(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Always do further validation for non-null values.
|
||||||
|
|
||||||
|
doValidate(value, errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates <code>value</code>, placing any validation errors in
|
||||||
|
* <code>errors</code>. This particular implementation does
|
||||||
|
* nothing. Subclasses are expected to add specific validation
|
||||||
|
* behaviors.
|
||||||
|
*
|
||||||
|
* @param value The value to validate; it cannot be null
|
||||||
|
* @param errors The <code>ErrorList</code> that traps validation
|
||||||
|
* errors; it cannot be null
|
||||||
|
*/
|
||||||
|
protected void doValidate(final Object value, final ErrorList errors) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(value, Object.class);
|
||||||
|
Assert.exists(errors, ErrorList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link #doWrite(ParameterWriter,Object)}.
|
||||||
|
*
|
||||||
|
* @see Parameter#write(ParameterWriter,Object)
|
||||||
|
*/
|
||||||
|
public final void write(final ParameterWriter writer, final Object value) {
|
||||||
|
Assert.exists(writer);
|
||||||
|
|
||||||
|
// XXX what to do about nulls here?
|
||||||
|
|
||||||
|
doWrite(writer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marshals and writes <code>value</code> to <code>writer</code>.
|
||||||
|
*
|
||||||
|
* This implementation is suited to a parameter with a singular
|
||||||
|
* scalar value. Subclasses that are compound parameters should
|
||||||
|
* override this method to delegate to child parameters.
|
||||||
|
*
|
||||||
|
* @param writer The <code>ParameterWriter</code> we write to; it
|
||||||
|
* cannot be null
|
||||||
|
* @param value The value to write; it may be null
|
||||||
|
*/
|
||||||
|
protected void doWrite(final ParameterWriter writer, final Object value) {
|
||||||
|
writer.write(this, marshal(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts <code>value</code> to a representative
|
||||||
|
* <code>String</code>, which is returned.
|
||||||
|
*
|
||||||
|
* @param value The value to marshal; it may be null
|
||||||
|
* @return The <code>String</code> literal representation of
|
||||||
|
* <code>value</code>; it may be null
|
||||||
|
*/
|
||||||
|
protected String marshal(final Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a <code>String</code> representation of this object.
|
||||||
|
*
|
||||||
|
* @return <code>super.toString() + "," + getName() + "," +
|
||||||
|
* isRequired()</code>
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return super.toString() + "," + getName() + "," + isRequired();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,307 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base implementation of the <code>ParameterContext</code>
|
||||||
|
* interface.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see com.arsdigita.util.parameter.ParameterContext
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public abstract class AbstractParameterContext implements ParameterContext {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(AbstractParameterContext.class);
|
||||||
|
|
||||||
|
private final MapParameter m_param;
|
||||||
|
private final HashMap m_map;
|
||||||
|
private final Properties m_info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parameter context.
|
||||||
|
*/
|
||||||
|
public AbstractParameterContext() {
|
||||||
|
m_param = new MapParameter("root");
|
||||||
|
m_map = new HashMap();
|
||||||
|
m_info = new Properties();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers <code>param</code> to the context.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> being registered; it
|
||||||
|
* cannot be null
|
||||||
|
*/
|
||||||
|
public final void register(final Parameter param) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Registering " + param + " on " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
Assert.isTrue(!m_param.contains(param),
|
||||||
|
param + " is already registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_param.add(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ParameterContext#getParameters()
|
||||||
|
*/
|
||||||
|
public final Parameter[] getParameters() {
|
||||||
|
final ArrayList list = new ArrayList();
|
||||||
|
final Iterator params = m_param.iterator();
|
||||||
|
|
||||||
|
while (params.hasNext()) {
|
||||||
|
list.add(params.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Parameter[]) list.toArray(new Parameter[list.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unmarshaled value of <code>param</code>.
|
||||||
|
*
|
||||||
|
* If the loaded value is null, <code>param.getDefaultValue()</code>
|
||||||
|
* is returned.
|
||||||
|
*
|
||||||
|
* @param param The named <code>Parameter</code> whose value to
|
||||||
|
* retrieve; it cannot be null
|
||||||
|
* @return The unmarshaled Java object value of <code>param</code>
|
||||||
|
*/
|
||||||
|
public Object get(final Parameter param) {
|
||||||
|
return get(param, param.getDefaultValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unmarshaled value of <code>param</code>, returning
|
||||||
|
* <code>dephalt</code> if <code>param</code>'s value is null.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value to
|
||||||
|
* retrieve; it cannot be null
|
||||||
|
* @param dephalt The fallback default value; it may be null
|
||||||
|
* @return The unmarshaled Java object value of <code>param</code>
|
||||||
|
* or <code>dephalt</code> if the former is null
|
||||||
|
*/
|
||||||
|
public Object get(final Parameter param, final Object dephault) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
Assert.isTrue(m_param.contains(param),
|
||||||
|
param + " has not been registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX check for is loaded?
|
||||||
|
|
||||||
|
final Object value = m_map.get(param);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
return dephault;
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ParameterContext#get(Parameter,Object)
|
||||||
|
*/
|
||||||
|
public void set(final Parameter param, final Object value) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Setting " + param + " to " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
|
||||||
|
m_map.put(param, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and unmarshals all values associated with the registered
|
||||||
|
* parameters from <code>reader</code>. Any errors are returned.
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> from which to
|
||||||
|
* fetch the values; it cannot be null
|
||||||
|
* @return An <code>ErrorList</code> containing any errors
|
||||||
|
* encountered while loading; it cannot be null
|
||||||
|
*/
|
||||||
|
public final ErrorList load(final ParameterReader reader) {
|
||||||
|
final ErrorList errors = new ErrorList();
|
||||||
|
|
||||||
|
load(reader, errors);
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and unmarshals all values associated with the registered
|
||||||
|
* parameters from <code>reader</code>. If any errors are
|
||||||
|
* encountered, they are added to <code>errors</code>.
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> from which to
|
||||||
|
* fetch the values; it cannot be null
|
||||||
|
* @param errors The <code>ErrorList</code> that captures any
|
||||||
|
* errors while loading; it cannot be null
|
||||||
|
*/
|
||||||
|
public final void load(final ParameterReader reader,
|
||||||
|
final ErrorList errors) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(reader, ParameterReader.class);
|
||||||
|
Assert.exists(errors, ErrorList.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_map.putAll((Map) m_param.read(reader, errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates all values associated with the registered parameters.
|
||||||
|
* Any errors encountered are returned.
|
||||||
|
*
|
||||||
|
* @return An <code>ErrorList</code> containing validation errors;
|
||||||
|
* it cannot be null
|
||||||
|
*/
|
||||||
|
public final ErrorList validate() {
|
||||||
|
final ErrorList errors = new ErrorList();
|
||||||
|
|
||||||
|
m_param.validate(m_map, errors);
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ParameterContext#validate(ErrorList)
|
||||||
|
*/
|
||||||
|
public final void validate(final ErrorList errors) {
|
||||||
|
Assert.exists(errors, ErrorList.class);
|
||||||
|
|
||||||
|
m_param.validate(m_map, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ParameterContext#save(ParameterWriter)
|
||||||
|
*/
|
||||||
|
public final void save(ParameterWriter writer) {
|
||||||
|
m_param.write(writer, m_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads source data for <code>ParameterInfo</code> objects from
|
||||||
|
* the file <code>YourClass_parameter.properties</code> next to
|
||||||
|
* <code>YourClass.class</code>.
|
||||||
|
*
|
||||||
|
* <code>YourClass_parameter.properties</code>:
|
||||||
|
*
|
||||||
|
* <blockquote><pre>
|
||||||
|
* yourforum.notification_enabled.title=Flag to enable forum notifications
|
||||||
|
* yourforum.notification_enabled.purpose=Enables or disables forum notifications
|
||||||
|
* yourforum.notification_enabled.example=true
|
||||||
|
* yourforum.notifiaction_enabled.format=true|false
|
||||||
|
* </pre></blockquote>
|
||||||
|
*
|
||||||
|
* @see ParameterInfo
|
||||||
|
*/
|
||||||
|
protected final void loadInfo() {
|
||||||
|
final InputStream in = findInfo(getClass());
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_info.load(in);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UncheckedWrapperException(ioe);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Iterator params = m_param.iterator();
|
||||||
|
|
||||||
|
while (params.hasNext()) {
|
||||||
|
final Parameter param = (Parameter) params.next();
|
||||||
|
|
||||||
|
param.setInfo(new Info(param));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Private classes and methods
|
||||||
|
//
|
||||||
|
|
||||||
|
private class Info implements ParameterInfo {
|
||||||
|
private final String m_name;
|
||||||
|
|
||||||
|
Info(final Parameter param) {
|
||||||
|
m_name = param.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getTitle() {
|
||||||
|
return m_info.getProperty(m_name + ".title");
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getPurpose() {
|
||||||
|
return m_info.getProperty(m_name + ".purpose");
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getExample() {
|
||||||
|
return m_info.getProperty(m_name + ".example");
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getFormat() {
|
||||||
|
return m_info.getProperty(m_name + ".format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream findInfo(final Class klass) {
|
||||||
|
final List files = new LinkedList();
|
||||||
|
InputStream in = findInfo(klass, files);
|
||||||
|
if ( in == null ) {
|
||||||
|
throw new IllegalStateException
|
||||||
|
("Could not find any of the following files: " + files);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream findInfo(final Class klass, final List files) {
|
||||||
|
if (klass == null) { return null; }
|
||||||
|
final String name =
|
||||||
|
klass.getName().replace('.', '/') + "_parameter.properties";
|
||||||
|
files.add(name);
|
||||||
|
if ( klass.getClassLoader() == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final InputStream in = klass.getClassLoader().getResourceAsStream(name);
|
||||||
|
|
||||||
|
if (in == null) {
|
||||||
|
return findInfo(klass.getSuperclass(), files);
|
||||||
|
} else {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.converters.BooleanConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* A parameter representing a Java <code>Boolean</code>.
|
||||||
|
*
|
||||||
|
* @see java.lang.Boolean
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class BooleanParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
static {
|
||||||
|
Converters.set(Boolean.class, new BooleanConverter());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanParameter(final String name) {
|
||||||
|
super(name, Boolean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt, Boolean.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
// import com.arsdigita.util.parameter.ErrorList;
|
||||||
|
// import com.arsdigita.util.parameter.Parameter;
|
||||||
|
// import com.arsdigita.util.parameter.ParameterLoader;
|
||||||
|
// import com.arsdigita.util.parameter.ParameterValue;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.LineNumberReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes an input stream (a set of lines, each containing a comma separated
|
||||||
|
* list of parameter values) and ....
|
||||||
|
*
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class CSVParameterReader implements ParameterReader {
|
||||||
|
|
||||||
|
private final LineNumberReader m_reader;
|
||||||
|
private final Parameter[] m_params;
|
||||||
|
private final HashMap m_line;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param reader: input stream to read values
|
||||||
|
* @param params: array of parameter objects to store procecced values
|
||||||
|
*/
|
||||||
|
public CSVParameterReader(final Reader reader, final Parameter[] params) {
|
||||||
|
m_reader = new LineNumberReader(reader); // input stream
|
||||||
|
m_params = params; // array of parameters
|
||||||
|
m_line = new HashMap(params.length); //
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param param
|
||||||
|
* @param errors
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public final String read(final Parameter param, final ErrorList errors) {
|
||||||
|
return (String) m_line.get(param);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* May 2009: Obviously a reminiscence from previous versions of code. This class
|
||||||
|
* is currently used by coreloader only and it does not use the load method
|
||||||
|
* and it works with load commented out.
|
||||||
|
*
|
||||||
|
* Code should be removed after extensive testing.
|
||||||
|
*
|
||||||
|
public final ParameterValue load(final Parameter param) {
|
||||||
|
final ParameterValue value = new ParameterValue();
|
||||||
|
|
||||||
|
// XXX this won't work correctly with compound parameters
|
||||||
|
value.setObject(param.read(this, value.getErrors()));
|
||||||
|
|
||||||
|
value.getErrors().check();
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Just a public visible entry point into internalNext, used to process
|
||||||
|
* an exception if thrown.
|
||||||
|
*
|
||||||
|
* @return: boolean true if any values could be processed.
|
||||||
|
*/
|
||||||
|
public final boolean next() {
|
||||||
|
try {
|
||||||
|
return internalNext();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UncheckedWrapperException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internally used worker method which processes the next() method.
|
||||||
|
*
|
||||||
|
* Reads in a line from input stream and asks parseLine to process it. The
|
||||||
|
* resulting array of strings (each containing a value)
|
||||||
|
* @return
|
||||||
|
* @throws java.io.IOException
|
||||||
|
*/
|
||||||
|
private boolean internalNext() throws IOException {
|
||||||
|
final String line = m_reader.readLine();
|
||||||
|
|
||||||
|
if (line == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
final String[] elems = parseLine(line);
|
||||||
|
|
||||||
|
// m_params: array of parameters to store the comma separated values
|
||||||
|
// used to determine the max. number of values which can be processed.
|
||||||
|
for (int i = 0; i < m_params.length; i++) {
|
||||||
|
if (i < elems.length) {
|
||||||
|
// If for the given index into the array of parametes a
|
||||||
|
// corresponding element in the array of strings exist,
|
||||||
|
// store it in a hash map (a hash map per line)
|
||||||
|
m_line.put(m_params[i], elems[i]);
|
||||||
|
} else {
|
||||||
|
m_line.put(m_params[i], null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final char ESCAPE = '\\';
|
||||||
|
private static final char QUOTE = '"';
|
||||||
|
private static final char SEPARATOR = ',';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal used helper method of method parseLine.
|
||||||
|
*
|
||||||
|
* @param c
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private char escape(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case 'n':
|
||||||
|
return '\n';
|
||||||
|
case 't':
|
||||||
|
return '\t';
|
||||||
|
case 'r':
|
||||||
|
return '\r';
|
||||||
|
default:
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a string and analyses it as a list of comma separated values.
|
||||||
|
*
|
||||||
|
* Internally used to store each value found in a new string and add it
|
||||||
|
* to an array of strings.
|
||||||
|
*
|
||||||
|
* @param line: string containing a comma separated list of values
|
||||||
|
* @return : array of strings, each containing a value of the list
|
||||||
|
*/
|
||||||
|
private String[] parseLine(final String line) {
|
||||||
|
int length = line.length();
|
||||||
|
|
||||||
|
// Check here if the last character is an escape character so
|
||||||
|
// that we don't need to check in the main loop.
|
||||||
|
if (line.charAt(length - 1) == ESCAPE) {
|
||||||
|
throw new IllegalArgumentException
|
||||||
|
(m_reader.getLineNumber() +
|
||||||
|
": last character is an escape character\n" + line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The set of parsed fields.
|
||||||
|
List result = new ArrayList();
|
||||||
|
|
||||||
|
// The characters between seperators.
|
||||||
|
StringBuffer buf = new StringBuffer(length);
|
||||||
|
// Marks the begining of the field relative to buf,
|
||||||
|
// -1 indicates the beginning of buf.
|
||||||
|
int begin = -1;
|
||||||
|
// Marks the end of the field relative to buf.
|
||||||
|
int end = 0;
|
||||||
|
|
||||||
|
// Indicates whether or not we're in a quoted string.
|
||||||
|
boolean quote = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
char c = line.charAt(i);
|
||||||
|
if (quote) {
|
||||||
|
switch (c) {
|
||||||
|
case QUOTE:
|
||||||
|
quote = false;
|
||||||
|
break;
|
||||||
|
case ESCAPE:
|
||||||
|
buf.append(escape(line.charAt(++i)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buf.append(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = buf.length();
|
||||||
|
} else {
|
||||||
|
switch (c) {
|
||||||
|
case SEPARATOR:
|
||||||
|
result.add(field(buf, begin, end));
|
||||||
|
buf = new StringBuffer(length);
|
||||||
|
begin = -1;
|
||||||
|
end = 0;
|
||||||
|
break;
|
||||||
|
case ESCAPE:
|
||||||
|
if (begin < 0) { begin = buf.length(); }
|
||||||
|
buf.append(escape(line.charAt(++i)));
|
||||||
|
end = buf.length();
|
||||||
|
break;
|
||||||
|
case QUOTE:
|
||||||
|
if (begin < 0) { begin = buf.length(); }
|
||||||
|
quote = true;
|
||||||
|
end = buf.length();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (begin < 0 &&
|
||||||
|
!Character.isWhitespace(c)) {
|
||||||
|
begin = buf.length();
|
||||||
|
}
|
||||||
|
buf.append(c);
|
||||||
|
if (!Character.isWhitespace(c)) { end = buf.length(); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quote) {
|
||||||
|
throw new IllegalArgumentException
|
||||||
|
(m_reader.getLineNumber() + ": unterminated string\n" + line);
|
||||||
|
} else {
|
||||||
|
result.add(field(buf, begin, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] fields = new String[result.size()];
|
||||||
|
result.toArray(fields);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* internal helper method for method parseLine
|
||||||
|
*
|
||||||
|
* @param field
|
||||||
|
* @param begin
|
||||||
|
* @param end
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String field(StringBuffer field, int begin, int end) {
|
||||||
|
if (begin < 0) {
|
||||||
|
return field.substring(0, end);
|
||||||
|
} else {
|
||||||
|
return field.substring(begin, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.converters.ClassConverter;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter representing a Java <code>Class</code>.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see java.lang.Class
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ClassParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(ClassParameter.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
logger.debug("Static initalizer starting...");
|
||||||
|
Converters.set(Class.class, new ClassConverter());
|
||||||
|
logger.debug("Static initalizer finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassParameter(final String name) {
|
||||||
|
super(name, Class.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt, Class.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// value != null
|
||||||
|
protected Object unmarshal(String value, ErrorList errors) {
|
||||||
|
Class theClass = null;
|
||||||
|
try {
|
||||||
|
theClass = Class.forName(value);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
errors.add(new ParameterError(this, "No such class: " + value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return theClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String marshal(Object value) {
|
||||||
|
Class theClass = ((Class) value);
|
||||||
|
if (theClass == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return theClass.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregates a set of <code>ParameterReaders</code> so they may be
|
||||||
|
* treated as one.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see ParameterReader
|
||||||
|
* @author Rafael H. Schloming <rhs@mit.edu>
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class CompoundParameterReader implements ParameterReader {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(CompoundParameterReader.class);
|
||||||
|
|
||||||
|
private final List m_readers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new compound parameter reader.
|
||||||
|
*/
|
||||||
|
public CompoundParameterReader() {
|
||||||
|
m_readers = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds <code>reader</code> to the set of component readers.
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> being added; it
|
||||||
|
* cannot be null
|
||||||
|
*/
|
||||||
|
public void add(final ParameterReader reader) {
|
||||||
|
Assert.exists(reader, ParameterReader.class);
|
||||||
|
|
||||||
|
m_readers.add(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ParameterReader#read(Parameter,ErrorList)
|
||||||
|
*/
|
||||||
|
public String read(final Parameter param, final ErrorList errors) {
|
||||||
|
for (final Iterator it = m_readers.iterator(); it.hasNext(); ) {
|
||||||
|
final ParameterReader reader = (ParameterReader) it.next();
|
||||||
|
|
||||||
|
final String result = reader.read(param, errors);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* Collects together BeanUtils converters for use by the base
|
||||||
|
* <code>Parameter</code>s.
|
||||||
|
*
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class Converters {
|
||||||
|
|
||||||
|
private static Map s_converters = Collections.synchronizedMap
|
||||||
|
(new HashMap());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the <code>Converter</code> registered for
|
||||||
|
* <code>clacc</code>. This method will fail if no converter is
|
||||||
|
* found.
|
||||||
|
*
|
||||||
|
* @param clacc The <code>Class</code> of the parameter value; it
|
||||||
|
* cannot be null
|
||||||
|
* @return A <code>Converter</code> instance; it cannot be null
|
||||||
|
*/
|
||||||
|
public static final Converter get(final Class clacc) {
|
||||||
|
Assert.exists(clacc, Class.class);
|
||||||
|
|
||||||
|
final Converter converter = (Converter) s_converters.get(clacc);
|
||||||
|
|
||||||
|
Assert.exists(converter, Converter.class);
|
||||||
|
|
||||||
|
return converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers <code>converter</code> for <code>clacc</code>.
|
||||||
|
*
|
||||||
|
* @param clacc The <code>Class</code> of the parameter value; it
|
||||||
|
* cannot be null
|
||||||
|
* @param converter The <code>Converter</code> to register to
|
||||||
|
* <code>clacc</code>; it cannot be null
|
||||||
|
*/
|
||||||
|
public static final void set(final Class clacc, final Converter converter) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(clacc, Class.class);
|
||||||
|
Assert.exists(converter, Converter.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_converters.put(clacc, converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts <code>value</code> using the converter registered for
|
||||||
|
* <code>clacc</code>.
|
||||||
|
*
|
||||||
|
* @param clacc The <code>Class</code> of the parameter value; it
|
||||||
|
* cannot be null
|
||||||
|
* @param value The <code>String</code>-encoded value of the
|
||||||
|
* parameter; it may be null
|
||||||
|
* @return The Java object conversion for <code>value</code>; it
|
||||||
|
* may be null
|
||||||
|
*/
|
||||||
|
public static final Object convert(final Class clacc, final String value) {
|
||||||
|
Assert.exists(clacc, Class.class);
|
||||||
|
|
||||||
|
return get(clacc).convert(clacc, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import javax.mail.internet.AddressException;
|
||||||
|
import javax.mail.internet.InternetAddress;
|
||||||
|
import org.apache.oro.text.perl.Perl5Util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* A parameter representing an <code>InternetAddress</code>.
|
||||||
|
*
|
||||||
|
* @see javax.mail.internet.InternetAddress
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class EmailParameter extends StringParameter {
|
||||||
|
|
||||||
|
private static final Perl5Util s_perl = new Perl5Util();
|
||||||
|
private static final String s_regex =
|
||||||
|
"/^[^@<>\"\t ]+@[^@<>\".\t]+([.][^@<>\".\n ]+)+$/";
|
||||||
|
|
||||||
|
public EmailParameter(final String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object unmarshal(final String value, final ErrorList errors) {
|
||||||
|
try {
|
||||||
|
return new InternetAddress(value);
|
||||||
|
} catch (AddressException ae) {
|
||||||
|
errors.add(new ParameterError(this, ae));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doValidate(final Object value, final ErrorList errors) {
|
||||||
|
super.doValidate(value, errors);
|
||||||
|
|
||||||
|
final InternetAddress email = (InternetAddress) value;
|
||||||
|
|
||||||
|
if (!s_perl.match(s_regex, email.toString())) {
|
||||||
|
final ParameterError error = new ParameterError
|
||||||
|
(this, "The value is not a valid email address");
|
||||||
|
|
||||||
|
errors.add(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* A parameter that maps keys to values and, given a key, marshals or
|
||||||
|
* unmarshals to the corresponding value.
|
||||||
|
*
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class EnumerationParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger
|
||||||
|
(EnumerationParameter.class);
|
||||||
|
|
||||||
|
private final HashMap m_entries;
|
||||||
|
private final HashMap m_reverse;
|
||||||
|
|
||||||
|
public EnumerationParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt);
|
||||||
|
|
||||||
|
m_entries = new HashMap();
|
||||||
|
m_reverse = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumerationParameter(final String name) {
|
||||||
|
this(name, Parameter.REQUIRED, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void put(final String name, final Object value) {
|
||||||
|
if (m_entries.containsKey(name)) {
|
||||||
|
throw new IllegalArgumentException
|
||||||
|
("name already has a value: " + name);
|
||||||
|
}
|
||||||
|
if (m_reverse.containsKey(value)) {
|
||||||
|
throw new IllegalArgumentException
|
||||||
|
("value already has a name: " + value);
|
||||||
|
}
|
||||||
|
m_entries.put(name, value);
|
||||||
|
m_reverse.put(value, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object unmarshal(final String value, final ErrorList errors) {
|
||||||
|
if (m_entries.containsKey(value)) {
|
||||||
|
return m_entries.get(value);
|
||||||
|
} else {
|
||||||
|
final ParameterError error = new ParameterError
|
||||||
|
(this, "The value must be one of " + m_entries.keySet());
|
||||||
|
|
||||||
|
errors.add(error);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String marshal(Object value) {
|
||||||
|
return (String) m_reverse.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* A collection to store <code>ParameterError</code>s that are
|
||||||
|
* encountered during parameter reading or validation. This
|
||||||
|
* collection is used in the lifecycle methods of
|
||||||
|
* <code>Parameter</code>. It is ordinarily returned to the
|
||||||
|
* parameter-using code so that it can handle errors.
|
||||||
|
*
|
||||||
|
* @see ParameterError
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class ErrorList {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(ErrorList.class);
|
||||||
|
|
||||||
|
private final ArrayList m_params;
|
||||||
|
|
||||||
|
// XXX temporarily package access
|
||||||
|
final ArrayList m_errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new error list.
|
||||||
|
*/
|
||||||
|
public ErrorList() {
|
||||||
|
m_params = new ArrayList();
|
||||||
|
m_errors = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds <code>error</code> to the error list.
|
||||||
|
*
|
||||||
|
* @param error A <code>ParameterError</code> representing a read
|
||||||
|
* or validation error; it cannot be null
|
||||||
|
*/
|
||||||
|
public final void add(final ParameterError error) {
|
||||||
|
Assert.exists(error, ParameterError.class);
|
||||||
|
|
||||||
|
final Parameter param = error.getParameter();
|
||||||
|
|
||||||
|
synchronized (m_params) {
|
||||||
|
if (!m_params.contains(param)) {
|
||||||
|
m_params.add(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_errors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an iterator over the currently stored errors.
|
||||||
|
*
|
||||||
|
* @see ParameterError
|
||||||
|
* @return An <code>Iterator</code> of
|
||||||
|
* <code>ParameterError</code>s; it cannot be null
|
||||||
|
*/
|
||||||
|
public final Iterator iterator() {
|
||||||
|
return m_errors.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether the error collection is empty or not.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the collection is empty, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
public final boolean isEmpty() {
|
||||||
|
return m_errors.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a <code>ParameterException</code> containing the error
|
||||||
|
* list. This method is for use when the client code wants the
|
||||||
|
* program to fail via an exception if there are errors.
|
||||||
|
*
|
||||||
|
* @throws ParameterException if the error list is not empty
|
||||||
|
*/
|
||||||
|
public final void check() throws ParameterException {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
final StringWriter writer = new StringWriter();
|
||||||
|
report(writer);
|
||||||
|
s_log.error(writer.toString());
|
||||||
|
|
||||||
|
throw new ParameterException
|
||||||
|
("Errors encountered while reading parameters", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints parameter errors to <code>out</code> with formatting
|
||||||
|
* appropriate to the console.
|
||||||
|
*
|
||||||
|
* @param out The <code>Writer</code> to print the errors to
|
||||||
|
*/
|
||||||
|
public final void report(final Writer out) {
|
||||||
|
try {
|
||||||
|
Assert.exists(out, PrintWriter.class);
|
||||||
|
|
||||||
|
final Iterator params = m_params.iterator();
|
||||||
|
|
||||||
|
while (params.hasNext()) {
|
||||||
|
final Parameter param = (Parameter) params.next();
|
||||||
|
|
||||||
|
out.write("Parameter " + param.getName() + " has the " +
|
||||||
|
"following errors:\n");
|
||||||
|
|
||||||
|
final Iterator errors = m_errors.iterator();
|
||||||
|
|
||||||
|
while (errors.hasNext()) {
|
||||||
|
final ParameterError error =
|
||||||
|
(ParameterError) errors.next();
|
||||||
|
|
||||||
|
if (error.getParameter().equals(param)) {
|
||||||
|
out.write("\t" + error.getMessage() + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flush();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new UncheckedWrapperException(ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Parameter representing a File
|
||||||
|
*
|
||||||
|
* @see Parameter
|
||||||
|
* @see java.io.File
|
||||||
|
* @author bche
|
||||||
|
*/
|
||||||
|
public class FileParameter extends AbstractParameter {
|
||||||
|
private static final Logger s_log = Logger.getLogger(FileParameter.class);
|
||||||
|
|
||||||
|
public FileParameter(final String name) {
|
||||||
|
super(name, File.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object unmarshal(final String value, final ErrorList errors) {
|
||||||
|
final String sPath = value;
|
||||||
|
File file = new File(sPath);
|
||||||
|
if (file.exists()) {
|
||||||
|
return file;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String marshal(final Object value) {
|
||||||
|
final File file = (File) value;
|
||||||
|
if (file == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return file.getAbsolutePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doValidate(final Object value, final ErrorList errors) {
|
||||||
|
final File file = (File) value;
|
||||||
|
if (!file.exists()) {
|
||||||
|
errors.add(
|
||||||
|
new ParameterError(
|
||||||
|
this,
|
||||||
|
"File " + file.getAbsolutePath() + " does not exist"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.converters.IntegerConverter;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter representing a Java <code>Integer</code>.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see java.lang.Integer
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class IntegerParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(IntegerParameter.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
logger.debug("Static initalizer starting...");
|
||||||
|
Converters.set(Integer.class, new IntegerConverter());
|
||||||
|
logger.debug("Static initalizer finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegerParameter(final String name) {
|
||||||
|
super(name, Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegerParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt, Integer.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter that manages a collection of <code>Parameter</code> to
|
||||||
|
* <code>Object</code> value mappings.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see java.util.Map
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class MapParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
private final ArrayList m_params;
|
||||||
|
|
||||||
|
public MapParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt, String.class);
|
||||||
|
|
||||||
|
m_params = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapParameter(final String name) {
|
||||||
|
super(name, String.class);
|
||||||
|
|
||||||
|
m_params = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void add(final Parameter param) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
|
||||||
|
m_params.add(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean contains(final Parameter param) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
|
||||||
|
return m_params.contains(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Iterator iterator() {
|
||||||
|
return m_params.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object doRead(final ParameterReader reader,
|
||||||
|
final ErrorList errors) {
|
||||||
|
final HashMap map = new HashMap();
|
||||||
|
final Iterator params = m_params.iterator();
|
||||||
|
|
||||||
|
while (params.hasNext()) {
|
||||||
|
final Parameter param = (Parameter) params.next();
|
||||||
|
final Object value = param.read(reader, errors);
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
map.put(param, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doValidate(final Object value, final ErrorList errors) {
|
||||||
|
final HashMap map = (HashMap) value;
|
||||||
|
final Iterator params = m_params.iterator();
|
||||||
|
|
||||||
|
while (params.hasNext()) {
|
||||||
|
final Parameter param = (Parameter) params.next();
|
||||||
|
|
||||||
|
if (map.containsKey(param)) {
|
||||||
|
param.validate(map.get(param), errors);
|
||||||
|
} else {
|
||||||
|
param.validate(param.getDefaultValue(), errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doWrite(final ParameterWriter writer, final Object value) {
|
||||||
|
final HashMap map = (HashMap) value;
|
||||||
|
final Iterator params = m_params.iterator();
|
||||||
|
|
||||||
|
while (params.hasNext()) {
|
||||||
|
final Parameter param = (Parameter) params.next();
|
||||||
|
|
||||||
|
if (map.containsKey(param)) {
|
||||||
|
param.write(writer, map.get(param));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes a named property that can read, write, and validate its
|
||||||
|
* own value.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* See the documentation on {@link #read}, {@link #write}, and {@link #validate}
|
||||||
|
* for details.
|
||||||
|
|
||||||
|
* They have the following features as well:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Multiplicity. A parameter can be nullable (0..x) or required
|
||||||
|
* (1..x) and singular (x..1) or multiple (x..n). The current
|
||||||
|
* parameter implementation only models nullablel vs. required
|
||||||
|
* parameters.</li>
|
||||||
|
*
|
||||||
|
* <li>Defaulting. A parameter can have a value to fall back on if
|
||||||
|
* none is set.</li>
|
||||||
|
*
|
||||||
|
* <li>Optional metadata. Optional extra "info" can be associated
|
||||||
|
* with a parameter.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* The read and validate phases of a parameter collect errors into a
|
||||||
|
* list so that calling code can control error handling. This is in
|
||||||
|
* lieu of throwing exceptions that are not useful in creating
|
||||||
|
* error-recovery UIs.
|
||||||
|
*
|
||||||
|
* In contrast, the write phase of a parameter is expected to complete
|
||||||
|
* successfully or fail outright.
|
||||||
|
*
|
||||||
|
* Parameters are stateless "messages". They do not store their own
|
||||||
|
* values. Instead, a {@link com.arsdigita.util.parameter.ParameterContext}
|
||||||
|
* manages a set of parameters and keeps their values.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Here's what it typically looks like to use a parameter:
|
||||||
|
*
|
||||||
|
* <blockquote><code>
|
||||||
|
* Properties props = System.getProperties();
|
||||||
|
* ParameterReader reader = JavaPropertyReader(props);
|
||||||
|
* ParameterWriter writer = JavaPropertyWriter(props);
|
||||||
|
* ErrorList errors = new ErrorList();
|
||||||
|
*
|
||||||
|
* Object value = param.read(reader, errors);
|
||||||
|
* errors.check(); // If errors is not empty, fails
|
||||||
|
*
|
||||||
|
* param.validate(value, errors);
|
||||||
|
* errors.check(); // If errors is not empty, fails
|
||||||
|
*
|
||||||
|
* // We now have a valid unmarshaled value, so code of actual use can
|
||||||
|
* // go here.
|
||||||
|
*
|
||||||
|
* param.write(writer, value);
|
||||||
|
* </code></blockquote>
|
||||||
|
*
|
||||||
|
* @see com.arsdigita.util.parameter.AbstractParameter
|
||||||
|
* @see com.arsdigita.util.parameter.ParameterContext
|
||||||
|
* @author Rafael H. Schloming <rhs@mit.edu>
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface Parameter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to indicate the parameter value is nullable.
|
||||||
|
*/
|
||||||
|
public static final int OPTIONAL = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to indicate the parameter value cannot be null.
|
||||||
|
*/
|
||||||
|
public static final int REQUIRED = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells wether the parameter is nullable or not.
|
||||||
|
*
|
||||||
|
* @return true if the parameter cannot be null; false if it can
|
||||||
|
* be null
|
||||||
|
*/
|
||||||
|
boolean isRequired();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the parameter.
|
||||||
|
*
|
||||||
|
* @return The <code>String</code> parameter name; it cannot be
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default value of the parameter. Implementations may
|
||||||
|
* choose to substitute this value for null.
|
||||||
|
*
|
||||||
|
* @return The fallback value; it may be null
|
||||||
|
*/
|
||||||
|
Object getDefaultValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets metadata associated with the parameter if it is available.
|
||||||
|
*
|
||||||
|
* @return The <code>ParameterInfo</code> object; it may be null
|
||||||
|
*/
|
||||||
|
ParameterInfo getInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the optional parameter metadata to <code>info</code>.
|
||||||
|
*
|
||||||
|
* @param info The <code>ParameterInfo</code> to associate; it may
|
||||||
|
* be null
|
||||||
|
*/
|
||||||
|
void setInfo(ParameterInfo info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parameter value as a Java object. The value will have
|
||||||
|
* a specific runtime type and so may be appropriately cast.
|
||||||
|
*
|
||||||
|
* Reading typically follows the following procedure:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>Read the literal string value associated with the
|
||||||
|
* parameter from <code>reader</code></li>
|
||||||
|
*
|
||||||
|
* <li>Convert the literal string value into an approprite Java
|
||||||
|
* object</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* If at any point in the process an error is encountered, it is
|
||||||
|
* added to <code>errors</code>. Callers of this method will
|
||||||
|
* typically construct an <code>ErrorList</code> in which to
|
||||||
|
* collect errors.
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> from which to
|
||||||
|
* recover a string literal value; it cannot be null
|
||||||
|
* @param errors The <code>ErrorList</code> in which to collect
|
||||||
|
* any errors encountered; it cannot be null
|
||||||
|
* @return The Java object value of the parameter
|
||||||
|
*/
|
||||||
|
Object read(ParameterReader reader, ErrorList errors);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the parameter value, <code>value</code>. Any
|
||||||
|
* validation errors encountered are added to <code>errors</code>.
|
||||||
|
*
|
||||||
|
* @param value The value to validate; this is typically the value
|
||||||
|
* returned by {@link #read}; it may be null
|
||||||
|
* @param errors The <code>ErrorList</code> in which to collect
|
||||||
|
* any errors encountered; it cannot be null
|
||||||
|
*/
|
||||||
|
void validate(Object value, ErrorList errors);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the parameter value as a string literal. The parameter
|
||||||
|
* marshals the object <code>value</code> to a string and sends it
|
||||||
|
* to <code>writer</code>.
|
||||||
|
*
|
||||||
|
* @param writer The <code>ParameterWriter</code> that will take
|
||||||
|
* the marshaled value and store it; it cannot be null
|
||||||
|
* @param value The Java object value of the parameter
|
||||||
|
*/
|
||||||
|
void write(ParameterWriter writer, Object value);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A container of parameters.
|
||||||
|
*
|
||||||
|
* A parameter context binds together a set of parameters and keeps their values.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see com.arsdigita.util.parameter.Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface ParameterContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the parameters registered on the parameter context.
|
||||||
|
*
|
||||||
|
* @return A <code>Parameter[]</code> of all the parameters; it
|
||||||
|
* cannot be null
|
||||||
|
*/
|
||||||
|
Parameter[] getParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unmarshaled value of <code>param</code>. If the
|
||||||
|
* loaded value is null, <code>param.getDefaultValue()</code> is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @param param The named <code>Parameter</code> whose value to
|
||||||
|
* retrieve; it cannot be null
|
||||||
|
* @return The unmarshaled Java object value of <code>param</code>
|
||||||
|
*/
|
||||||
|
Object get(Parameter param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unmarshaled value of <code>param</code>, returning
|
||||||
|
* <code>dephalt</code> if <code>param</code>'s value is null.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value to
|
||||||
|
* retrieve; it cannot be null
|
||||||
|
* @param dephalt The fallback default value; it may be null
|
||||||
|
* @return The unmarshaled Java object value of <code>param</code>
|
||||||
|
* or <code>dephalt</code> if the former is null
|
||||||
|
*/
|
||||||
|
Object get(Parameter param, Object dephalt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of <code>param</code> to <code>value</code>.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value to set; it
|
||||||
|
* cannot be null
|
||||||
|
* @param value The new value of <code>param</code>; it may be
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
void set(Parameter param, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and unmarshals all values associated with the registered
|
||||||
|
* parameters from <code>reader</code>. If any errors are
|
||||||
|
* encountered, they are added to <code>errors</code>.
|
||||||
|
*
|
||||||
|
* @param reader The <code>ParameterReader</code> from which to
|
||||||
|
* fetch the values; it cannot be null
|
||||||
|
* @param errors The <code>ErrorList</code> that captures any
|
||||||
|
* errors while loading; it cannot be null
|
||||||
|
*/
|
||||||
|
void load(ParameterReader reader, ErrorList errors);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marshals and writes all values associated with the registered
|
||||||
|
* parameters to <code>writer</code>.
|
||||||
|
*
|
||||||
|
* @param writer The <code>ParameterWriter</code> to which values
|
||||||
|
* are written; it cannot be null
|
||||||
|
*/
|
||||||
|
void save(ParameterWriter writer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates all values associated with the registered parameters.
|
||||||
|
* Any errors encountered are added to <code>errors</code>.
|
||||||
|
*
|
||||||
|
* @param errors The <code>ErrorList</code> that captures
|
||||||
|
* validation errors; it cannot be null
|
||||||
|
*/
|
||||||
|
void validate(ErrorList errors);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* Information about an error for a parameter. Parameter implementors
|
||||||
|
* will add <code>ParameterError</code>s to the passed in
|
||||||
|
* <code>ErrorList</code> when their parameters encounter error
|
||||||
|
* conditions.
|
||||||
|
*
|
||||||
|
* @see ErrorList
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class ParameterError {
|
||||||
|
|
||||||
|
private final Parameter m_param;
|
||||||
|
private final String m_message;
|
||||||
|
private Throwable m_throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parameter error for <code>param</code>.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value is in
|
||||||
|
* error; it cannot be null
|
||||||
|
* @param message A <code>String</code> description of the error
|
||||||
|
*/
|
||||||
|
public ParameterError(final Parameter param,
|
||||||
|
final String message) {
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(param, Parameter.class);
|
||||||
|
Assert.exists(message, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_param = param;
|
||||||
|
m_message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parameter error for <code>param</code>, drawing
|
||||||
|
* its error message from <code>throwable</code>.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> whose value is in
|
||||||
|
* error; it cannot be null
|
||||||
|
* @param throwable The <code>Throwable</code> for the error; it
|
||||||
|
* cannot be null
|
||||||
|
*/
|
||||||
|
public ParameterError(final Parameter param,
|
||||||
|
final Throwable throwable) {
|
||||||
|
this(param, throwable.getMessage());
|
||||||
|
|
||||||
|
m_throwable = throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parameter associated with this error.
|
||||||
|
*
|
||||||
|
* @return The <code>Parameter</code> in error; it cannot be null
|
||||||
|
*/
|
||||||
|
public final Parameter getParameter() {
|
||||||
|
return m_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the message associated with this error.
|
||||||
|
*
|
||||||
|
* @return The <code>String</code> message for the error; it
|
||||||
|
* cannot be null
|
||||||
|
*/
|
||||||
|
public final String getMessage() {
|
||||||
|
// XXX this actually can be null, so need to prevent that
|
||||||
|
return m_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the throwable, if present, that corresponds to the error.
|
||||||
|
*
|
||||||
|
* @return The <code>Throwable</code> of this error; it may be
|
||||||
|
* null
|
||||||
|
*/
|
||||||
|
public final Throwable getThrowable() {
|
||||||
|
return m_throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the error suitable for
|
||||||
|
* debugging.
|
||||||
|
*
|
||||||
|
* @return <code>super.toString() + "," + param.getName()</code>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString() + "," + m_param.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* An exception to indicate invalid parameter states. This exception should only
|
||||||
|
* be used when the client code of a parameter opts in to using exceptions
|
||||||
|
* rather than handling parameter errors itself. See
|
||||||
|
* {@link com.arsdigita.util.parameter.ErrorList#check()}.
|
||||||
|
*
|
||||||
|
* @see com.arsdigita.util.parameter.ErrorList
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public final class ParameterException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(
|
||||||
|
ParameterException.class);
|
||||||
|
private static final long serialVersionUID = 1726920836531266365L;
|
||||||
|
|
||||||
|
private final ErrorList m_errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new parameter exception with the content
|
||||||
|
* <code>message</code>.
|
||||||
|
*
|
||||||
|
* @param message A <code>String</code> describing what's wrong; it cannot
|
||||||
|
* be null
|
||||||
|
* @param errors The <code>ErrorList</code> containing the errors that
|
||||||
|
* prompted this exception; it cannot be null
|
||||||
|
*/
|
||||||
|
public ParameterException(final String message, final ErrorList errors) {
|
||||||
|
super(message);
|
||||||
|
|
||||||
|
if (Assert.isEnabled()) {
|
||||||
|
Assert.exists(message, String.class);
|
||||||
|
Assert.exists(errors, List.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_errors = errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the set of errors associated with the exception.
|
||||||
|
*
|
||||||
|
* @return The <code>ErrorList</code> of errors; it cannot be null
|
||||||
|
*/
|
||||||
|
public final ErrorList getErrors() {
|
||||||
|
return m_errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* Metadata for a parameter that is of use for building documentation
|
||||||
|
* or user interfaces for parameters. The fields are not required and
|
||||||
|
* thus the methods of this class may return null.
|
||||||
|
*
|
||||||
|
* @see Parameter#setInfo(ParameterInfo)
|
||||||
|
* @see Parameter#getInfo()
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface ParameterInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pretty name of the parameter.
|
||||||
|
*
|
||||||
|
* @return The <code>String</code> title of the parameter; it may
|
||||||
|
* be null
|
||||||
|
*/
|
||||||
|
String getTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parameter's reason for being.
|
||||||
|
*
|
||||||
|
* @return The <code>String</code> purpose of the parameter; it
|
||||||
|
* may be null
|
||||||
|
*/
|
||||||
|
String getPurpose();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an example value for the parameter.
|
||||||
|
*
|
||||||
|
* @return A <code>String</code> example value; it may be null
|
||||||
|
*/
|
||||||
|
String getExample();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a format description.
|
||||||
|
*
|
||||||
|
* @return A format <code>String</code>; it may be null
|
||||||
|
*/
|
||||||
|
String getFormat();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an encoded string value for a parameter from storage. Any
|
||||||
|
* errors encountered while reading are added to an error list.
|
||||||
|
* This class is counterpart to <code>ParameterWriter</code>.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see Parameter#write(ParameterWriter, Object)
|
||||||
|
* @see ErrorList
|
||||||
|
* @see ParameterWriter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface ParameterReader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an encoded <code>String</code> value for
|
||||||
|
* <code>param</code> from storage. If there are errors, they are
|
||||||
|
* added to <code>errors</code>.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> being read; it cannot
|
||||||
|
* be null
|
||||||
|
* @param errors The <code>ErrorList</code> that will collect any
|
||||||
|
* errors; it cannot be null
|
||||||
|
* @return The marshaled <code>String</code> value for
|
||||||
|
* <code>param</code>; it may be null
|
||||||
|
*/
|
||||||
|
String read(Parameter param, ErrorList errors);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* Writes encoded parameter values to storage. Implementors define
|
||||||
|
* the exact nature of the storage.
|
||||||
|
*
|
||||||
|
* @see Parameter#write(ParameterWriter,Object)
|
||||||
|
* @see ParameterReader
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public interface ParameterWriter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the marshaled <code>value</code> for parameter
|
||||||
|
* <code>param</code> to storage.
|
||||||
|
*
|
||||||
|
* @param param The <code>Parameter</code> that is being written;
|
||||||
|
* it cannot be null
|
||||||
|
* @param value The encoded <code>String</code> value to store for
|
||||||
|
* <code>param</code>; it may be null
|
||||||
|
*/
|
||||||
|
void write(Parameter param, String value);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter representing a JEE <code>Resource</code> (input stream).
|
||||||
|
*
|
||||||
|
* This takes in a path and makes sure that the resource exists either
|
||||||
|
* as a File or an actual resource. If it does, it returns the
|
||||||
|
* InputStream for the given Resource. If it does not, and if it is
|
||||||
|
* required, it logs an error. Otherwise, it returns null.
|
||||||
|
*
|
||||||
|
* Development note / CHANGELOG
|
||||||
|
* Had been deprecated for a while in favour of an URLParameter and a
|
||||||
|
* application specific resource: protocol extension (c.ad.util.protocol.resource).
|
||||||
|
* As of version 6.5 reverted to ResourceParameter to avoid non-standard extensions.
|
||||||
|
*
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @author Brett <bprucha@users.sourceforge net>
|
||||||
|
* @author PBoy <pboy@users.sourceforge net>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ResourceParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(ResourceParameter.class);
|
||||||
|
|
||||||
|
private Object m_default = null;
|
||||||
|
|
||||||
|
public ResourceParameter(final String name) {
|
||||||
|
super(name, InputStream.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaultValue) {
|
||||||
|
|
||||||
|
super(name, multiplicity, defaultValue, InputStream.class);
|
||||||
|
m_default = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default value and return it as InputStream.
|
||||||
|
*
|
||||||
|
* Developers note:
|
||||||
|
* This makes the trick to use Parameter.java interface rsp AbstractParameter
|
||||||
|
* for other types of parameter as String. If you don't overwrite this
|
||||||
|
* method, you will always get a casting error, because the parameter
|
||||||
|
* returns a string instead of the intended object!
|
||||||
|
*
|
||||||
|
* @return default value as InputStream
|
||||||
|
*/
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
|
||||||
|
if(m_default instanceof String) {
|
||||||
|
ErrorList errors = new ErrorList();
|
||||||
|
InputStream stream = (InputStream)unmarshal((String)m_default, errors);
|
||||||
|
|
||||||
|
if(!errors.isEmpty()) {
|
||||||
|
String strErrors = "";
|
||||||
|
for(Iterator i = errors.iterator(); i.hasNext(); ) {
|
||||||
|
ParameterError pe = (ParameterError)i.next();
|
||||||
|
strErrors += pe.getMessage() + "\r\n";
|
||||||
|
}
|
||||||
|
throw new UncheckedWrapperException(strErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
} else
|
||||||
|
return m_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmarshals the encoded string value of the parameter to get the intended
|
||||||
|
* object type. It tries first to find a file of the specified name in the
|
||||||
|
* file system. If not successful it uses the classloader to find the file
|
||||||
|
* in the class path / jar files.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param errors
|
||||||
|
* @return parameter value as an InputStream
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Object unmarshal(String value, final ErrorList errors) {
|
||||||
|
|
||||||
|
// NOTE:
|
||||||
|
// This implementation will never find the file in the file system.
|
||||||
|
// The name has to be specified relativ to document root. So we must
|
||||||
|
// precede value with the context path, e.g. using
|
||||||
|
// c.ad.runtime.CCMResourceManager as soon as it's implementation is
|
||||||
|
// fixed / stable (when all modifications of the runtime environment
|
||||||
|
// are done).
|
||||||
|
File file = new File(value);
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
// it is not a standard file so lets try to see if it
|
||||||
|
// is a resource
|
||||||
|
if (value.startsWith("/")) {
|
||||||
|
value = value.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassLoader cload = Thread.currentThread().getContextClassLoader();
|
||||||
|
URL url = cload.getResource(value);
|
||||||
|
InputStream stream = cload.getResourceAsStream(value);
|
||||||
|
if (stream == null && isRequired()) {
|
||||||
|
s_log.error(value + " is not a valid file and is required");
|
||||||
|
|
||||||
|
final ParameterError error = new ParameterError
|
||||||
|
(this, "Resource not found");
|
||||||
|
errors.add(error);
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return new FileInputStream(file);
|
||||||
|
} catch (FileNotFoundException ioe) {
|
||||||
|
// we know the file exists so this should not
|
||||||
|
// be an issue
|
||||||
|
s_log.error(value + " is not a valid file and is required", ioe);
|
||||||
|
|
||||||
|
errors.add(new ParameterError(this, ioe));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Classes;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter representing an instance of a Java class.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class SingletonParameter extends ClassParameter {
|
||||||
|
|
||||||
|
public SingletonParameter(final String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SingletonParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String marshal(Object value) {
|
||||||
|
return super.marshal(value.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object unmarshal(final String value, final ErrorList errors) {
|
||||||
|
final Class clacc = (Class) super.unmarshal(value, errors);
|
||||||
|
if(clacc == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Classes.newInstance(clacc);
|
||||||
|
} catch (UncheckedWrapperException uwe) {
|
||||||
|
errors.add(new ParameterError(this, uwe.getRootCause()));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter representing a Java <code>Class</code> which is checked to be
|
||||||
|
* an implementation of a required class / interface.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see java.lang.Class
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class SpecificClassParameter extends ClassParameter {
|
||||||
|
|
||||||
|
|
||||||
|
private Class m_requiredClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param name
|
||||||
|
* @param multiplicity
|
||||||
|
* @param defaultObj
|
||||||
|
* @param requiredClass
|
||||||
|
*/
|
||||||
|
public SpecificClassParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaultObj,
|
||||||
|
final Class requiredClass) {
|
||||||
|
super(name, multiplicity, defaultObj);
|
||||||
|
m_requiredClass = requiredClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmarshals a string representation of the parameter.
|
||||||
|
*
|
||||||
|
* @param value string representation of class, must be value != null
|
||||||
|
* @param errors
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Object unmarshal(String value, ErrorList errors) {
|
||||||
|
Class theClass = (Class) super.unmarshal(value,errors);
|
||||||
|
if (theClass != null) {
|
||||||
|
if (!m_requiredClass.isAssignableFrom(theClass)) {
|
||||||
|
errors.add(new ParameterError(this, "class " + value +
|
||||||
|
" must implement : " +
|
||||||
|
m_requiredClass.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return theClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 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.util.parameter;
|
||||||
|
|
||||||
|
// import com.arsdigita.util.parameter.StringParameter;
|
||||||
|
// import com.arsdigita.util.parameter.ErrorList;
|
||||||
|
import com.arsdigita.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StringArrayParameter
|
||||||
|
*
|
||||||
|
* Usage Example:
|
||||||
|
* <pre>
|
||||||
|
* private static parameter exampleName ;
|
||||||
|
* exampleName = new StringArrayParameter(
|
||||||
|
* "com.arsdigita.package.example_name",
|
||||||
|
* Parameter.REQUIRED,
|
||||||
|
* new String[] {"String Example 01","String Example 02"}
|
||||||
|
* );
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class StringArrayParameter extends StringParameter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param name: String literal
|
||||||
|
* @param multiplicity Indicator wether required (1) or not (0) (nullable)
|
||||||
|
* @param defaalt default value
|
||||||
|
*/
|
||||||
|
public StringArrayParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a String[] object into a literal representation.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String marshal(final Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return StringUtils.join((String[])value, ',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param literal
|
||||||
|
* @param errors
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Object unmarshal(final String literal,
|
||||||
|
final ErrorList errors) {
|
||||||
|
final String[] literals = StringUtils.split(literal, ',');
|
||||||
|
final String[] strings = new String[literals.length];
|
||||||
|
|
||||||
|
for (int i = 0; i < literals.length; i++) {
|
||||||
|
final String elem = literals[i];
|
||||||
|
|
||||||
|
strings[i] = (String) super.unmarshal(elem, errors);
|
||||||
|
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doValidate(final Object value,
|
||||||
|
final ErrorList errors) {
|
||||||
|
if (value != null) {
|
||||||
|
final String[] strings = (String[]) value;
|
||||||
|
|
||||||
|
for (int i = 0; i < strings.length; i++) {
|
||||||
|
super.doValidate(strings[i], errors);
|
||||||
|
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import org.apache.commons.beanutils.converters.StringConverter;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter representing a Java <code>String</code>.
|
||||||
|
*
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* @see java.lang.String
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class StringParameter extends AbstractParameter {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(StringParameter.class);
|
||||||
|
|
||||||
|
static {
|
||||||
|
logger.debug("Static initalizer starting...");
|
||||||
|
Converters.set(String.class, new StringConverter());
|
||||||
|
logger.debug("Static initalizer finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringParameter(final String name) {
|
||||||
|
super(name, String.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.util.parameter;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* A parameter representing a Java <code>URL</code>.
|
||||||
|
*
|
||||||
|
* @see java.net.URL
|
||||||
|
* @see Parameter
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class URLParameter extends StringParameter {
|
||||||
|
|
||||||
|
public URLParameter(final String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public URLParameter(final String name,
|
||||||
|
final int multiplicity,
|
||||||
|
final Object defaalt) {
|
||||||
|
super(name, multiplicity, defaalt);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object unmarshal(final String value, final ErrorList errors) {
|
||||||
|
try {
|
||||||
|
return new URL(value);
|
||||||
|
} catch (MalformedURLException mue) {
|
||||||
|
errors.add(new ParameterError(this, mue));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,609 @@
|
||||||
|
/*
|
||||||
|
* 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.xml;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import org.w3c.dom.NamedNodeMap;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper class that implements some functionality of
|
||||||
|
* <code>org.jdom.Element</code> using <code>org.w3c.dom.Element</code>.
|
||||||
|
*
|
||||||
|
* @author Patrick McNeill
|
||||||
|
* @since ACS 4.5a
|
||||||
|
* @version $Revision$ $Date$
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class Element {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(Element.class.getName());
|
||||||
|
protected org.w3c.dom.Element m_element;
|
||||||
|
/* DOM element that is being wrapped */
|
||||||
|
/**
|
||||||
|
* owner document
|
||||||
|
*/
|
||||||
|
private org.w3c.dom.Document m_doc;
|
||||||
|
|
||||||
|
private static ThreadLocal s_localDocument = new ThreadLocal() {
|
||||||
|
@Override
|
||||||
|
public Object initialValue() {
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory builder =
|
||||||
|
DocumentBuilderFactory.newInstance();
|
||||||
|
builder.setNamespaceAware(true);
|
||||||
|
return builder.newDocumentBuilder().newDocument();
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
s_log.error(e);
|
||||||
|
throw new UncheckedWrapperException(
|
||||||
|
"INTERNAL: Could not create thread local DOM document.",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
private static org.w3c.dom.Document getDocument() {
|
||||||
|
return (org.w3c.dom.Document) s_localDocument.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// public org.w3c.dom.Document getOwnerDocument() {
|
||||||
|
// if (null == m_doc) {
|
||||||
|
// m_doc = (org.w3c.dom.Document) s_localDocument.get();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return m_doc;
|
||||||
|
// }
|
||||||
|
// public void importElement(final Element element) {
|
||||||
|
// element.m_element = (org.w3c.dom.Element) this.m_element
|
||||||
|
// .getOwnerDocument().importNode(element.m_element,
|
||||||
|
// true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void syncDocs() {
|
||||||
|
if (m_doc == null) {
|
||||||
|
m_doc = (org.w3c.dom.Document) s_localDocument.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_element.getOwnerDocument().equals(m_doc)) {
|
||||||
|
m_element = (org.w3c.dom.Element) m_doc.importNode(m_element, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protected constructor to set up factories, etc. Does not actually
|
||||||
|
* create a new element. Used if we are programatically setting the
|
||||||
|
* m_element field later.
|
||||||
|
*/
|
||||||
|
protected Element() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element with the given name and no assigned namespace.
|
||||||
|
*
|
||||||
|
* @param name the name of the element
|
||||||
|
*/
|
||||||
|
public Element(String name) {
|
||||||
|
this();
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
|
||||||
|
m_element = getDocument().createElement(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element with the given name, and assigns it to the
|
||||||
|
* namespace defined at <code>uri</code>. The namespace prefix is
|
||||||
|
* automatically determined.
|
||||||
|
*
|
||||||
|
* @param name the name of the element
|
||||||
|
* @param uri the URI for the namespace definition
|
||||||
|
*/
|
||||||
|
public Element(String name, String uri) {
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
Assert.exists(uri, String.class);
|
||||||
|
|
||||||
|
m_element = getDocument().createElementNS(uri, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element and adds it as a child to this
|
||||||
|
* element. <code>elt.newChildElement("newElt")</code> is
|
||||||
|
* equivalent to
|
||||||
|
* <pre>
|
||||||
|
* Element newElt = new Element("newElt");
|
||||||
|
* elt.addChild(newElt);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param name the name of the element
|
||||||
|
* @return the created child element.
|
||||||
|
* @pre m_element != null
|
||||||
|
*/
|
||||||
|
public Element newChildElement(String name) {
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
|
||||||
|
if (m_doc == null) {
|
||||||
|
m_doc = this.m_element.getOwnerDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
Element result = new Element();
|
||||||
|
result.m_element = m_doc.createElement(name);
|
||||||
|
this.m_element.appendChild(result.m_element);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element. Adds it as a child to this element
|
||||||
|
* element and assigns it to the namespace defined at <code>uri</code>.
|
||||||
|
* <code>elt.newChildElement("newElt", namespace)</code> is
|
||||||
|
* equivalent to
|
||||||
|
* <pre>
|
||||||
|
* Element newElt = new Element("newElt", namespace);
|
||||||
|
* elt.addChild(newElt);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param name the name of the Element
|
||||||
|
* @param uri the URI for the namespace definition
|
||||||
|
* @return the created child element.
|
||||||
|
* @pre m_element != null
|
||||||
|
*/
|
||||||
|
public Element newChildElement(String name, String uri) {
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
Assert.exists(uri, String.class);
|
||||||
|
|
||||||
|
if (m_doc == null) {
|
||||||
|
m_doc = this.m_element.getOwnerDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
Element result = new Element();
|
||||||
|
result.m_element = m_doc.createElementNS(uri, name);
|
||||||
|
this.m_element.appendChild(result.m_element);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the passed in element and all of its children to a new
|
||||||
|
* Element.
|
||||||
|
*
|
||||||
|
* @param copyFrom
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Element newChildElement(Element copyFrom) {
|
||||||
|
Assert.exists(copyFrom, Element.class);
|
||||||
|
|
||||||
|
if (m_doc == null) {
|
||||||
|
m_doc = this.m_element.getOwnerDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
Element copyTo = new Element();
|
||||||
|
copyTo.m_element = m_doc.createElementNS(copyFrom.m_element.getNamespaceURI(), copyFrom.getName());
|
||||||
|
this.m_element.appendChild(copyTo.m_element);
|
||||||
|
newChildElementHelper(copyFrom, copyTo);
|
||||||
|
return copyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the passed in element and all of its children to a new
|
||||||
|
* Element using the passed-in name.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @param copyFrom
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Element newChildElement(String name, Element copyFrom) {
|
||||||
|
if (m_doc == null) {
|
||||||
|
m_doc = this.m_element.getOwnerDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
Element copyTo = new Element();
|
||||||
|
copyTo.m_element = m_doc.createElement(name);
|
||||||
|
this.m_element.appendChild(copyTo.m_element);
|
||||||
|
newChildElementHelper(copyFrom, copyTo);
|
||||||
|
return copyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the passed in element and all of its children to a new
|
||||||
|
* Element using the passed-in name.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @param uri
|
||||||
|
* @param copyFrom
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Element newChildElement(String name, String uri, Element copyFrom) {
|
||||||
|
if (m_doc == null) {
|
||||||
|
m_doc = this.m_element.getOwnerDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
Element copyTo = new Element();
|
||||||
|
copyTo.m_element = m_doc.createElementNS(uri, name);
|
||||||
|
this.m_element.appendChild(copyTo.m_element);
|
||||||
|
newChildElementHelper(copyFrom, copyTo);
|
||||||
|
return copyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void newChildElementHelper(Element copyFrom, Element copyTo) {
|
||||||
|
copyTo.setText(copyFrom.getText());
|
||||||
|
|
||||||
|
|
||||||
|
NamedNodeMap nnm = copyFrom.m_element.getAttributes();
|
||||||
|
|
||||||
|
if (nnm != null) {
|
||||||
|
for (int i = 0; i < nnm.getLength(); i++) {
|
||||||
|
Attr attr = (org.w3c.dom.Attr) nnm.item(i);
|
||||||
|
copyTo.addAttribute(attr.getName(), attr.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator iter = copyFrom.getChildren().iterator();
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Element child = (Element) iter.next();
|
||||||
|
copyTo.newChildElement(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an attribute to the element.
|
||||||
|
*
|
||||||
|
* @param name the name of the attribute
|
||||||
|
* @param value the value of the attribute
|
||||||
|
* @return this element.
|
||||||
|
*/
|
||||||
|
public Element addAttribute(String name, String value) {
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
|
||||||
|
m_element.setAttribute(name, value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element addAttribute(String name,
|
||||||
|
String value,
|
||||||
|
String ns) {
|
||||||
|
Assert.exists(name, String.class);
|
||||||
|
Assert.exists(ns, String.class);
|
||||||
|
|
||||||
|
m_element.setAttributeNS(ns, name, value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a child element to this element.
|
||||||
|
*
|
||||||
|
* @param newContent the new child element
|
||||||
|
* @return this element.
|
||||||
|
*/
|
||||||
|
public Element addContent(Element newContent) {
|
||||||
|
Assert.exists(newContent, Element.class);
|
||||||
|
|
||||||
|
newContent.importInto(m_element.getOwnerDocument());
|
||||||
|
m_element.appendChild(newContent.getInternalElement());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the text value of the current element (the part between the
|
||||||
|
* tags). If the passed in text is null then it is converted to
|
||||||
|
* the empty string.
|
||||||
|
*
|
||||||
|
* @param text the text to include
|
||||||
|
* @return this element.
|
||||||
|
*/
|
||||||
|
public Element setText(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
// This converts the null to the empty string because
|
||||||
|
// org.w3c.dom does not like null and HTML does not
|
||||||
|
// differentiate between "" and null. The other option
|
||||||
|
// is to throw the NPE which causes other problems
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
org.w3c.dom.Text textElem =
|
||||||
|
m_element.getOwnerDocument().createTextNode(text);
|
||||||
|
m_element.appendChild(textElem);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the concatenation of all the text in all child nodes
|
||||||
|
* of the current element.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getText() {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
|
org.w3c.dom.NodeList nl = m_element.getChildNodes();
|
||||||
|
|
||||||
|
for (int i = 0; i < nl.getLength(); i++) {
|
||||||
|
org.w3c.dom.Node n = nl.item(i);
|
||||||
|
|
||||||
|
if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
|
||||||
|
result.append(((org.w3c.dom.Text) n).getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Element setCDATASection(String cdata) {
|
||||||
|
s_log.debug("Setting CDATA section to '" + cdata + "'.");
|
||||||
|
|
||||||
|
if (cdata == null) {
|
||||||
|
cdata = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
org.w3c.dom.CDATASection cdataSection =
|
||||||
|
m_element.getOwnerDocument().createCDATASection(cdata);
|
||||||
|
|
||||||
|
m_element.appendChild(cdataSection);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCDATASection() {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
|
org.w3c.dom.NodeList nl = m_element.getChildNodes();
|
||||||
|
|
||||||
|
for (int i = 0; i < nl.getLength(); i++) {
|
||||||
|
org.w3c.dom.Node n = nl.item(i);
|
||||||
|
|
||||||
|
if (n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
|
||||||
|
result.append(((org.w3c.dom.CDATASection) n).getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String str = result.toString();
|
||||||
|
|
||||||
|
s_log.debug("Fetched this from CDATA section: " + str);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a <code>List</code> of all the child elements nested
|
||||||
|
* directly (one level deep) within this element, as <code>Element</code>
|
||||||
|
* objects. If this target element has no nested elements, an empty
|
||||||
|
* <code>List</code> is returned. The returned list is "live", so
|
||||||
|
* changes to it affect the element's actual contents.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* This performs no recursion, so elements nested two levels deep would
|
||||||
|
* have to be obtained with:
|
||||||
|
* <pre>
|
||||||
|
* Iterator itr = currentElement.getChildren().iterator();
|
||||||
|
* while (itr.hasNext()) {
|
||||||
|
* Element oneLevelDeep = (Element)nestedElements.next();
|
||||||
|
* List twoLevelsDeep = oneLevelDeep.getChildren();
|
||||||
|
* // Do something with these children
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* @return list of child <code>Element</code> objects for this element.
|
||||||
|
*/
|
||||||
|
public java.util.List getChildren() {
|
||||||
|
java.util.List retval = new java.util.ArrayList();
|
||||||
|
org.w3c.dom.NodeList nl = m_element.getChildNodes();
|
||||||
|
for (int i = 0; i < nl.getLength(); i++) {
|
||||||
|
org.w3c.dom.Node n = nl.item(i);
|
||||||
|
if (n instanceof org.w3c.dom.Element) {
|
||||||
|
Element elt = new Element();
|
||||||
|
elt.m_element = (org.w3c.dom.Element) n;
|
||||||
|
retval.add(elt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.Map getAttributes() {
|
||||||
|
// Retrieve the attributes of the DOM Element
|
||||||
|
org.w3c.dom.NamedNodeMap attributeNodeMap =
|
||||||
|
m_element.getAttributes();
|
||||||
|
|
||||||
|
// Create the HashMap that we will return the attributes
|
||||||
|
// in
|
||||||
|
java.util.HashMap returnMap = new java.util.HashMap();
|
||||||
|
|
||||||
|
// Copy the attribute values in the NamedNodeMap to the
|
||||||
|
// HashMap
|
||||||
|
for (int i = 0; i < attributeNodeMap.getLength(); ++i) {
|
||||||
|
// Get the Node
|
||||||
|
org.w3c.dom.Node attributeNode = attributeNodeMap.item(i);
|
||||||
|
// Copy the name and value to the map
|
||||||
|
returnMap.put(attributeNode.getNodeName(),
|
||||||
|
attributeNode.getNodeValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the HashMap
|
||||||
|
return returnMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an attribute value by name.
|
||||||
|
* @param name The name of the attribute to retrieve
|
||||||
|
* @return The Attr value as a string,
|
||||||
|
* or the empty string if that attribute does not have a specified
|
||||||
|
* or default value.
|
||||||
|
*/
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
return m_element.getAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAttribute(String name) {
|
||||||
|
return m_element.hasAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return m_element.getTagName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to allow this class to interact appropriately with the
|
||||||
|
* Document class (for example, allows nodes to be moved around,
|
||||||
|
* and so on).
|
||||||
|
*
|
||||||
|
* @return the internal DOM Element.
|
||||||
|
*/
|
||||||
|
protected final org.w3c.dom.Element getInternalElement() {
|
||||||
|
return m_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports the internal node into another document.
|
||||||
|
* This could also be done with a combination of getInternalElement
|
||||||
|
* and a setInternalElement function.
|
||||||
|
*
|
||||||
|
* @param doc the org.w3c.dom.Document to import into
|
||||||
|
*/
|
||||||
|
protected void importInto(org.w3c.dom.Document doc) {
|
||||||
|
/*
|
||||||
|
Exception e = new Exception();
|
||||||
|
java.io.StringWriter sw = new java.io.StringWriter();
|
||||||
|
e.printStackTrace(new java.io.PrintWriter(sw));
|
||||||
|
System.out.println(sw.toString().substring(0, 300));
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_element = (org.w3c.dom.Element) doc.importNode(m_element, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workaround for bug in some versions of Xerces.
|
||||||
|
* For some reason, importNode doesn't also copy attribute
|
||||||
|
* values unless you call getValue() on them first. This may
|
||||||
|
* be fixed in a later version of Xerces. In the meantime,
|
||||||
|
* calling visitAllAttributes(node) before importNode should
|
||||||
|
* help.
|
||||||
|
*
|
||||||
|
* @param node the org.w3c.dom.Node about to be imported
|
||||||
|
* @deprecated with no replacement, 1 May 2003
|
||||||
|
*/
|
||||||
|
public static void visitAllAttributes(org.w3c.dom.Node node) {
|
||||||
|
org.w3c.dom.NamedNodeMap nnm = node.getAttributes();
|
||||||
|
if (nnm != null) {
|
||||||
|
for (int i = 0; i < nnm.getLength(); i++) {
|
||||||
|
org.w3c.dom.Attr attr = (org.w3c.dom.Attr) nnm.item(i);
|
||||||
|
attr.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
org.w3c.dom.NodeList nl = node.getChildNodes();
|
||||||
|
if (nl != null) {
|
||||||
|
for (int i = 0; i < nl.getLength(); i++) {
|
||||||
|
visitAllAttributes(nl.item(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrieve an unordered list of strings relating to node tree including
|
||||||
|
* and below the current element. Strings include element names, attribute names,
|
||||||
|
* attribute values, text and CData sections
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List getXMLFragments() {
|
||||||
|
|
||||||
|
List unsortedList = new ArrayList();
|
||||||
|
unsortedList.add(getName());
|
||||||
|
unsortedList.add(getText());
|
||||||
|
// CData sections are not included in getChildren()
|
||||||
|
unsortedList.add(getCDATASection());
|
||||||
|
Iterator it = getAttributes().entrySet().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
java.util.Map.Entry entry = (java.util.Map.Entry) it.next();
|
||||||
|
unsortedList.add(entry.getKey());
|
||||||
|
unsortedList.add(entry.getValue());
|
||||||
|
}
|
||||||
|
Iterator childElements = getChildren().iterator();
|
||||||
|
while (childElements.hasNext()) {
|
||||||
|
Element el = (Element) childElements.next();
|
||||||
|
unsortedList.addAll(el.getXMLFragments());
|
||||||
|
}
|
||||||
|
return unsortedList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrieve a string that is an ordered concatenation of all information describing
|
||||||
|
* this node and its subnodes, suitable as the basis of a hashCode or equals
|
||||||
|
* implementation.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected String getXMLHashString() {
|
||||||
|
// attributes and child nodes are retrieved as HashMap and List
|
||||||
|
// respectively. These make no guarantees about the order of
|
||||||
|
// iteration, and so we sort here to make sure the same element
|
||||||
|
// will return the same XMLHash
|
||||||
|
List sortedList = getXMLFragments();
|
||||||
|
Collections.sort(sortedList);
|
||||||
|
StringBuilder xml = new StringBuilder();
|
||||||
|
Iterator xmlFragments = sortedList.iterator();
|
||||||
|
while (xmlFragments.hasNext()) {
|
||||||
|
xml.append(xmlFragments.next());
|
||||||
|
}
|
||||||
|
s_log.debug("getXMLHashString: " + xml.toString());
|
||||||
|
return xml.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
Date start = new Date();
|
||||||
|
String hashString = getXMLHashString();
|
||||||
|
s_log.debug(
|
||||||
|
"hashCode: getXMLString took "
|
||||||
|
+ (new Date().getTime() - start.getTime())
|
||||||
|
+ " millisecs");
|
||||||
|
|
||||||
|
return hashString.hashCode();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
s_log.debug("equals invoked");
|
||||||
|
Date start = new Date();
|
||||||
|
if (other == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!other.getClass().equals(Element.class)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Element otherElement = (Element) other;
|
||||||
|
String thisXML = getXMLHashString();
|
||||||
|
String otherXML = otherElement.getXMLHashString();
|
||||||
|
s_log.debug(
|
||||||
|
"Equals: getXMLString twice took "
|
||||||
|
+ (new Date().getTime() - start.getTime())
|
||||||
|
+ " millisecs");
|
||||||
|
return thisXML.equals(otherXML);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.xml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface providing an API for converting an object
|
||||||
|
* to a string. Thus instead of doing
|
||||||
|
* <pre>
|
||||||
|
* Date today = new Date();
|
||||||
|
* element.addAttribute("today", date.toString());
|
||||||
|
* </pre>
|
||||||
|
* we can do:
|
||||||
|
* <pre>
|
||||||
|
* Date today = new Date();
|
||||||
|
* element.addAttribute("today", XML.format(date));
|
||||||
|
* </pre>
|
||||||
|
* Or if you require a non-default format:
|
||||||
|
* <pre>
|
||||||
|
* Date today = new Date();
|
||||||
|
* element.addAttribute("today", new DateTimeFormatter.format(today));
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public interface Formatter {
|
||||||
|
String format(Object value);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,284 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.xml;
|
||||||
|
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
|
||||||
|
import com.arsdigita.xml.formatters.DateTimeFormatter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.parsers.SAXParser;
|
||||||
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
|
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a set of static helper methods for dealing with XML,
|
||||||
|
* including file parsing & object -> string serialization
|
||||||
|
*/
|
||||||
|
public class XML {
|
||||||
|
|
||||||
|
private static final Logger s_log = Logger.getLogger(XML.class);
|
||||||
|
|
||||||
|
// private static XMLConfig s_config;
|
||||||
|
|
||||||
|
private static final Map s_formatters = new HashMap();
|
||||||
|
static {
|
||||||
|
s_log.debug("Static initalizer starting...");
|
||||||
|
s_formatters.put(Date.class, new DateTimeFormatter());
|
||||||
|
s_log.debug("Static initalizer finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. All methods are static, no initialization required.
|
||||||
|
*/
|
||||||
|
private XML() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current configuration
|
||||||
|
public static XMLConfig getConfig() {
|
||||||
|
if (s_config == null) {
|
||||||
|
s_config = new XMLConfig();
|
||||||
|
s_config.load();
|
||||||
|
}
|
||||||
|
return s_config;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a formatter for serializing objects of a
|
||||||
|
* class to a String suitable for XML output.
|
||||||
|
* @param klass
|
||||||
|
* @param formatter
|
||||||
|
*/
|
||||||
|
public static void registerFormatter(Class klass,
|
||||||
|
Formatter formatter) {
|
||||||
|
s_formatters.put(klass, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a formatter against a class.
|
||||||
|
* @param klass
|
||||||
|
*/
|
||||||
|
public static void unregisterFormatter(Class klass) {
|
||||||
|
s_formatters.remove(klass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a directly registered formatter for a class.
|
||||||
|
* @param klass the class to find a formatter for
|
||||||
|
* @return the formatter, or null if non is registered
|
||||||
|
*/
|
||||||
|
public static Formatter getFormatter(Class klass) {
|
||||||
|
return (Formatter)s_formatters.get(klass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for the best matching formatter.
|
||||||
|
*
|
||||||
|
* @param klass the class to find a formatter for
|
||||||
|
* @return the formatter, or null if non is registered
|
||||||
|
*/
|
||||||
|
public static Formatter findFormatter(Class klass) {
|
||||||
|
Formatter formatter = null;
|
||||||
|
while (formatter == null && klass != null) {
|
||||||
|
formatter = getFormatter(klass);
|
||||||
|
klass = klass.getSuperclass();
|
||||||
|
}
|
||||||
|
return formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an object to a String using the closest
|
||||||
|
* matching registered Formatter implementation. Looks
|
||||||
|
* for a formatter registered against the object's
|
||||||
|
* class first, then its superclass, etc. If no formatter
|
||||||
|
* is found, uses the toString() method.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String format(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof String) {
|
||||||
|
return (String)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Formatter formatter = findFormatter(value.getClass());
|
||||||
|
if (formatter == null) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("No formatter for " + value.getClass());
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Processing " + value.getClass() +
|
||||||
|
" with " + formatter.getClass());
|
||||||
|
}
|
||||||
|
return formatter.format(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes an XML file with the default SAX Parser, with
|
||||||
|
* namespace processing, schema validation & DTD validation
|
||||||
|
* enabled.
|
||||||
|
*
|
||||||
|
* @param path the XML file relative to the webapp root
|
||||||
|
* @param handler the content handler
|
||||||
|
*/
|
||||||
|
public static final void parseResource(String path,
|
||||||
|
DefaultHandler handler) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Processing resource " + path +
|
||||||
|
" with " + handler.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassLoader cload = Thread.currentThread().getContextClassLoader();
|
||||||
|
InputStream stream = cload.getResourceAsStream(path);
|
||||||
|
|
||||||
|
if (stream == null) {
|
||||||
|
throw new IllegalArgumentException("no such resource: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(stream, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes an XML file with the default SAX Parser, with
|
||||||
|
* namespace processing, schema validation & DTD validation
|
||||||
|
* enabled.
|
||||||
|
*
|
||||||
|
* @param source the xml input stream
|
||||||
|
* @param handler the content handler
|
||||||
|
*/
|
||||||
|
public static final void parse(InputStream source,
|
||||||
|
DefaultHandler handler) {
|
||||||
|
if (s_log.isDebugEnabled()) {
|
||||||
|
s_log.debug("Processing stream " + source +
|
||||||
|
" with " + handler.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// ToDo (pboy): We should use
|
||||||
|
// SAXParserFactory.newInstance(String clName, ClassLoader clLoader)
|
||||||
|
// instead to achieve independence of a JVM wide acceptable
|
||||||
|
// configuration (affecting all CCM instances which may run in a
|
||||||
|
// container).
|
||||||
|
// Requires additional modifications in c.ad.util.xml.XML
|
||||||
|
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||||
|
spf.setFeature("http://xml.org/sax/features/namespaces", true);
|
||||||
|
SAXParser parser = spf.newSAXParser();
|
||||||
|
parser.parse(source, handler);
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
throw new UncheckedWrapperException("error parsing stream", e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
if (e.getException() != null) {
|
||||||
|
throw new UncheckedWrapperException("error parsing stream",
|
||||||
|
e.getException());
|
||||||
|
} else {
|
||||||
|
throw new UncheckedWrapperException("error parsing stream", e);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedWrapperException("error parsing stream", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This visitor is called by {@link #traverse(Element, int, XML.Action)}.
|
||||||
|
**/
|
||||||
|
public interface Action {
|
||||||
|
void apply(Element elem, int level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the skeleton structure of the element to the supplied print
|
||||||
|
* writer.
|
||||||
|
* @param element
|
||||||
|
* @param writer
|
||||||
|
**/
|
||||||
|
public static void toSkeleton(final Element element,
|
||||||
|
final PrintWriter writer) {
|
||||||
|
|
||||||
|
XML.traverse(element, 0, new Action() {
|
||||||
|
@Override
|
||||||
|
public void apply(Element elem, int level) {
|
||||||
|
final String padding = " ";
|
||||||
|
for (int ii=0; ii<level; ii++) {
|
||||||
|
writer.print(padding);
|
||||||
|
}
|
||||||
|
writer.print(elem.getName());
|
||||||
|
Iterator attrs = elem.getAttributes().keySet().iterator();
|
||||||
|
while (attrs.hasNext()) {
|
||||||
|
writer.print(" @");
|
||||||
|
writer.print((String) attrs.next());
|
||||||
|
}
|
||||||
|
writer.println("");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a wrapper for {@link #toSkeleton(Element, PrintWriter)}.
|
||||||
|
*
|
||||||
|
* @param element
|
||||||
|
* @return
|
||||||
|
**/
|
||||||
|
public static String toSkeleton(Element element) {
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(writer);
|
||||||
|
XML.toSkeleton(element, pw);
|
||||||
|
pw.close();
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-order, depth-first traversal.
|
||||||
|
*
|
||||||
|
* @param elem
|
||||||
|
* @param level
|
||||||
|
* @param action
|
||||||
|
**/
|
||||||
|
public static void traverse(Element elem, int level, Action action) {
|
||||||
|
action.apply(elem, level);
|
||||||
|
final Iterator children=elem.getChildren().iterator();
|
||||||
|
while (children.hasNext()) {
|
||||||
|
XML.traverse((Element) children.next(), level+1, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.xml.formatters;
|
||||||
|
|
||||||
|
import com.arsdigita.xml.Formatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternate formatter for java.util.Date objects, outputting the date in
|
||||||
|
* 'medium' format. The time is omitted.
|
||||||
|
*
|
||||||
|
* @author unknown
|
||||||
|
* @author Sören Bernstein <quasi@quasiweb.de>
|
||||||
|
*/
|
||||||
|
public class DateFormatter implements Formatter {
|
||||||
|
|
||||||
|
private static DateFormatterConfig m_config;
|
||||||
|
|
||||||
|
public static final DateFormatterConfig getConfig() {
|
||||||
|
if (m_config == null) {
|
||||||
|
m_config = new DateFormatterConfig();
|
||||||
|
m_config.load();
|
||||||
|
}
|
||||||
|
return m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(Object value) {
|
||||||
|
Date date = (Date) value;
|
||||||
|
|
||||||
|
//Locale locale = GlobalizationHelper.getNegotiatedLocale();
|
||||||
|
final Locale locale = Locale.getDefault();
|
||||||
|
|
||||||
|
DateFormat format = DateFormat
|
||||||
|
.getDateInstance(DateFormat.MEDIUM, locale);
|
||||||
|
|
||||||
|
return format.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.arsdigita.xml.formatters;
|
||||||
|
|
||||||
|
|
||||||
|
import com.arsdigita.runtime.AbstractConfig;
|
||||||
|
import com.arsdigita.util.parameter.Parameter;
|
||||||
|
import com.arsdigita.util.parameter.StringParameter;
|
||||||
|
|
||||||
|
public final class DateFormatterConfig extends AbstractConfig {
|
||||||
|
|
||||||
|
private final Parameter m_locale;
|
||||||
|
|
||||||
|
public DateFormatterConfig() {
|
||||||
|
m_locale = new StringParameter("waf.xml.formatters.locale", Parameter.OPTIONAL, null);
|
||||||
|
register(m_locale);
|
||||||
|
loadInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getLocale() {
|
||||||
|
return (String) get (m_locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
waf.xml.formatters.locale.title=Locale language code (see http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt)
|
||||||
|
waf.xml.formatters.locale.purpose=If set will use this rather than the contexts locale. Useful for things that may be formatted differently in other locales, eg dates.
|
||||||
|
waf.xml.formatters.locale.example=en
|
||||||
|
waf.xml.formatters.locale.format=[string]
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.xml.formatters;
|
||||||
|
|
||||||
|
//import com.arsdigita.globalization.GlobalizationHelper;
|
||||||
|
import com.arsdigita.xml.Formatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default formatter for java.util.Date objects, outputing the date in
|
||||||
|
* 'medium' format and the time in 'short' format.
|
||||||
|
*
|
||||||
|
* @author unknown
|
||||||
|
* @author Sören Bernstein <quasi@quasiweb.de>
|
||||||
|
*/
|
||||||
|
public class DateTimeFormatter implements Formatter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(Object value) {
|
||||||
|
Date date = (Date) value;
|
||||||
|
//Locale locale = GlobalizationHelper.getNegotiatedLocale();
|
||||||
|
final Locale locale = Locale.getDefault();
|
||||||
|
|
||||||
|
DateFormat format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
|
||||||
|
DateFormat.SHORT, locale);
|
||||||
|
|
||||||
|
return format.format(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2005 Runtime Collective Ltd. 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.xml.formatters;
|
||||||
|
|
||||||
|
//import com.arsdigita.kernel.Kernel;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DateFormatter which displays dates as:
|
||||||
|
* <br>
|
||||||
|
* <yearNo> | <monthNo> | <dayOfMonthNo> | <dayOfWeekNo>
|
||||||
|
* | <hour> | <minute> | <second> | <apm> | <localised date>
|
||||||
|
* <br>
|
||||||
|
* the numbers are padded with 0s, so the positions of the fields are always
|
||||||
|
* 0, 7, 12, 17, 21, 26, 31, 36, 41 (in Java), and 1, 8, 13, 18, 22, 27, 32, 37, 42 (in XSL).
|
||||||
|
*/
|
||||||
|
public class FullDateFormatter extends DateFormatter {
|
||||||
|
|
||||||
|
public static String SEPARATOR = " | ";
|
||||||
|
public static String AM = "am";
|
||||||
|
public static String PM = "pm";
|
||||||
|
public static char ZERO = '0';
|
||||||
|
|
||||||
|
public String format(Object value) {
|
||||||
|
|
||||||
|
String parentResult = super.format(value);
|
||||||
|
|
||||||
|
// if (!XMLConfig.getConfig().getActivateFullTimeFormatter()) {
|
||||||
|
// return parentResult;
|
||||||
|
// }
|
||||||
|
|
||||||
|
Date date = (Date) value;
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
StringBuffer result = new StringBuffer(60);
|
||||||
|
|
||||||
|
cal.setTime(date);
|
||||||
|
|
||||||
|
append(result, cal.get(Calendar.YEAR));
|
||||||
|
appendMaybeSmall(result, cal.get(Calendar.MONTH));
|
||||||
|
appendMaybeSmall(result, cal.get(Calendar.DAY_OF_MONTH));
|
||||||
|
append(result, cal.get(Calendar.DAY_OF_WEEK));
|
||||||
|
appendMaybeSmall(result, cal.get(Calendar.HOUR));
|
||||||
|
appendMaybeSmall(result, cal.get(Calendar.MINUTE));
|
||||||
|
appendMaybeSmall(result, cal.get(Calendar.SECOND));
|
||||||
|
|
||||||
|
switch (cal.get(Calendar.AM_PM)) {
|
||||||
|
case Calendar.AM: result.append(AM); break;
|
||||||
|
case Calendar.PM: result.append(PM); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(SEPARATOR)
|
||||||
|
.append(parentResult);
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendMaybeSmall(StringBuffer sb, int value) {
|
||||||
|
if (value < 10) {
|
||||||
|
sb.append(ZERO);
|
||||||
|
}
|
||||||
|
append(sb, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void append(StringBuffer sb, int value) {
|
||||||
|
sb.append(value)
|
||||||
|
.append(SEPARATOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-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.xml.formatters;
|
||||||
|
|
||||||
|
import com.arsdigita.xml.Formatter;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternate formatter for java.util.Date objects,
|
||||||
|
* outputing the date in 'medium' format. The time
|
||||||
|
* is ommitted.
|
||||||
|
*
|
||||||
|
* @author unknown
|
||||||
|
* @author Sören Bernstein <quasi@quasiweb.de>
|
||||||
|
*/
|
||||||
|
public class TimeFormatter implements Formatter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(Object value) {
|
||||||
|
Date date = (Date) value;
|
||||||
|
|
||||||
|
// Locale locale = GlobalizationHelper.getNegotiatedLocale();
|
||||||
|
final Locale locale = Locale.getDefault();
|
||||||
|
|
||||||
|
DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
|
||||||
|
|
||||||
|
return format.format(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,23 +33,23 @@ public class CcmSessionContext implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 6110177865273823685L;
|
private static final long serialVersionUID = 6110177865273823685L;
|
||||||
|
|
||||||
private Party currentParty;
|
private Subject currentParty;
|
||||||
private Party effectiveParty;
|
private Subject effectiveParty;
|
||||||
|
|
||||||
public Party getCurrentParty() {
|
public Subject getCurrentParty() {
|
||||||
return currentParty;
|
return currentParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentParty(final Party currentParty) {
|
public void setCurrentParty(final Subject currentParty) {
|
||||||
this.currentParty = currentParty;
|
this.currentParty = currentParty;
|
||||||
this.effectiveParty = currentParty;
|
this.effectiveParty = currentParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Party getEffectiveParty() {
|
public Subject getEffectiveParty() {
|
||||||
return effectiveParty;
|
return effectiveParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setEffectiveParty(final Party effectiveParty) {
|
protected void setEffectiveParty(final Subject effectiveParty) {
|
||||||
this.effectiveParty = effectiveParty;
|
this.effectiveParty = effectiveParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ public class CcmSessionContext implements Serializable {
|
||||||
* @param party The party with which permissions the code is executed.
|
* @param party The party with which permissions the code is executed.
|
||||||
* @param runnable The code to execute.
|
* @param runnable The code to execute.
|
||||||
*/
|
*/
|
||||||
public void sudo(final Party party, final Runnable runnable) {
|
public void sudo(final Subject party, final Runnable runnable) {
|
||||||
//ToDo: Check if current user is permitted to use sudo.
|
//ToDo: Check if current user is permitted to use sudo.
|
||||||
|
|
||||||
effectiveParty = party;
|
effectiveParty = party;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "ccm_groups")
|
@Table(name = "ccm_groups")
|
||||||
@XmlRootElement(name = "user-group", namespace = CORE_XML_NS)
|
@XmlRootElement(name = "user-group", namespace = CORE_XML_NS)
|
||||||
public class Group extends Party implements Serializable {
|
public class Group extends Subject implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = -5555063356689597270L;
|
private static final long serialVersionUID = -5555063356689597270L;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ public class Permission implements Serializable {
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "grantee_id")
|
@JoinColumn(name = "grantee_id")
|
||||||
private Party grantee;
|
private Subject grantee;
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "granted_privilege_id")
|
@JoinColumn(name = "granted_privilege_id")
|
||||||
|
|
@ -94,11 +94,11 @@ public class Permission implements Serializable {
|
||||||
this.permissionId = permissionId;
|
this.permissionId = permissionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Party getGrantee() {
|
public Subject getGrantee() {
|
||||||
return grantee;
|
return grantee;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setGrantee(final Party grantee) {
|
protected void setGrantee(final Subject grantee) {
|
||||||
this.grantee = grantee;
|
this.grantee = grantee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,12 @@ import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.persistence.CollectionTable;
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
@ -44,16 +48,21 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "parties")
|
@Table(name = "subjects")
|
||||||
@XmlRootElement(name = "party", namespace = CORE_XML_NS)
|
@XmlRootElement(name = "subject", namespace = CORE_XML_NS)
|
||||||
public class Party extends CcmObject implements Serializable {
|
public class Subject implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 6303836654273293979L;
|
private static final long serialVersionUID = 6303836654273293979L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "subject_id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private long subjectId;
|
||||||
|
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
@CollectionTable(name = "party_email_addresses",
|
@CollectionTable(name = "subject_email_addresses",
|
||||||
joinColumns = {
|
joinColumns = {
|
||||||
@JoinColumn(name = "party_id")})
|
@JoinColumn(name = "subject_id")})
|
||||||
@Size(min = 1)
|
@Size(min = 1)
|
||||||
@XmlElementWrapper(name = "email-addresses", namespace = CORE_XML_NS)
|
@XmlElementWrapper(name = "email-addresses", namespace = CORE_XML_NS)
|
||||||
@XmlElement(name = "email-address", namespace = CORE_XML_NS)
|
@XmlElement(name = "email-address", namespace = CORE_XML_NS)
|
||||||
|
|
@ -66,12 +75,20 @@ public class Party extends CcmObject implements Serializable {
|
||||||
@XmlElement(name = "granted-permission", namespace = CORE_XML_NS)
|
@XmlElement(name = "granted-permission", namespace = CORE_XML_NS)
|
||||||
private List<Permission> grantedPermissions;
|
private List<Permission> grantedPermissions;
|
||||||
|
|
||||||
public Party() {
|
public Subject() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
grantedPermissions = new ArrayList<>();
|
grantedPermissions = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getSubjectId() {
|
||||||
|
return subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setSubjectId(final long subjectId) {
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
public List<EmailAddress> getEmailAddresses() {
|
public List<EmailAddress> getEmailAddresses() {
|
||||||
if (emailAddresses == null) {
|
if (emailAddresses == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -113,24 +130,25 @@ public class Party extends CcmObject implements Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hash = super.hashCode();
|
int hash = 7;
|
||||||
hash = 41 * hash + Objects.hashCode(emailAddresses);
|
hash = 53 * hash + (int) (subjectId ^ (subjectId >>> 32));
|
||||||
|
hash = 53 * hash + Objects.hashCode(emailAddresses);
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
if (!super.equals(obj)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!(obj instanceof Party)) {
|
if (!(obj instanceof Subject)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final Party other = (Party) obj;
|
final Subject other = (Subject) obj;
|
||||||
|
if (subjectId != other.getSubjectId()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!other.canEqual(this)) {
|
if (!other.canEqual(this)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -138,9 +156,24 @@ public class Party extends CcmObject implements Serializable {
|
||||||
return Objects.equals(emailAddresses, other.getEmailAddresses());
|
return Objects.equals(emailAddresses, other.getEmailAddresses());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canEqual(final Object obj) {
|
public boolean canEqual(final Object obj) {
|
||||||
return obj instanceof Party;
|
return obj instanceof Subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final String toString() {
|
||||||
|
return toString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(final String data) {
|
||||||
|
return String.format("%s{ "
|
||||||
|
+ "subjectId = %d, "
|
||||||
|
+ "emailAddresses = %s"
|
||||||
|
+ "%s}",
|
||||||
|
super.toString(),
|
||||||
|
subjectId,
|
||||||
|
Objects.toString(emailAddresses),
|
||||||
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +38,8 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||||
|
|
@ -47,11 +49,17 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||||
/**
|
/**
|
||||||
* The {@code User} entity stores the name and the password of a user along with
|
* The {@code User} entity stores the name and the password of a user along with
|
||||||
* some other informations.
|
* some other informations.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "ccm_users")
|
@Table(name = "ccm_users")
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name = "findUserByScreenName",
|
||||||
|
query = "SELECT u FROM User u WHERE u.screenName = :screenname"),
|
||||||
|
@NamedQuery(name = "findUserByEmail",
|
||||||
|
query = "SELECT u FROM User u JOIN u.emailAddresses e"
|
||||||
|
+ "WHERE e.address = :emailAddress")})
|
||||||
@XmlRootElement(name = "user", namespace = CORE_XML_NS)
|
@XmlRootElement(name = "user", namespace = CORE_XML_NS)
|
||||||
//Supressing a few warnings from PMD because they misleading here.
|
//Supressing a few warnings from PMD because they misleading here.
|
||||||
//User is perfectly fine class name, and the complexity is not to high...
|
//User is perfectly fine class name, and the complexity is not to high...
|
||||||
|
|
@ -59,7 +67,7 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||||
"PMD.CyclomaticComplexity",
|
"PMD.CyclomaticComplexity",
|
||||||
"PMD.StdCyclomaticComplexity",
|
"PMD.StdCyclomaticComplexity",
|
||||||
"PMD.ModifiedCyclomaticComplexity"})
|
"PMD.ModifiedCyclomaticComplexity"})
|
||||||
public class User extends Party implements Serializable {
|
public class User extends Subject implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 892038270064849732L;
|
private static final long serialVersionUID = 892038270064849732L;
|
||||||
|
|
||||||
|
|
@ -77,18 +85,18 @@ public class User extends Party implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A user name of the user. Usually an abbreviation of the users real name.
|
* A user name of the user. Usually an abbreviation of the users real name.
|
||||||
* For example a the <em>John Doe</em> might have the scree name
|
* For example a the <em>John Doe</em> might have the scree name
|
||||||
* <code>jdoe</code>. The screen name is used as user name for logins (if
|
* <code>jdoe</code>. The screen name is used as user name for logins (if
|
||||||
* the system if configured so, otherwise the email address of the user is
|
* the system if configured so, otherwise the email address of the user is
|
||||||
* used).
|
* used).
|
||||||
*/
|
*/
|
||||||
@Column(name = "screen_name", length = 255, nullable = false)
|
@Column(name = "screen_name", length = 255, nullable = false, unique = true)
|
||||||
@NotBlank
|
@NotBlank
|
||||||
@XmlElement(name = "screen-name", namespace = CORE_XML_NS)
|
@XmlElement(name = "screen-name", namespace = CORE_XML_NS)
|
||||||
private String screenName;
|
private String screenName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A user can be banned which means that he or she can't login into the
|
* A user can be banned which means that he or she can't login into the
|
||||||
* system anymore.
|
* system anymore.
|
||||||
*/
|
*/
|
||||||
@Column(name = "banned")
|
@Column(name = "banned")
|
||||||
|
|
@ -96,7 +104,8 @@ public class User extends Party implements Serializable {
|
||||||
private boolean banned;
|
private boolean banned;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alias for the user used in an another system for SSO, for example LDAP.
|
* An alias for the user used in an another system for SSO, for example
|
||||||
|
* LDAP.
|
||||||
*/
|
*/
|
||||||
@Column(name = "sso_login", length = 512)
|
@Column(name = "sso_login", length = 512)
|
||||||
@XmlElement(name = "sso-login", namespace = CORE_XML_NS)
|
@XmlElement(name = "sso-login", namespace = CORE_XML_NS)
|
||||||
|
|
@ -117,25 +126,25 @@ public class User extends Party implements Serializable {
|
||||||
private String salt;
|
private String salt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hash algorithm used to hash the password. This allows us
|
* The hash algorithm used to hash the password. This allows us the change
|
||||||
* the change to another, stronger hash algorithm without invalidating
|
* to another, stronger hash algorithm without invalidating existing
|
||||||
* existing accounts. The algorithm to use for new passwords can be
|
* accounts. The algorithm to use for new passwords can be configured by the
|
||||||
* configured by the administrator.
|
* administrator.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Column(name = "hash_algorithm", length = 64)
|
@Column(name = "hash_algorithm", length = 64)
|
||||||
@XmlTransient
|
@XmlTransient
|
||||||
private String hashAlgorithm;
|
private String hashAlgorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the user should be forced to change his or her password
|
* Indicates that the user should be forced to change his or her password on
|
||||||
* on the next login.
|
* the next login.
|
||||||
*/
|
*/
|
||||||
@Column(name = "password_reset_required")
|
@Column(name = "password_reset_required")
|
||||||
private boolean passwordResetRequired;
|
private boolean passwordResetRequired;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Question the recover a forgotten password.
|
* Question the recover a forgotten password.
|
||||||
*/
|
*/
|
||||||
@Column(name = "password_question", length = 2048)
|
@Column(name = "password_question", length = 2048)
|
||||||
@XmlElement(name = "password-question", namespace = CORE_XML_NS)
|
@XmlElement(name = "password-question", namespace = CORE_XML_NS)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides complex operations on {@link User} objects like updating
|
||||||
|
* the password. To use this class add an injection point to your class.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class UserManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link UserRepository} for interacting with the database. The method
|
||||||
|
* takes care of hashing the password with random salt.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private transient UserRepository userRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the password of an user.
|
||||||
|
*
|
||||||
|
* @param user The user whose password is to be updated.
|
||||||
|
* @param password The new password.
|
||||||
|
*/
|
||||||
|
public void updatePassword(final User user, final String password) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Random random = new Random(System.currentTimeMillis());
|
||||||
|
final byte[] passwordBytes = password.getBytes("UTF-8");
|
||||||
|
final byte[] salt = new byte[getSaltLength()];
|
||||||
|
random.nextBytes(salt);
|
||||||
|
|
||||||
|
final byte[] saltedPassword = new byte[passwordBytes.length
|
||||||
|
+ salt.length];
|
||||||
|
System.arraycopy(passwordBytes,
|
||||||
|
0,
|
||||||
|
saltedPassword,
|
||||||
|
0,
|
||||||
|
passwordBytes.length);
|
||||||
|
System.arraycopy(salt,
|
||||||
|
0,
|
||||||
|
saltedPassword,
|
||||||
|
passwordBytes.length,
|
||||||
|
salt.length);
|
||||||
|
final MessageDigest digest = MessageDigest.getInstance(
|
||||||
|
getHashAlgorithm());
|
||||||
|
final byte[] hashedBytes = digest.digest(saltedPassword);
|
||||||
|
|
||||||
|
final String hashedPassword = new String(hashedBytes, "UTF-8");
|
||||||
|
|
||||||
|
user.setPassword(hashedPassword);
|
||||||
|
userRepository.save(user);
|
||||||
|
|
||||||
|
} catch (NoSuchAlgorithmException ex) {
|
||||||
|
throw new RuntimeException(String.format(
|
||||||
|
"Configured hash algorithm '%s 'is not available.",
|
||||||
|
getHashAlgorithm()), ex);
|
||||||
|
} catch (UnsupportedEncodingException ex) {
|
||||||
|
throw new RuntimeException("UTF-8 charset is not supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the hash algorithm to use.
|
||||||
|
*
|
||||||
|
* ToDo: Make configurable.
|
||||||
|
*
|
||||||
|
* @return At the moment SHA-512, will be made configurable.
|
||||||
|
*/
|
||||||
|
private String getHashAlgorithm() {
|
||||||
|
return "SHA-512";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length for the salt (number of bytes).
|
||||||
|
*
|
||||||
|
* ToDo: Make configurable.
|
||||||
|
*
|
||||||
|
* @return At the moment 256. Will be made configurable.
|
||||||
|
*/
|
||||||
|
private int getSaltLength() {
|
||||||
|
return 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class UserRepository extends AbstractEntityRepository<Long, User> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<User> getEntityClass() {
|
||||||
|
return User.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNew(final User entity) {
|
||||||
|
return entity.getSubjectId() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User findByScreenName(final String screenname) {
|
||||||
|
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||||
|
"findUserByScreenName", User.class);
|
||||||
|
query.setParameter("screenname", screenname);
|
||||||
|
|
||||||
|
final List<User> result = query.getResultList();
|
||||||
|
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else if (result.size() == 1) {
|
||||||
|
return result.get(0);
|
||||||
|
} else {
|
||||||
|
throw new MultipleMatchingUserException(String.format(
|
||||||
|
"Found multipe users identified by screen name '%s'. "
|
||||||
|
+ "Check your database.",
|
||||||
|
screenname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public User findByEmailAddress(final String emailAddress) {
|
||||||
|
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||||
|
"findUserByEmailAddress", User.class);
|
||||||
|
query.setParameter("emailAddress", emailAddress);
|
||||||
|
|
||||||
|
final List<User> result = query.getResultList();
|
||||||
|
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else if(result.size() == 1) {
|
||||||
|
return result.get(0);
|
||||||
|
} else {
|
||||||
|
throw new MultipleMatchingUserException(String.format(
|
||||||
|
"Found multipe users identified by email address '%s'. "
|
||||||
|
+ "Check your database.",
|
||||||
|
emailAddress));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MultipleMatchingUserException extends RuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 100237510055701060L;
|
||||||
|
|
||||||
|
public MultipleMatchingUserException(final String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
|
import com.arsdigita.kernel.KernelConfig;
|
||||||
|
|
||||||
|
import org.libreccm.core.User;
|
||||||
|
import org.libreccm.core.UserRepository;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.auth.login.AccountNotFoundException;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a username and a password in the database.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class LocalLoginModule extends PasswordLoginModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link UserRepository} instance for getting user accounts from the
|
||||||
|
* database.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private transient UserRepository userRepository;
|
||||||
|
|
||||||
|
private transient Subject subject;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final Subject subject,
|
||||||
|
final CallbackHandler callbackHandler,
|
||||||
|
final Map<String, ?> sharedState,
|
||||||
|
final Map<String, ?> options) {
|
||||||
|
super.initialize(subject, callbackHandler, sharedState, options);
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean commit() throws LoginException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean abort() throws LoginException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean logout() throws LoginException {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the provided password against the (hashed) password in the
|
||||||
|
* database.
|
||||||
|
*
|
||||||
|
* @param username The username identifying the user account the verify.
|
||||||
|
* @param password The password to verify.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the password matches the password in the
|
||||||
|
* database, {@code false} if not or if there is no user account
|
||||||
|
* identified by the provided user name.
|
||||||
|
*
|
||||||
|
* @throws LoginException If an error occurs in the process.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean checkPassword(final String username,
|
||||||
|
final String password)
|
||||||
|
throws LoginException {
|
||||||
|
|
||||||
|
//Depending on the configured user identifier retrieve the user account
|
||||||
|
//using the screen name or the email address.
|
||||||
|
final User user;
|
||||||
|
if (KernelConfig.getConfig().emailIsPrimaryIdentifier()) {
|
||||||
|
user = userRepository.findByEmailAddress(username);
|
||||||
|
} else {
|
||||||
|
user = userRepository.findByScreenName(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If no matching user is found report this by throwing an exception.
|
||||||
|
if (user == null) {
|
||||||
|
throw new AccountNotFoundException(String.format(
|
||||||
|
"No user account identified by '%s' found.", username));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the password. The algorithm used for hashing is stored in the
|
||||||
|
// database so we need to retrieve the correct MessageDigest instance
|
||||||
|
// first.
|
||||||
|
try {
|
||||||
|
final MessageDigest digest = MessageDigest.getInstance(user
|
||||||
|
.getHashAlgorithm());
|
||||||
|
final String saltedPassword = String.format("%s%s",
|
||||||
|
password,
|
||||||
|
user.getSalt());
|
||||||
|
final String passwordHash = new String(digest.digest(
|
||||||
|
saltedPassword.getBytes()));
|
||||||
|
|
||||||
|
if (passwordHash.equals(user.getPassword())) {
|
||||||
|
subject.getPrincipals().add(new SubjectPrincipal(user
|
||||||
|
.getSubjectId()));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (NoSuchAlgorithmException ex) {
|
||||||
|
throw new LoginException(String.format(
|
||||||
|
"Failed to validate password because the password stored for "
|
||||||
|
+ "user '%s' in the database is hashed with algorithm '%s' "
|
||||||
|
+ "which is not avialable.",
|
||||||
|
username, user.getHashAlgorithm()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
|
import org.libreccm.core.CcmSessionContext;
|
||||||
|
import org.libreccm.core.User;
|
||||||
|
import org.libreccm.core.UserRepository;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import javax.security.auth.callback.Callback;
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.auth.callback.NameCallback;
|
||||||
|
import javax.security.auth.callback.PasswordCallback;
|
||||||
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
|
import javax.security.auth.login.LoginContext;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides methods for authenticating a user and for logging out a user.
|
||||||
|
*
|
||||||
|
* Under the hood JAAS is used for authentication.
|
||||||
|
*
|
||||||
|
* If a user is authenticated successfully the user object is stored in the
|
||||||
|
* session scoped bean {@link CcmSessionContext}.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@RequestScoped
|
||||||
|
public class LoginManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the register login context.
|
||||||
|
*/
|
||||||
|
private static final String REGISTER_LOGIN_CONTEXT = "RegisterLoginContext";
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private transient CcmSessionContext sessionContext;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private transient UserRepository userRepository;
|
||||||
|
|
||||||
|
public void login(final String username, final String password)
|
||||||
|
throws LoginException {
|
||||||
|
|
||||||
|
final CallbackHandler callbackHandler = new LoginCallbackHandler(
|
||||||
|
username, password);
|
||||||
|
final LoginContext loginContext = new LoginContext(
|
||||||
|
REGISTER_LOGIN_CONTEXT,
|
||||||
|
callbackHandler);
|
||||||
|
loginContext.login();
|
||||||
|
final Subject subject = loginContext.getSubject();
|
||||||
|
|
||||||
|
final Set<SubjectPrincipal> principals = subject.getPrincipals(
|
||||||
|
SubjectPrincipal.class);
|
||||||
|
if (principals.isEmpty()) {
|
||||||
|
throw new LoginException("No principal set");
|
||||||
|
} else {
|
||||||
|
final Iterator<SubjectPrincipal> iterator = principals.iterator();
|
||||||
|
final SubjectPrincipal principal = iterator.next();
|
||||||
|
final User user = userRepository.findById(principal.getSubjectId());
|
||||||
|
|
||||||
|
sessionContext.setCurrentParty(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LoginCallbackHandler implements CallbackHandler {
|
||||||
|
|
||||||
|
private final String username;
|
||||||
|
private final String password;
|
||||||
|
|
||||||
|
public LoginCallbackHandler(final String username,
|
||||||
|
final String password) {
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(final Callback[] callbacks)
|
||||||
|
throws IOException, UnsupportedCallbackException {
|
||||||
|
|
||||||
|
for (Callback callback : callbacks) {
|
||||||
|
if (callback instanceof NameCallback) {
|
||||||
|
((NameCallback) callback).setName(username);
|
||||||
|
} else if (callback instanceof PasswordCallback) {
|
||||||
|
((PasswordCallback) callback).setPassword(password
|
||||||
|
.toCharArray());
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedCallbackException(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,213 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
|
import org.apache.log4j.LogManager;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import javax.security.auth.callback.Callback;
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.auth.callback.NameCallback;
|
||||||
|
import javax.security.auth.callback.PasswordCallback;
|
||||||
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
|
import javax.security.auth.login.LoginContext;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
import javax.security.auth.spi.LoginModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This {@code LoginModule} provides common methods for {@code LoginModule}s
|
||||||
|
* using a username/password combination to authenticate users. If provides
|
||||||
|
* common methods. It tries to fetch username and password from shared data
|
||||||
|
* provided by the calling {@link LoginContext} if possible. Otherwise is
|
||||||
|
* queries the user using {@link Callback}s. Username and password are stored in
|
||||||
|
* the shared data for use by other {@code LoginModule}s.
|
||||||
|
*
|
||||||
|
* This class in a reworked version of
|
||||||
|
* {@code org.arsdigita.kernel.security.PasswordLoginModule} developed by Sameer
|
||||||
|
* Ajmani (according to the JavaDoc). The main differences is that the new
|
||||||
|
* version uses generics and multi-catch for exceptions. Also the code,
|
||||||
|
* especially if clauses have been reworked to match the conventions enforced by
|
||||||
|
* PMD and other style checkers. Also the methods {@code getPassword} and
|
||||||
|
* {@code getUsername} have been renamed to {@code retrievePassword} and
|
||||||
|
* {@code retrieveUsername} because this class is not a Java Bean and the values
|
||||||
|
* are not Java Bean Properties.
|
||||||
|
*
|
||||||
|
* This class is abstract. The methods
|
||||||
|
* {@link #checkPassword(java.lang.String, char[])}, {@link #commit()}, {@link #abort()}
|
||||||
|
* and {@link #logout()} are left to implement by sub classes.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public abstract class PasswordLoginModule implements LoginModule {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
|
PasswordLoginModule.class);
|
||||||
|
/**
|
||||||
|
* Key for username in shared data map.
|
||||||
|
*/
|
||||||
|
private static final String NAME_KEY = "javax.security.auth.login.name";
|
||||||
|
/**
|
||||||
|
* Key for password in shared data map.
|
||||||
|
*/
|
||||||
|
private static final String PASSWORD_KEY
|
||||||
|
= "javax.security.auth.login.password";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields set by the {@link #initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
|
||||||
|
* method.
|
||||||
|
* We only set the fields we use in this class.
|
||||||
|
*/
|
||||||
|
private CallbackHandler callbackHandler;
|
||||||
|
private Map<String, ?> sharedState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @param subject {@inheritDoc }
|
||||||
|
* @param callbackHandler {@inheritDoc }
|
||||||
|
* @param sharedState {@inheritDoc }
|
||||||
|
* @param options {@inheritDoc }
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void initialize(final Subject subject,
|
||||||
|
final CallbackHandler callbackHandler,
|
||||||
|
final Map<String, ?> sharedState,
|
||||||
|
final Map<String, ?> options) {
|
||||||
|
LOGGER.debug("Initalizing...");
|
||||||
|
this.callbackHandler = callbackHandler;
|
||||||
|
this.sharedState = sharedState;
|
||||||
|
LOGGER.debug("Initalized...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the {@link LoginModule#login()} method. Retrieves the
|
||||||
|
* username and the password using the {@link #retrieveUsername()} and
|
||||||
|
* {@link #retrievePassword()} methods and call the
|
||||||
|
* {@link #checkPassword(java.lang.String, char[])} method.
|
||||||
|
*
|
||||||
|
* @return The return value of the
|
||||||
|
* {@link #checkPassword(java.lang.String, char[])} method.
|
||||||
|
*
|
||||||
|
* @throws LoginException If something goes wrong.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean login() throws LoginException {
|
||||||
|
LOGGER.debug("Trying to authenticate user...");
|
||||||
|
return checkPassword(retrieveUsername(), retrievePassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @return {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @throws LoginException {@inheritDoc }
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public abstract boolean commit() throws LoginException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @return {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @throws LoginException {@inheritDoc }
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public abstract boolean abort() throws LoginException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @return {@inheritDoc }
|
||||||
|
*
|
||||||
|
* @throws LoginException {@inheritDoc }
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public abstract boolean logout() throws LoginException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to read username from shared data map; otherwise retreives it
|
||||||
|
* using a NameCallback.
|
||||||
|
*
|
||||||
|
* @return the username.
|
||||||
|
*
|
||||||
|
* @throws LoginException if an error occurs.
|
||||||
|
*/
|
||||||
|
private String retrieveUsername() throws LoginException {
|
||||||
|
String username = (String) sharedState.get(NAME_KEY);
|
||||||
|
if (username == null) {
|
||||||
|
try {
|
||||||
|
final NameCallback callback = new NameCallback("Username: ");
|
||||||
|
callbackHandler.handle(new Callback[]{callback});
|
||||||
|
username = callback.getName();
|
||||||
|
} catch (IOException | UnsupportedCallbackException ex) {
|
||||||
|
throw new LoginException("Could not get Username");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to read password from shared data map; otherwise retreives it
|
||||||
|
* using a PasswordCallback.
|
||||||
|
*
|
||||||
|
* @return the password.
|
||||||
|
*
|
||||||
|
* @throws LoginException if an error occurs.
|
||||||
|
*/
|
||||||
|
private String retrievePassword() throws LoginException {
|
||||||
|
String password = (String) sharedState.get(PASSWORD_KEY);
|
||||||
|
|
||||||
|
if (password == null) {
|
||||||
|
try {
|
||||||
|
final PasswordCallback callback = new PasswordCallback(
|
||||||
|
"Password: ",
|
||||||
|
false);
|
||||||
|
callbackHandler.handle(new Callback[]{callback});
|
||||||
|
password = new String(callback.getPassword());
|
||||||
|
} catch (UnsupportedCallbackException | IOException ex) {
|
||||||
|
throw new LoginException("Could not get password");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given username/password combination is valid.
|
||||||
|
*
|
||||||
|
* @param username the username to check.
|
||||||
|
* @param password the password to check.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the username/password combination is valid,
|
||||||
|
* {@code false} to otherwise.
|
||||||
|
*
|
||||||
|
* @throws LoginException If an error occurs.
|
||||||
|
*/
|
||||||
|
protected abstract boolean checkPassword(String username, String password)
|
||||||
|
throws LoginException;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public final class SubjectPrincipal implements Principal {
|
||||||
|
|
||||||
|
private final long subjectId;
|
||||||
|
|
||||||
|
public SubjectPrincipal(final long subjectId) {
|
||||||
|
this.subjectId = subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSubjectId() {
|
||||||
|
return subjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return Long.toString(subjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 5;
|
||||||
|
hash = 41 * hash + (int) (this.subjectId ^ (this.subjectId >>> 32));
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final SubjectPrincipal other = (SubjectPrincipal) obj;
|
||||||
|
return this.subjectId == other.getSubjectId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s{ "
|
||||||
|
+ "subjectId = %d"
|
||||||
|
+ " }",
|
||||||
|
super.toString(),
|
||||||
|
subjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
package org.libreccm.messaging;
|
package org.libreccm.messaging;
|
||||||
|
|
||||||
import org.libreccm.core.CcmObject;
|
import org.libreccm.core.CcmObject;
|
||||||
import org.libreccm.core.Party;
|
import org.libreccm.core.Subject;
|
||||||
import org.libreccm.jpa.utils.MimeTypeConverter;
|
import org.libreccm.jpa.utils.MimeTypeConverter;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -56,7 +56,7 @@ public class Message extends CcmObject implements Serializable {
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "sender_id")
|
@JoinColumn(name = "sender_id")
|
||||||
private Party sender;
|
private Subject sender;
|
||||||
|
|
||||||
@Column(name = "subject")
|
@Column(name = "subject")
|
||||||
private String subject;
|
private String subject;
|
||||||
|
|
@ -82,11 +82,11 @@ public class Message extends CcmObject implements Serializable {
|
||||||
@OneToMany(mappedBy = "message")
|
@OneToMany(mappedBy = "message")
|
||||||
private List<Attachment> attachments;
|
private List<Attachment> attachments;
|
||||||
|
|
||||||
public Party getSender() {
|
public Subject getSender() {
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setSender(final Party sender) {
|
protected void setSender(final Subject sender) {
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
package org.libreccm.notification;
|
package org.libreccm.notification;
|
||||||
|
|
||||||
import org.libreccm.core.CcmObject;
|
import org.libreccm.core.CcmObject;
|
||||||
import org.libreccm.core.Party;
|
import org.libreccm.core.Subject;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -57,7 +57,7 @@ public class Digest extends CcmObject implements Serializable {
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "from_party_id")
|
@JoinColumn(name = "from_party_id")
|
||||||
private Party fromParty;
|
private Subject fromParty;
|
||||||
|
|
||||||
@Column(name = "subject", length = 255, nullable = false)
|
@Column(name = "subject", length = 255, nullable = false)
|
||||||
private String subject;
|
private String subject;
|
||||||
|
|
@ -78,11 +78,11 @@ public class Digest extends CcmObject implements Serializable {
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date nextRun;
|
private Date nextRun;
|
||||||
|
|
||||||
public Party getFromParty() {
|
public Subject getFromParty() {
|
||||||
return fromParty;
|
return fromParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFromParty(final Party fromParty) {
|
public void setFromParty(final Subject fromParty) {
|
||||||
this.fromParty = fromParty;
|
this.fromParty = fromParty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
package org.libreccm.notification;
|
package org.libreccm.notification;
|
||||||
|
|
||||||
import org.libreccm.core.CcmObject;
|
import org.libreccm.core.CcmObject;
|
||||||
import org.libreccm.core.Party;
|
import org.libreccm.core.Subject;
|
||||||
import org.libreccm.messaging.Message;
|
import org.libreccm.messaging.Message;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -80,7 +80,7 @@ public class Notification extends CcmObject implements Serializable {
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "receiver_id")
|
@JoinColumn(name = "receiver_id")
|
||||||
private Party receiver;
|
private Subject receiver;
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "digest_id")
|
@JoinColumn(name = "digest_id")
|
||||||
|
|
@ -119,11 +119,11 @@ public class Notification extends CcmObject implements Serializable {
|
||||||
@Column(name = "expunge_message")
|
@Column(name = "expunge_message")
|
||||||
private boolean expungeMessage;
|
private boolean expungeMessage;
|
||||||
|
|
||||||
public Party getReceiver() {
|
public Subject getReceiver() {
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReceiver(final Party receiver) {
|
public void setReceiver(final Subject receiver) {
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.notification;
|
package org.libreccm.notification;
|
||||||
|
|
||||||
import org.libreccm.core.Party;
|
import org.libreccm.core.Subject;
|
||||||
import org.libreccm.messaging.Message;
|
import org.libreccm.messaging.Message;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -60,7 +60,7 @@ public class QueueItem implements Serializable {
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "receiver_id")
|
@JoinColumn(name = "receiver_id")
|
||||||
private Party receiver;
|
private Subject receiver;
|
||||||
|
|
||||||
@Column(name = "retry_count")
|
@Column(name = "retry_count")
|
||||||
private long retryCount;
|
private long retryCount;
|
||||||
|
|
@ -89,11 +89,11 @@ public class QueueItem implements Serializable {
|
||||||
this.queueItemId = queueItemId;
|
this.queueItemId = queueItemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Party getReceiver() {
|
public Subject getReceiver() {
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReceiver(final Party receiver) {
|
public void setReceiver(final Subject receiver) {
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.search.lucene;
|
package org.libreccm.search.lucene;
|
||||||
|
|
||||||
import org.libreccm.core.Party;
|
import org.libreccm.core.Subject;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -92,7 +92,7 @@ public class Document implements Serializable {
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "created_by_party_id")
|
@JoinColumn(name = "created_by_party_id")
|
||||||
private Party createdBy;
|
private Subject createdBy;
|
||||||
|
|
||||||
@Column(name = "last_modified")
|
@Column(name = "last_modified")
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
|
@ -100,7 +100,7 @@ public class Document implements Serializable {
|
||||||
|
|
||||||
@OneToOne
|
@OneToOne
|
||||||
@JoinColumn(name = "last_modified_by")
|
@JoinColumn(name = "last_modified_by")
|
||||||
private Party lastModifiedBy;
|
private Subject lastModifiedBy;
|
||||||
|
|
||||||
@Column(name = "content_section", length = 512)
|
@Column(name = "content_section", length = 512)
|
||||||
private String contentSection;
|
private String contentSection;
|
||||||
|
|
@ -213,11 +213,11 @@ public class Document implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Party getCreatedBy() {
|
public Subject getCreatedBy() {
|
||||||
return createdBy;
|
return createdBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCreatedBy(final Party createdBy) {
|
public void setCreatedBy(final Subject createdBy) {
|
||||||
this.createdBy = createdBy;
|
this.createdBy = createdBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,11 +237,11 @@ public class Document implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Party getLastModifiedBy() {
|
public Subject getLastModifiedBy() {
|
||||||
return lastModifiedBy;
|
return lastModifiedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastModifiedBy(final Party lastModifiedBy) {
|
public void setLastModifiedBy(final Subject lastModifiedBy) {
|
||||||
this.lastModifiedBy = lastModifiedBy;
|
this.lastModifiedBy = lastModifiedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
waf.debug.title=Global debug flag
|
||||||
|
waf.debug.purpose=Enables or disables WAF debugging
|
||||||
|
waf.debug.example=true
|
||||||
|
waf.debug.format=true|false
|
||||||
|
|
||||||
|
waf.kernel.data_permission_check_enabled.title=DML permission checking flag
|
||||||
|
waf.kernel.data_permission_check_enabled.purpose=Enables or disables permissions checks on database writes
|
||||||
|
waf.kernel.data_permission_check_enabled.example=true
|
||||||
|
waf.kernel.data_permission_check_enabled.format=true|false
|
||||||
|
|
||||||
|
waf.kernel.primary_user_identifier.title=The primary user identification
|
||||||
|
waf.kernel.primary_user_identifier.purpose=Determines whether email addresses or screen names are used to authenticate users
|
||||||
|
waf.kernel.primary_user_identifier.example=email
|
||||||
|
waf.kernel.primary_user_identifier.format=email|screen_name
|
||||||
|
|
||||||
|
waf.kernel.remember_login.title=Remember login by default
|
||||||
|
waf.kernel.remember_login.purpose=Determines whether the "remember login" feature is enabled or disabled by default
|
||||||
|
waf.kernel.remember_login.example=true
|
||||||
|
waf.kernel.remember_login.format=true|false
|
||||||
|
|
||||||
|
waf.kernel.secure_login.title=Require secure login
|
||||||
|
waf.kernel.secure_login.purpose=Accept only credentials presented over secure connection
|
||||||
|
waf.kernel.secure_login.example=true
|
||||||
|
waf.kernel.secure_login.format=true|false
|
||||||
|
|
||||||
|
waf.kernel.sso_login.title=Enable SSO login
|
||||||
|
waf.kernel.sso_login.purpose=Enable alternative "RegisterSSO" login context.
|
||||||
|
waf.kernel.sso_login.example=false
|
||||||
|
waf.kernel.sso_login.format=true|false
|
||||||
|
|
||||||
|
waf.kernel.supported_languages.title=Set the supported languages for categorization
|
||||||
|
waf.kernel.supported_languages.purpose=Set the supported languages for categorization. First entry is the default language
|
||||||
|
waf.kernel.supported_languages.example=en,de,fr,nl,it,pt,es
|
||||||
|
waf.kernel.supported_languages.format=[string]
|
||||||
|
|
||||||
|
waf.kernel.language_independent_items.title=Allow language independent content items
|
||||||
|
waf.kernel.language_independent_items.purpose=Allow language independent content items
|
||||||
|
waf.kernel.language_independent_items.example=false
|
||||||
|
waf.kernel.language_independent_items.format=true|false
|
||||||
|
|
||||||
|
waf.kernel.language_independent_code.title=Select language independent code
|
||||||
|
waf.kernel.language_independent_code.purpose=Allow language independent code
|
||||||
|
waf.kernel.language_independent_code.example=--
|
||||||
|
waf.kernel.language_independent_code.format=[string]
|
||||||
|
|
@ -41,7 +41,7 @@ public class EqualsAndHashCodeTest extends EqualsVerifier {
|
||||||
CcmObject.class,
|
CcmObject.class,
|
||||||
EmailAddress.class,
|
EmailAddress.class,
|
||||||
GroupMembership.class,
|
GroupMembership.class,
|
||||||
Party.class,
|
Subject.class,
|
||||||
Permission.class,
|
Permission.class,
|
||||||
PersonName.class,
|
PersonName.class,
|
||||||
Privilege.class,
|
Privilege.class,
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public class ToStringTest extends ToStringVerifier {
|
||||||
CcmObject.class,
|
CcmObject.class,
|
||||||
EmailAddress.class,
|
EmailAddress.class,
|
||||||
GroupMembership.class,
|
GroupMembership.class,
|
||||||
Party.class,
|
Subject.class,
|
||||||
Permission.class,
|
Permission.class,
|
||||||
PersonName.class,
|
PersonName.class,
|
||||||
Privilege.class,
|
Privilege.class,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue