Mercurial > dive4elements > framework
changeset 10:e8626caac353
* Made Artifact life cycle symmetric: setup/endOfLife.
* Implement defaults for Artifact and ArtifactFactory.
* Added connection pooling from apache commons dbcp
* Made sql schema of artifact database more compatible.
* Improve example config.
* Made artifactdb start with 'mvn exec:exec'
* minor fixes.
artifacts/trunk@25 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 06 Sep 2009 12:00:56 +0000 |
parents | a5a279a0ee35 |
children | af07d004d320 |
files | Changelog TODO artifact-database/doc/artifactdb-example-conf.xml artifact-database/doc/schema.sql artifact-database/pom.xml artifact-database/src/main/java/de/intevation/artifactdatabase/Config.java artifact-database/src/main/java/de/intevation/artifactdatabase/DBConnection.java artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultArtifact.java artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultArtifactFactory.java artifact-database/src/main/java/de/intevation/artifactdatabase/FactoryBootstrap.java artifacts/src/main/java/de/intevation/artifacts/Artifact.java artifacts/src/main/java/de/intevation/artifacts/ArtifactFactory.java |
diffstat | 12 files changed, 447 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- a/Changelog Fri Sep 04 16:06:44 2009 +0000 +++ b/Changelog Sun Sep 06 12:00:56 2009 +0000 @@ -1,3 +1,51 @@ +2009-09-06 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * artifacts/src/main/java/de/intevation/artifacts/Artifact.java(setup): + Added the setup() method to have symmetric counter part to endOfLife(). + + * artifacts/src/main/java/de/intevation/artifacts/ArtifactFactory.java(timeToLiveUntouched): + Added this method to let the factory decide how long an artifact should live in ms. + This is not a part of the Artifact itself because this is only evaluated once when + the artifact is created. + + * artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultArtifact.java: + New. Simple base class implementation of the Artifact interface. + + * artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultArtifactFactory.java: + New. Simple base class implementation of the ArtifactFactory interface. When setup() + on instances of this class is called, it pull ttl, name, description and + the artifact class name from the node given. See artifactdb-example-conf.xml + for examples. + + * artifact-database/pom.xml: Cleaned up XML. + Introduced dependency to apache commons dbcp, used for pooling of the + database connections to artifact db. + Added parameters for the exec:exec goal to make the project + startable without building packages. + + * artifact-database/doc/schema.sql: Removed AUTO_INCREMENT from primary key + to avoid compatibility issues with other non-H2 databases (PostgreSQL, Oracle, ...) + which have no or limited support for generated keys in the JDBC driver. Now + using an explicit sequence. TTL ist now big int to bring the resolution to ms. + + * artifact-database/src/main/java/de/intevation/artifactdatabase/Config.java: + Refactored a bit to make the XPath access function usable on arbitrary XML + documents and parts of. + + * artifact-database/src/main/java/de/intevation/artifactdatabase/DBConnection.java: + New. Exposes DataSource from a apache dbcp connection pool configured by the + global configuration file. See artifactdb-example-conf.xml for examples. + TODO: Write some documentation about this. + + * artifact-database/doc/artifactdb-example-conf.xml: Adjusted to be a more realistic + example config file. Added references to DefaultArtifact/DefaultArtifactFactory and + demonstrate how to configure the connection pool. + + * TODO: Add remark to document the connection file. + + * artifact-database/src/main/java/de/intevation/artifactdatabase/FactoryBootstrap.java: + Do not crash when config does not contain any factories. + 2009-09-04 Sascha L. Teichmann <sascha.teichmann@intevation.de> * artifact-database/src/main/java/de/intevation/artifactdatabase/Config.java (getNodeXPath):
--- a/TODO Fri Sep 04 16:06:44 2009 +0000 +++ b/TODO Sun Sep 06 12:00:56 2009 +0000 @@ -1,2 +1,3 @@ TODO: * integrate logging into artifact database. + * Document the XML of the configuration file.
--- a/artifact-database/doc/artifactdb-example-conf.xml Fri Sep 04 16:06:44 2009 +0000 +++ b/artifact-database/doc/artifactdb-example-conf.xml Sun Sep 06 12:00:56 2009 +0000 @@ -1,11 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?> <artifact-database> <factories> - <context-factory>com.example.Context</context-factory> + <context-factory>de.intevation.artifactdatabase.DefaultArtifactContextFactory</context-factory> <artifact-factories> - <artifact-factory>com.example.ArtifactExampleFactoryOne</artifact-factory> - <artifact-factory>com.example.ArtifactExampleFactoryTwo</artifact-factory> - <artifact-factory>com.example.ArtifactExampleFactoryThree</artifact-factory> + <artifact-factory + name="dummy-1" description="dummy description 1" ttl="60000" + artifact="de.intevation.artifactdatabase.DefaultArtifact">de.intevation.artifactdatabase.DefaultArtifactFactory</artifact-factory> + <artifact-factory + name="dummy-2" description="dummy description 2" ttl="1800000" + artifact="de.intevation.artifactdatabase.DefaultArtifact">de.intevation.artifactdatabase.DefaultArtifactFactory</artifact-factory> + <artifact-factory + name="dummy-3" description="dummy description 3" + artifact="de.intevation.artifactdatabase.DefaultArtifact">de.intevation.artifactdatabase.DefaultArtifactFactory</artifact-factory> </artifact-factories> </factories> + <database> + <user></user> + <password></password> + <!-- <url>jdbc:h2:artifacts.db</url> --> + <!-- <driver>org.h2.Driver</driver> --> + <!-- <sql></sql> --> + </database> </artifact-database>
--- a/artifact-database/doc/schema.sql Fri Sep 04 16:06:44 2009 +0000 +++ b/artifact-database/doc/schema.sql Sun Sep 06 12:00:56 2009 +0000 @@ -4,12 +4,16 @@ BEGIN; +-- not using AUTO_INCREMENT to be more compatible with +-- other dbms. +CREATE SEQUENCE ARTIFACTS_ID_SEQ; + CREATE TABLE artifacts ( - id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, - gid UUID NOT NULL UNIQUE, - creation TIMESTAMP NOT NULL, - last_access TIMESTAMP NOT NULL, - ttl TIME, -- NULL means eternal + id INT PRIMARY KEY NOT NULL, + gid UUID NOT NULL UNIQUE, + creation TIMESTAMP NOT NULL, + last_access TIMESTAMP NOT NULL, + ttl BIGINT, -- NULL means eternal data BINARY );
--- a/artifact-database/pom.xml Fri Sep 04 16:06:44 2009 +0000 +++ b/artifact-database/pom.xml Sun Sep 06 12:00:56 2009 +0000 @@ -1,4 +1,5 @@ -<?xml version="1.0"?><project> +<?xml version="1.0"?> +<project> <parent> <artifactId>artifact-system</artifactId> <groupId>de.intevation.bsh</groupId> @@ -12,35 +13,53 @@ <url>http://maven.apache.org</url> <build> <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>2.2</version> - <configuration> - <archive> - <manifest> - <mainClass>de.intevation.artifactdatabase.App</mainClass> - </manifest> - </archive> - </configuration> - </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.2</version> + <configuration> + <archive> + <manifest> + <mainClass>de.intevation.artifactdatabase.App</mainClass> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.1</version> + <configuration> + <executable>java</executable> + <arguments> + <argument>-classpath</argument> + <classpath/> + <argument>de.intevation.artifactdatabase.App</argument> + </arguments> + </configuration> + </plugin> </plugins> </build> <dependencies> <dependency> - <groupId>de.intevation.bsh.artifacts</groupId> - <artifactId>artifacts</artifactId> - <version>1.0-SNAPSHOT</version> + <groupId>de.intevation.bsh.artifacts</groupId> + <artifactId>artifacts</artifactId> + <version>1.0-SNAPSHOT</version> </dependency> - <dependency> - <groupId>org.restlet</groupId> - <artifactId>org.restlet</artifactId> - <version>2.0-M3</version> - </dependency> <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - <version>1.1.117</version> + <groupId>org.restlet</groupId> + <artifactId>org.restlet</artifactId> + <version>2.0-M3</version> + </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>1.1.117</version> + </dependency> + <dependency> + <groupId>commons-dbcp</groupId> + <artifactId>commons-dbcp</artifactId> + <version>1.2.2</version> </dependency> </dependencies> </project>
--- a/artifact-database/src/main/java/de/intevation/artifactdatabase/Config.java Fri Sep 04 16:06:44 2009 +0000 +++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/Config.java Sun Sep 06 12:00:56 2009 +0000 @@ -20,6 +20,9 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathConstants; +/** + * @author Sascha L. Teichmann + */ public final class Config { public static final String CONFIG_PROPERTY = "artifact.database.config"; @@ -71,6 +74,38 @@ return null; } + public static final Object getXPath( + Object root, String query, QName returnType + ) { + if (root == null) { + return null; + } + + XPathFactory factory = XPathFactory.newInstance(); + XPath xpath = factory.newXPath(); + + try { + return xpath.evaluate(query, root, returnType); + } + catch (XPathExpressionException xpee) { + xpee.printStackTrace(System.err); + } + + return null; + } + + public static final Object getXPath(String query, QName returnType) { + return getXPath(getConfig(), query, returnType); + } + + public static final NodeList getNodeSetXPath(String query) { + return (NodeList)getXPath(query, XPathConstants.NODESET); + } + + public static final Node getNodeXPath(String query) { + return (Node)getXPath(query, XPathConstants.NODE); + } + public static final String getStringXPath(String xpath) { return getStringXPath(xpath, null); } @@ -82,31 +117,25 @@ : s; } - public static final Object getXPath(String query, QName returnType) { - Document document = getConfig(); - if (document == null) { - return null; - } - - XPathFactory factory = XPathFactory.newInstance(); - XPath xpath = factory.newXPath(); - - try { - return xpath.evaluate(query, document, returnType); - } - catch (XPathExpressionException xpee) { - xpee.printStackTrace(System.err); - } - - return null; + public static final NodeList getNodeSetXPath(Object root, String query) { + return (NodeList)getXPath(root, query, XPathConstants.NODESET); } - public static final NodeList getNodeSetXPath(String query) { - return (NodeList)getXPath(query, XPathConstants.NODESET); + public static final Node getNodeXPath(Object root, String query) { + return (Node)getXPath(root, query, XPathConstants.NODE); } - public static final Node getNodeXPath(String query) { - return (Node)getXPath(query, XPathConstants.NODE); + public static final String getStringXPath(Object root, String xpath) { + return getStringXPath(root, xpath, null); + } + + public static final String getStringXPath( + Object root, String query, String def + ) { + String s = (String)getXPath(root, query, XPathConstants.STRING); + return s == null || s.length() == 0 + ? def + : s; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/DBConnection.java Sun Sep 06 12:00:56 2009 +0000 @@ -0,0 +1,78 @@ +package de.intevation.artifactdatabase; + +import javax.sql.DataSource; + +import java.sql.SQLException; + +import org.apache.commons.dbcp.BasicDataSource; + +/** + * @author Sascha L. Teichmann + */ +public class DBConnection +{ + public static final String DB_DRIVER = + "/artifacts-database/database/driver/text()"; + public static final String DB_URL = + "/artifacts-database/database/url/text()"; + public static final String DB_USER = + "/artifacts-database/database/driver/user/text()"; + public static final String DB_PASSWORD = + "/artifacts-database/database/driver/password()"; + + public static final String DEFAULT_DRIVER = + "org.h2.Driver"; + + public static final String DEFAULT_URL = + "jdbc:h2:artifacts.db"; + + public static final String DEFAULT_USER = ""; + public static final String DEFAULT_PASSWORD = ""; + + private DBConnection() { + } + + private static BasicDataSource dataSource; + + private static final void addShutdownHook() { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + if (dataSource != null) { + try { + dataSource.close(); + } + catch (SQLException sqle) { + } + dataSource = null; + } + } + }); + } + + public static synchronized DataSource getDataSource() { + if (dataSource == null) { + dataSource = new BasicDataSource(); + + String driver = Config.getStringXPath( + DB_DRIVER, DEFAULT_DRIVER); + + String url = Config.getStringXPath( + DB_URL, DEFAULT_URL); + + String user = Config.getStringXPath( + DB_USER, DEFAULT_USER); + + String password = Config.getStringXPath( + DB_PASSWORD, DEFAULT_PASSWORD); + + dataSource.setDriverClassName(driver); + dataSource.setUsername(user); + dataSource.setPassword(password); + dataSource.setUrl(url); + addShutdownHook(); + } + + return dataSource; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultArtifact.java Sun Sep 06 12:00:56 2009 +0000 @@ -0,0 +1,65 @@ +package de.intevation.artifactdatabase; + +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import de.intevation.artifacts.Artifact; + +/** + * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) + */ +public class DefaultArtifact +implements Artifact +{ + protected String identifier; + + public DefaultArtifact() { + } + + protected Document newDocument() { + try { + return DocumentBuilderFactory + .newInstance() + .newDocumentBuilder() + .newDocument(); + } + catch (ParserConfigurationException pce) { + pce.printStackTrace(System.err); + } + return null; + } + + public String identifier() { + return this.identifier; + } + + public String hash() { + return String.valueOf(hashCode()); + } + + public Document describe(Object context) { + return newDocument(); + } + + public Document advance(Document target, Object context) { + return newDocument(); + } + + public Document feed(Document target, Object context) { + return newDocument(); + } + + public byte [] out(Document format, Object context) { + return new byte[0]; + } + + public void setup(String identifier, Object context) { + this.identifier = identifier; + } + + public void endOfLife(Object context) { + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultArtifactFactory.java Sun Sep 06 12:00:56 2009 +0000 @@ -0,0 +1,102 @@ +package de.intevation.artifactdatabase; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import de.intevation.artifacts.ArtifactFactory; +import de.intevation.artifacts.Artifact; + +public class DefaultArtifactFactory +implements ArtifactFactory +{ + public static final String XPATH_TTL = "@ttl"; + public static final String XPATH_NAME = "@name"; + public static final String XPATH_DESCRIPTION = "@description"; + public static final String XPATH_ARTIFACT = "@artifact"; + + public static final String DEFAULT_DESCRIPTION = + "No description available"; + + public static final String DEFAULT_ARTIFACT = + "de.intevation.artifactdatabase.DefaultArtifact"; + + protected Long ttl; + + protected String name; + + protected String description; + + protected Class artifactClass; + + public DefaultArtifactFactory() { + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Artifact createArtifact(String identifier, Object context) { + + try { + Artifact artifact = + (Artifact)artifactClass.newInstance(); + + artifact.setup(identifier, context); + + return artifact; + } + catch (InstantiationException ie) { + ie.printStackTrace(System.err); + } + catch (IllegalAccessException iae) { + iae.printStackTrace(System.err); + } + catch (ClassCastException cce) { + cce.printStackTrace(System.err); + } + + return null; + } + + public void setup(Document document, Node factoryNode) { + + String ttlString = Config.getStringXPath(factoryNode, XPATH_TTL); + if (ttlString != null) { + try { + ttl = Long.valueOf(ttlString); + } + catch (NumberFormatException nfe) { + nfe.printStackTrace(System.err); + } + } + + description = Config.getStringXPath( + factoryNode, XPATH_DESCRIPTION, DEFAULT_DESCRIPTION); + + name = Config.getStringXPath( + factoryNode, XPATH_NAME, toString()); + + String artifact = Config.getStringXPath( + factoryNode, XPATH_ARTIFACT, DEFAULT_ARTIFACT); + + try { + artifactClass = Class.forName(artifact); + } + catch (ClassNotFoundException cnfe) { + cnfe.printStackTrace(System.err); + } + + if (artifactClass == null) { + artifactClass = DefaultArtifact.class; + } + } + + public Long timeToLiveUntouched(Artifact artifact, Object context) { + return ttl; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:
--- a/artifact-database/src/main/java/de/intevation/artifactdatabase/FactoryBootstrap.java Fri Sep 04 16:06:44 2009 +0000 +++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/FactoryBootstrap.java Sun Sep 06 12:00:56 2009 +0000 @@ -66,6 +66,11 @@ NodeList nodes = Config.getNodeSetXPath(ARTIFACT_FACTORIES); + if (nodes == null) { + System.err.println("ERROR: no factories found"); + return; + } + Document config = Config.getConfig(); for (int i = 0, N = nodes.getLength(); i < N; ++i) {
--- a/artifacts/src/main/java/de/intevation/artifacts/Artifact.java Fri Sep 04 16:06:44 2009 +0000 +++ b/artifacts/src/main/java/de/intevation/artifacts/Artifact.java Sun Sep 06 12:00:56 2009 +0000 @@ -22,6 +22,15 @@ * <li>{@link #out(Document, Object) out()}: Produces output for this artifact.</li> * </ol> * + * There are two more methods involved with the life cycle of the are: + * <ol> + * <li>{@link #setup(String, Object) setup()}: Called after created by the + * factory.</li> + * <li>{@link #endOfLife(Object) endOfLife()}: Called when the artifact + * is going to be removed from + * system. Useful to clean up.</li> + * </ol> + * * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) */ public interface Artifact @@ -72,6 +81,14 @@ public byte [] out(Document format, Object context); /** + * When created by a factory this method is called to + * initialize the artifact. + * @param identifier The identifier from artifact database + * @param context The global context of the runtime system. + */ + public void setup(String identifier, Object context); + + /** * Called from artifact database when an artifact is * going to be removed from system. * @param context The global context of the runtime system.
--- a/artifacts/src/main/java/de/intevation/artifacts/ArtifactFactory.java Fri Sep 04 16:06:44 2009 +0000 +++ b/artifacts/src/main/java/de/intevation/artifacts/ArtifactFactory.java Sun Sep 06 12:00:56 2009 +0000 @@ -37,5 +37,17 @@ * @param factoryNode the ConfigurationNode of this Factory */ void setup(Document config, Node factoryNode); + + /** + * Tells how long an artifact should survive if it is + * not touched. This is put in the factory because + * life time is nothing a artifact should handle it self. + * This method is only called once directly after the + * artifact is created. + * @param artifact The artifact to be rated. + * @param context The global context. + * return time to live in ms. null means eternal. + */ + Long timeToLiveUntouched(Artifact artifact, Object context); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: