You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by mr...@apache.org on 2005/08/26 07:46:58 UTC
svn commit: r240168 [26/30] - in /struts/sandbox/trunk/ti: ./
core/src/java/org/apache/ti/ core/src/java/org/apache/ti/config/
core/src/java/org/apache/ti/config/mapper/
core/src/java/org/apache/ti/core/ core/src/java/org/apache/ti/core/factory/
core/s...
Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/type/TypeUtils.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/type/TypeUtils.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/type/TypeUtils.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/type/TypeUtils.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,609 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.type;
+
+import org.apache.ti.schema.config.NetuiConfigDocument.NetuiConfig;
+import org.apache.ti.schema.config.TypeConverters;
+import org.apache.ti.util.Bundle;
+import org.apache.ti.util.config.ConfigUtil;
+import org.apache.ti.util.internal.InternalStringBuilder;
+import org.apache.ti.util.logging.Logger;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ *
+ *
+ */
+public final class TypeUtils {
+
+ private static final Logger LOGGER = Logger.getInstance(TypeUtils.class);
+ private static final String TYPE_CONVERTER_PROPERTIES = "/properties/netui-typeconverter.properties";
+ private static final String EMPTY_STRING = "";
+ private static final HashMap/*<Class, BaseTypeConverter>*/ TYPE_CONVERTERS = new HashMap/*<Class, BaseTypeConverter>*/();
+ private static String TO_STRING = null;
+
+ static {
+ // initialize the default type converters
+ initialize();
+
+ Map/*<String, String>*/ map = readFromConfig();
+ if (map != null) {
+ load(map);
+ map.clear();
+ }
+
+ map = readFromProperties();
+ if (map != null)
+ load(map);
+
+ LOGGER.info(registeredConvertersToString());
+ }
+
+ /* do not construct */
+ private TypeUtils() {
+ }
+
+ /**
+ * Convert an object from a String to the given type.
+ *
+ * @param value the String to convert
+ * @param type the type to which to convert the String
+ * @return the Object result of converting the String to the type.
+ * @throws TypeConverterNotFoundException if a TypeConverter for the target type can not be found.
+ * @deprecated
+ */
+ public static final Object convertToObject(String value, Class type) {
+ return convertToObject(value, type, null);
+ }
+
+ /**
+ * Convert an object from a String to the given type using the specified {@link java.util.Locale}.
+ * <p/>
+ * The locale is optionally used depending on the implementation of the {@link TypeConverter} that is used.
+ *
+ * @param value the String to convert
+ * @param type the type to which to convert the String
+ * @param locale the locale to use during conversion
+ * @return the Object result of converting the String to the type.
+ * @throws TypeConverterNotFoundException if a TypeConverter for the target type can not be found.
+ */
+ public static final Object convertToObject(String value, Class type, Locale locale) {
+ BaseTypeConverter converter = lookupTypeConverter(type);
+ assert converter != null;
+ return converter.convertToObject(type, value, locale);
+ }
+
+ public static final byte convertToByte(String value) {
+ return ((Byte) convertToObject(value, byte.class, null)).byteValue();
+ }
+
+ public static final boolean convertToBoolean(String value) {
+ return ((Boolean) convertToObject(value, boolean.class, null)).booleanValue();
+ }
+
+ public static final char convertToChar(String value) {
+ return ((Character) convertToObject(value, char.class, null)).charValue();
+ }
+
+ public static final double convertToDouble(String value) {
+ return ((Double) convertToObject(value, double.class, null)).doubleValue();
+ }
+
+ public static final float convertToFloat(String value) {
+ return ((Float) convertToObject(value, float.class, null)).floatValue();
+ }
+
+ public static final int convertToInt(String value) {
+ return ((Integer) convertToObject(value, int.class, null)).intValue();
+ }
+
+ public static final long convertToLong(String value) {
+ return ((Long) convertToObject(value, long.class, null)).longValue();
+ }
+
+ public static final short convertToShort(String value) {
+ return ((Short) convertToObject(value, short.class, null)).shortValue();
+ }
+
+ public static final Byte convertToByteObject(String value) {
+ return (Byte) convertToObject(value, Byte.class, null);
+ }
+
+ public static final Boolean convertToBooleanObject(String value) {
+ return (Boolean) convertToObject(value, Boolean.class, null);
+ }
+
+ public static final Character convertToCharacterObject(String value) {
+ return (Character) convertToObject(value, Character.class, null);
+ }
+
+ public static final Double convertToDoubleObject(String value) {
+ return (Double) convertToObject(value, Double.class, null);
+ }
+
+ public static final Float convertToFloatObject(String value) {
+ return (Float) convertToObject(value, Float.class, null);
+ }
+
+ public static final Integer convertToIntegerObject(String value) {
+ return (Integer) convertToObject(value, Integer.class, null);
+ }
+
+ public static final Long convertToLongObject(String value) {
+ return (Long) convertToObject(value, Long.class, null);
+ }
+
+ public static final Short convertToShortObject(String value) {
+ return (Short) convertToObject(value, Short.class, null);
+ }
+
+ /**
+ * Internal method used to lookup a {@link BaseTypeConverter}.
+ *
+ * @param type the target conversion type
+ * @return a {@link BaseTypeConverter} to use for conversion
+ * @throws TypeConverterNotFoundException if a TypeConverter for the target type can not be found.
+ */
+ private static final BaseTypeConverter lookupTypeConverter(Class type) {
+ BaseTypeConverter converter = (BaseTypeConverter) TYPE_CONVERTERS.get(type);
+ if (converter == null) {
+ String msg = "Could not find a TypeConverter for converting a String to an object of type \"" +
+ (type != null ? type.getName() : null) + "\"";
+ TypeConverterNotFoundException tcn = new TypeConverterNotFoundException(msg);
+
+ if (type == null)
+ msg = Bundle.getErrorString("TypeUtils_nullType");
+ else
+ msg = Bundle.getErrorString("TypeUtils_noConverterForType", new Object[]{type.getName()});
+ tcn.setLocalizedMessage(msg);
+ LOGGER.error(msg);
+
+ throw tcn;
+ }
+
+ return converter;
+ }
+
+ private static String registeredConvertersToString() {
+ if (TO_STRING != null)
+ return TO_STRING;
+
+ InternalStringBuilder sb = new InternalStringBuilder(256);
+ sb.append(TypeUtils.class.getName() + " regestered converters (class name, TypeConverter implementation):\n");
+ sb.append(":::::\n");
+ Iterator iterator = TYPE_CONVERTERS.keySet().iterator();
+ while (iterator.hasNext()) {
+ Class key = (Class) iterator.next();
+ String keyName = key.getName();
+ String value = (TYPE_CONVERTERS.get(key) != null ? TYPE_CONVERTERS.get(key).getClass().getName() : "null");
+ sb.append(keyName);
+ sb.append(", ");
+ sb.append(value);
+ sb.append("\n");
+ }
+ sb.append(":::::\n");
+ TO_STRING = sb.toString();
+
+ return TO_STRING;
+ }
+
+ private static Map/*<String, String>*/ readFromProperties() {
+ Properties props = null;
+ InputStream is = null;
+ try {
+ is = (TypeUtils.class).getClassLoader().getResourceAsStream(TYPE_CONVERTER_PROPERTIES);
+
+ LOGGER.debug("found type converter InputStream at " + TYPE_CONVERTER_PROPERTIES + " " + (is != null ? "true" : "false"));
+
+ if (is == null)
+ return null;
+
+ props = new Properties();
+ props.load(is);
+ } catch (Exception e) {
+ LOGGER.warn("Error occurred reading type converter properties file", e);
+ } finally {
+ try {
+ if (is != null) is.close();
+ } catch (Exception ignore) {
+ }
+ }
+
+ LinkedHashMap/*<String, String>*/ map = new LinkedHashMap/*<String, String>*/();
+ Enumeration e = props.propertyNames();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ map.put(key, props.getProperty(key));
+ }
+
+ return map;
+ }
+
+ private static final Map/*<String, String>*/ readFromConfig() {
+ NetuiConfig config = ConfigUtil.getConfig();
+ if (config == null)
+ return null;
+
+ TypeConverters converters = config.getTypeConverters();
+ if (converters == null)
+ return null;
+
+ org.apache.ti.schema.config.TypeConverters.TypeConverter[] converterArray =
+ converters.getTypeConverterArray();
+ if (converterArray == null)
+ return null;
+
+ LinkedHashMap/*<String, String>*/ map = new LinkedHashMap/*<String, String>*/();
+ for (int i = 0; i < converterArray.length; i++) {
+ map.put(converterArray[i].getType(), converterArray[i].getConverterClass());
+ }
+
+ return map;
+ }
+
+ private static void load(Map/*<String, String>*/ map) {
+ // load the properties and continue to populate the map
+ for (Iterator i = map.keySet().iterator(); i.hasNext();) {
+ String key = (String) i.next();
+ String className = (String) map.get(key);
+
+ if ((key == null || key.equals(EMPTY_STRING)) || (className == null || className.equals(EMPTY_STRING))) {
+ LOGGER.warn("Could not create a TypeConverter for type \"" + key + "\" and TypeConverter \"" + className + "\"");
+ continue;
+ }
+
+ Class targetClazz = null;
+
+ /* attempt to load the "convert-to" class */
+ try {
+ targetClazz = Class.forName(key);
+ } catch (ClassNotFoundException cnf) {
+ LOGGER.warn("Could not create a TypeConverter for type \"" + key + "\" because the \"convert-to\" type could not be found.");
+ continue;
+ }
+
+ Class tcClazz = null;
+ BaseTypeConverter tc = null;
+ // try to find the TypeConverter implementation
+ try {
+ tcClazz = Class.forName(className);
+ Object obj = tcClazz.newInstance();
+
+ // this supports existing TypeConverter implementations
+ // but allows TypeUtils make calls against the BaseTypeConverter
+ // API, which supports Locale-based conversion
+ if (obj instanceof TypeConverter)
+ tc = new DelegatingTypeConverter((TypeConverter) obj);
+ else if (obj instanceof BaseTypeConverter)
+ tc = (BaseTypeConverter) obj;
+ else
+ throw new IllegalStateException("Attempt to load illegal type converter type: " + tcClazz);
+ } catch (ClassNotFoundException cnf) {
+ LOGGER.warn("Could not create a TypeConverter for type \"" + key + "\" because the TypeConverter implementation class \"" +
+ (tcClazz != null ? tcClazz.getName() : null) + "\" could not be found.");
+
+ continue;
+ } catch (Exception e) {
+ if (LOGGER.isWarnEnabled())
+ LOGGER.warn("Could not create a TypeConverter for type \"" + key + "\" because the implementation class \"" +
+ (tcClazz != null ? tcClazz.getName() : null) + "\" could not be instantiated.");
+ continue;
+ }
+
+ /* found two type converters for the same class -- warn */
+ if (TYPE_CONVERTERS.containsKey(targetClazz))
+ if (LOGGER.isWarnEnabled())
+ LOGGER.warn("Overwriting a previously defined TypeConverter named \"" + targetClazz +
+ "\" with a new TypeConverter implementation of type \"" + className + "\"");
+
+ if (LOGGER.isInfoEnabled())
+ LOGGER.info("Adding a type converter; target type=\"" + targetClazz.getName() +
+ "\" TypeConverter implementation=\"" + tc.getClass().getName() + "\"");
+
+ TYPE_CONVERTERS.put(targetClazz, tc);
+ }
+ }
+
+ /**
+ * Create converters that take an Object representing a value and convert
+ * that value, based on its type, to a String. Includes all primitive types,
+ * primitive wrappers, String, and BigDecimal. Types like BigDecimal are included
+ * because JDBC uses these complex types to map SQL types to Java objects.
+ */
+ private static void initialize() {
+ TYPE_CONVERTERS.put(byte.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ return (value == null || value.equals(EMPTY_STRING) ? new Byte((byte) 0) : new Byte(value.trim()));
+ }
+
+ });
+ TYPE_CONVERTERS.put(Byte.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, byte.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(boolean.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return Boolean.FALSE;
+
+ value = value.toLowerCase().trim();
+ if (value.equals("on") || value.equals("true"))
+ return Boolean.TRUE;
+ else
+ return Boolean.FALSE;
+ }
+ });
+ TYPE_CONVERTERS.put(Boolean.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, boolean.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(char.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return new Character('\u0000');
+ else
+ return new Character(value.charAt(0));
+ }
+ });
+ TYPE_CONVERTERS.put(Character.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, char.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(double.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return new Double(0.0);
+ else
+ return new Double(value.trim());
+ }
+ });
+ TYPE_CONVERTERS.put(Double.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, double.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(float.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return new Float(0.0);
+ else
+ return new Float(value.trim());
+ }
+ });
+ TYPE_CONVERTERS.put(Float.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, float.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(int.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return new Integer(0);
+ else
+ return new Integer(value.trim());
+ }
+ });
+ TYPE_CONVERTERS.put(Integer.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, int.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(long.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return new Long(0);
+ else
+ return new Long(value.trim());
+ }
+ });
+ TYPE_CONVERTERS.put(Long.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, long.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(short.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return new Short((short) 0);
+ else
+ return new Short(value.trim());
+ }
+ });
+ TYPE_CONVERTERS.put(Short.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return TypeUtils.convertToObject(value, short.class, null);
+ }
+ });
+
+ TYPE_CONVERTERS.put(String.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null)
+ return null;
+ else
+ return value;
+ }
+ });
+
+ TYPE_CONVERTERS.put(java.math.BigDecimal.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return new BigDecimal(value.trim());
+ }
+ });
+
+ TYPE_CONVERTERS.put(java.math.BigInteger.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return new BigInteger(value.trim());
+ }
+ });
+
+ TYPE_CONVERTERS.put(byte[].class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else
+ return value.getBytes();
+ }
+ });
+
+ TYPE_CONVERTERS.put(Byte[].class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+ else {
+ byte[] bytes = value.getBytes();
+ Byte[] wBytes = new Byte[bytes.length];
+
+ for (int i = 0; i < bytes.length; i++)
+ wBytes[i] = new Byte(bytes[i]);
+
+ return wBytes;
+ }
+ }
+ });
+
+ TYPE_CONVERTERS.put(Date.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+
+ try {
+ if (locale == null)
+ locale = Locale.getDefault();
+
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+ return df.parse(value);
+ } catch (java.text.ParseException pe) {
+ String msg = "Caugnt an error converting a String to a DateFormat.SHORT formatted Date";
+ LOGGER.warn(msg, pe);
+
+ TypeConversionException tce = new TypeConversionException(msg, pe);
+ tce.setLocalizedMessage(Bundle.getString("TypeUtils_javaUtilDateConvertError", new Object[]{pe.getMessage()}));
+ throw tce;
+ }
+ }
+ });
+
+ /* http://java.sun.com/j2se/1.4.1/docs/api/java/sql/Date.html */
+ TYPE_CONVERTERS.put(java.sql.Date.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING)) return null;
+
+ try {
+ return java.sql.Date.valueOf(value);
+ } catch (Exception e) {
+ String msg = "Caught an error converting a String to a java.sql.Date";
+ LOGGER.error(msg, e);
+
+ TypeConversionException tce = new TypeConversionException(msg, e);
+ tce.setLocalizedMessage(Bundle.getString("TypeUtils_javaSqlDateConvertError", new Object[]{e.getMessage()}));
+ throw tce;
+ }
+ }
+ });
+
+ /* http://java.sun.com/j2se/1.4.1/docs/api/java/sql/Timestamp.html */
+ TYPE_CONVERTERS.put(java.sql.Timestamp.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+
+ try {
+ return java.sql.Timestamp.valueOf(value);
+ } catch (Exception e) {
+ String msg = "Caught an error converting a String to a java.sql.Timestamp";
+ LOGGER.error(msg, e);
+
+ TypeConversionException tce = new TypeConversionException(msg, e);
+ tce.setLocalizedMessage(Bundle.getString("TypeUtils_javaSqlTimestampConvertError", new Object[]{e.getMessage()}));
+ throw tce;
+ }
+ }
+ });
+
+ /* http://java.sun.com/j2se/1.4.1/docs/api/java/sql/Time.html */
+ TYPE_CONVERTERS.put(java.sql.Time.class, new BaseTypeConverter() {
+ public Object convertToObject(Class type, String value, Locale locale) {
+ if (value == null || value.equals(EMPTY_STRING))
+ return null;
+
+ try {
+ return java.sql.Time.valueOf(value);
+ } catch (Exception e) {
+ String msg = "Caught an error converting a String to a java.sql.Time";
+ LOGGER.error(msg, e);
+
+ TypeConversionException tce = new TypeConversionException(msg, e);
+ tce.setLocalizedMessage(Bundle.getString("TypeUtils_javaSqlTimeConvertError", new Object[]{e.getMessage()}));
+ throw tce;
+ }
+ }
+ });
+ }
+}
Added: struts/sandbox/trunk/ti/java5/project.properties
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/java5/project.properties?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/java5/project.properties (added)
+++ struts/sandbox/trunk/ti/java5/project.properties Thu Aug 25 22:46:03 2005
@@ -0,0 +1 @@
+maven.compile.source=1.5
Added: struts/sandbox/trunk/ti/java5/project.xml
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/java5/project.xml?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/java5/project.xml (added)
+++ struts/sandbox/trunk/ti/java5/project.xml Thu Aug 25 22:46:03 2005
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+
+<project>
+
+ <extend>../project.xml</extend>
+ <id>struts-ti-java5</id>
+ <name>Struts Ti Java5 Support</name>
+
+</project>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org