OPENJPA-1764 Fix bug in DBCPDriverDataSource.mergeConnectionProperties, move common surefire-plugin systemProperties to parent pom and move the connection user/password to equivalent openjpa.Connection settings

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1002745 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Donald Woods 2010-09-29 17:12:49 +00:00
parent 6dbe665329
commit 4aa5b43825
8 changed files with 91 additions and 328 deletions

View File

@ -181,7 +181,6 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${test.jvm.arguments}</argLine>
<excludes> <excludes>
<!-- exclude classes that end with 'Test'; these <!-- exclude classes that end with 'Test'; these
are not test cases per OpenJPA standards --> are not test cases per OpenJPA standards -->
@ -192,40 +191,6 @@
<exclude>org/apache/openjpa/**/*$*.class</exclude> <exclude>org/apache/openjpa/**/*$*.class</exclude>
<exclude>org/apache/openjpa/**/*.*.class</exclude> <exclude>org/apache/openjpa/**/*.*.class</exclude>
</excludes> </excludes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>false</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>5</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>6</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -121,47 +121,6 @@
<!-- The surefire plugin is used to run the jUnit tests --> <!-- The surefire plugin is used to run the jUnit tests -->
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefire.jvm.args}</argLine>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>false</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>${derby.locks.deadlockTimeout}</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>${derby.locks.waitTimeout}</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

View File

@ -137,7 +137,6 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${test.jvm.arguments}</argLine>
<excludes> <excludes>
<!-- exclude classes that end with 'Test'; these <!-- exclude classes that end with 'Test'; these
are not test cases per OpenJPA standards --> are not test cases per OpenJPA standards -->
@ -148,44 +147,6 @@
<exclude>org/apache/openjpa/**/*$*.class</exclude> <exclude>org/apache/openjpa/**/*$*.class</exclude>
<exclude>org/apache/openjpa/**/*.*.class</exclude> <exclude>org/apache/openjpa/**/*.*.class</exclude>
</excludes> </excludes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>false</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>${derby.locks.deadlockTimeout}</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>${derby.locks.waitTimeout}</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -223,7 +223,6 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${test.jvm.arguments}</argLine>
<excludes> <excludes>
<!-- exclude classes that end with 'Test'; these <!-- exclude classes that end with 'Test'; these
are not test cases per OpenJPA standards --> are not test cases per OpenJPA standards -->
@ -234,44 +233,6 @@
<exclude>org/apache/openjpa/**/*$*.class</exclude> <exclude>org/apache/openjpa/**/*$*.class</exclude>
<exclude>org/apache/openjpa/**/*.*.class</exclude> <exclude>org/apache/openjpa/**/*.*.class</exclude>
</excludes> </excludes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>false</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>${derby.locks.deadlockTimeout}</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>${derby.locks.waitTimeout}</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -142,49 +142,49 @@ extends SimpleDriverDataSource implements Configurable {
// only perform the following check for the first connection attempt (_driverClassName == null), // only perform the following check for the first connection attempt (_driverClassName == null),
// as multiple connections could be requested (like from SchemaTool) and isDBCPDriver() will be true // as multiple connections could be requested (like from SchemaTool) and isDBCPDriver() will be true
if (isDBCPDataSource()) { if (isDBCPDataSource()) {
String propDriver = hasProperty(dbcpProps, "DriverClassName"); String propDriver = hasProperty(dbcpProps, "driverClassName");
if (propDriver == null || propDriver.trim().isEmpty()) { if (propDriver == null || propDriver.trim().isEmpty()) {
// if user specified DBCP for the connectionDriverName, then make sure they supplied a DriverClassName // if user specified DBCP for the connectionDriverName, then make sure they supplied a DriverClassName
throw new RuntimeException(_eloc.get("connection-property-invalid", "DriverClassName", throw new RuntimeException(_eloc.get("connection-property-invalid", "DriverClassName",
propDriver).getMessage()); propDriver).getMessage());
} }
propDriver = hasProperty(dbcpProps, "Url"); propDriver = hasProperty(dbcpProps, "url");
if (propDriver == null || propDriver.trim().isEmpty()) { if (propDriver == null || propDriver.trim().isEmpty()) {
// if user specified DBCP for the connectionDriverName, then make sure they supplied a Url // if user specified DBCP for the connectionDriverName, then make sure they supplied a Url
throw new RuntimeException(_eloc.get("connection-property-invalid", "Url", throw new RuntimeException(_eloc.get("connection-property-invalid", "URL",
propDriver).getMessage()); propDriver).getMessage());
} }
} else { } else {
// set Commons DBCP expected DriverClassName to the original connection driver name // set Commons DBCP expected DriverClassName to the original connection driver name
dbcpProps.setProperty(hasKey(dbcpProps, "DriverClassName", "DriverClassName"), getConnectionDriverName()); dbcpProps.setProperty(hasKey(dbcpProps, "driverClassName", "driverClassName"), getConnectionDriverName());
// set Commons DBCP expected URL property // set Commons DBCP expected URL property
dbcpProps.setProperty(hasKey(dbcpProps, "Url", "Url"), getConnectionURL()); dbcpProps.setProperty(hasKey(dbcpProps, "url", "url"), getConnectionURL());
} }
// Commons DBCP requires non-Null username/password values in the connection properties // Commons DBCP requires non-Null username/password values in the connection properties
if (hasKey(dbcpProps, "Username") == null) { if (hasKey(dbcpProps, "username") == null) {
if (getConnectionUserName() != null) if (getConnectionUserName() != null)
dbcpProps.setProperty("Username", getConnectionUserName()); dbcpProps.setProperty("username", getConnectionUserName());
else else
dbcpProps.setProperty("Username", ""); dbcpProps.setProperty("username", "");
} }
// Commons DBCP requires non-Null username/password values in the connection properties // Commons DBCP requires non-Null username/password values in the connection properties
if (hasKey(dbcpProps, "Password") == null) { if (hasKey(dbcpProps, "password") == null) {
if (getConnectionPassword() != null) if (getConnectionPassword() != null)
dbcpProps.setProperty("Password", getConnectionPassword()); dbcpProps.setProperty("password", getConnectionPassword());
else else
dbcpProps.setProperty("Password", ""); dbcpProps.setProperty("password", "");
} }
// set some default properties for DBCP // set some default properties for DBCP
if (hasKey(dbcpProps, "MaxIdle") == null) { if (hasKey(dbcpProps, "maxIdle") == null) {
dbcpProps.setProperty("MaxIdle", "1"); dbcpProps.setProperty("maxIdle", "1");
} }
if (hasKey(dbcpProps, "MinIdle") == null) { if (hasKey(dbcpProps, "minIdle") == null) {
dbcpProps.setProperty("MinIdle", "0"); dbcpProps.setProperty("minIdle", "0");
} }
if (hasKey(dbcpProps, "MaxActive") == null) { if (hasKey(dbcpProps, "maxActive") == null) {
dbcpProps.setProperty("MaxActive", "10"); dbcpProps.setProperty("maxActive", "10");
} }
return dbcpProps; return dbcpProps;
@ -202,28 +202,26 @@ extends SimpleDriverDataSource implements Configurable {
// need to map "user" to "username" for Commons DBCP // need to map "user" to "username" for Commons DBCP
String uid = removeProperty(mergedProps, "user"); String uid = removeProperty(mergedProps, "user");
if (uid != null) { if (uid != null) {
mergedProps.setProperty("Username", uid); mergedProps.setProperty("username", uid);
} }
// now, merge in any passed in properties // now, merge in any passed in properties
if (props != null && !props.isEmpty()) { if (props != null && !props.isEmpty()) {
for (Iterator<Object> itr = props.keySet().iterator(); itr.hasNext();) { for (Iterator<Object> itr = props.keySet().iterator(); itr.hasNext();) {
String key = (String)itr.next(); String key = (String)itr.next();
String value = mergedProps.getProperty(key); String value = props.getProperty(key);
if (value != null) { // need to map "user" to "username" for Commons DBCP
// need to map "user" to "username" for Commons DBCP if ("user".equalsIgnoreCase(key)) {
if ("user".equalsIgnoreCase(key)) { key = "username";
key = "Username"; }
} // case-insensitive search for existing key
// case-insensitive search for existing key String existingKey = hasKey(mergedProps, key);
String existingKey = hasKey(mergedProps, key); if (existingKey != null) {
if (existingKey != null) { // update existing entry
// update existing entry mergedProps.setProperty(existingKey, value);
mergedProps.setProperty(existingKey, value); } else {
} else { // add property to the merged set
// add property to the merged set mergedProps.setProperty(key, value);
mergedProps.setProperty(key, value);
}
} }
} }
} }

View File

@ -46,6 +46,7 @@
</activation> </activation>
<properties> <properties>
<build.enhance>false</build.enhance> <build.enhance>false</build.enhance>
<openjpa.dynamicEnhance>true</openjpa.dynamicEnhance>
<surefire.jvm.args>-Dopenjpa.RuntimeUnenhancedClasses=unsupported ${test.jvm.arguments}</surefire.jvm.args> <surefire.jvm.args>-Dopenjpa.RuntimeUnenhancedClasses=unsupported ${test.jvm.arguments}</surefire.jvm.args>
</properties> </properties>
<build> <build>
@ -54,36 +55,9 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${surefire.jvm.args}</argLine>
<includes> <includes>
<include>org/apache/openjpa/persistence/enhance/DynamicEnhancementSuite.java</include> <include>org/apache/openjpa/persistence/enhance/DynamicEnhancementSuite.java</include>
</includes> </includes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@ -830,7 +804,6 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${surefire.jvm.args}</argLine>
<excludes> <excludes>
<!-- exclude classes that end with 'Test'; these <!-- exclude classes that end with 'Test'; these
are not test cases per OpenJPA standards --> are not test cases per OpenJPA standards -->
@ -1012,52 +985,6 @@
<!-- TestEJBTransactionalClass tests nothing --> <!-- TestEJBTransactionalClass tests nothing -->
<exclude>org/apache/openjpa/persistence/kernel/TestEJBTransactionalClass.java</exclude> <exclude>org/apache/openjpa/persistence/kernel/TestEJBTransactionalClass.java</exclude>
</excludes> </excludes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>false</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>${derby.locks.deadlockTimeout}</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>${derby.locks.waitTimeout}</value>
</property>
<property>
<name>derby.storage.pageCacheSize</name>
<value>10000</value>
</property>
<property>
<name>derby.storage.initialPages</name>
<value>10</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -53,6 +53,7 @@
</activation> </activation>
<properties> <properties>
<build.enhance>false</build.enhance> <build.enhance>false</build.enhance>
<openjpa.dynamicEnhance>true</openjpa.dynamicEnhance>
<surefire.jvm.args>-Dopenjpa.RuntimeUnenhancedClasses=unsupported ${test.jvm.arguments}</surefire.jvm.args> <surefire.jvm.args>-Dopenjpa.RuntimeUnenhancedClasses=unsupported ${test.jvm.arguments}</surefire.jvm.args>
</properties> </properties>
<build> <build>
@ -61,39 +62,12 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${surefire.jvm.args}</argLine>
<includes> <includes>
<include>org/apache/openjpa/persistence/enhance/DynamicEnhancementSuite.java</include> <include>org/apache/openjpa/persistence/enhance/DynamicEnhancementSuite.java</include>
</includes> </includes>
<excludes> <excludes>
<exclude>${surefire.excludes.locking}</exclude> <exclude>${surefire.excludes.locking}</exclude>
</excludes> </excludes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@ -784,7 +758,6 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<argLine>${surefire.jvm.args}</argLine>
<excludes> <excludes>
<!-- <!--
exclude classes that end with 'Test'; these are not test cases per OpenJPA standards exclude classes that end with 'Test'; these are not test cases per OpenJPA standards
@ -792,44 +765,6 @@
<exclude>org/apache/openjpa/**/*Test.java</exclude> <exclude>org/apache/openjpa/**/*Test.java</exclude>
<exclude>${surefire.excludes.locking}</exclude> <exclude>${surefire.excludes.locking}</exclude>
</excludes> </excludes>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>false</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>${derby.locks.deadlockTimeout}</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>${derby.locks.waitTimeout}</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>Username=${connection.username},Password=${connection.password},${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

57
pom.xml
View File

@ -53,6 +53,9 @@
<test.jvm.maxheapsize>1024m</test.jvm.maxheapsize> <test.jvm.maxheapsize>1024m</test.jvm.maxheapsize>
<test.jvm.arguments>-Xmx${test.jvm.maxheapsize} -XX:MaxPermSize=${test.jvm.maxpermsize}</test.jvm.arguments> <test.jvm.arguments>-Xmx${test.jvm.maxheapsize} -XX:MaxPermSize=${test.jvm.maxpermsize}</test.jvm.arguments>
<surefire.jvm.args>${test.jvm.arguments}</surefire.jvm.args> <surefire.jvm.args>${test.jvm.arguments}</surefire.jvm.args>
<!-- Setting for openjpa.DynamicEnhancementAgent usage -->
<openjpa.dynamicEnhance>false</openjpa.dynamicEnhance>
<!-- Commons DBCP settings passed in as openjpa.ConnectionProperties -->
<dbcp.maxActive>10</dbcp.maxActive> <dbcp.maxActive>10</dbcp.maxActive>
<dbcp.maxIdle>5</dbcp.maxIdle> <dbcp.maxIdle>5</dbcp.maxIdle>
<dbcp.minIdle>2</dbcp.minIdle> <dbcp.minIdle>2</dbcp.minIdle>
@ -685,6 +688,60 @@
<useFile>false</useFile> <useFile>false</useFile>
<trimStackTrace>false</trimStackTrace> <trimStackTrace>false</trimStackTrace>
<useSystemClassLoader>true</useSystemClassLoader> <useSystemClassLoader>true</useSystemClassLoader>
<systemProperties>
<property>
<name>openjpa.Log</name>
<value>${openjpa.Log}</value>
</property>
<property>
<name>openjpa.DynamicEnhancementAgent</name>
<value>${openjpa.dynamicEnhance}</value>
</property>
<property>
<name>openjpa.ConnectionDriverName</name>
<value>${connection.driver.name}</value>
</property>
<property>
<name>openjpa.ConnectionURL</name>
<value>${connection.url}</value>
</property>
<property>
<name>openjpa.ConnectionUserName</name>
<value>${connection.username}</value>
</property>
<property>
<name>openjpa.ConnectionPassword</name>
<value>${connection.password}</value>
</property>
<property>
<name>derby.stream.error.file</name>
<value>target/derby.log</value>
</property>
<property>
<name>derby.locks.deadlockTimeout</name>
<value>${derby.locks.deadlockTimeout}</value>
</property>
<property>
<name>derby.locks.waitTimeout</name>
<value>${derby.locks.waitTimeout}</value>
</property>
<property>
<name>derby.storage.pageCacheSize</name>
<value>10000</value>
</property>
<property>
<name>derby.storage.initialPages</name>
<value>10</value>
</property>
<property>
<name>openjpa.ConnectionProperties</name>
<value>${dbcp.args}</value>
</property>
<property>
<name>tests.openjpa.allowfailure</name>
<value>${tests.openjpa.allowfailure}</value>
</property>
</systemProperties>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>