From 239643043159c492cceb32e2f277d404467c3553 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 4 Apr 2011 16:11:01 +0200 Subject: [PATCH] use timestamp instead of dateformat (yyyy-MM-dd HH-mm-ss) --- .../src/main/java/sonia/scm/group/Group.java | 4 - .../java/sonia/scm/repository/Changeset.java | 3 - .../java/sonia/scm/repository/Repository.java | 10 +- .../src/main/java/sonia/scm/user/User.java | 10 +- scm-webapp/pom.xml | 1 + .../java/sonia/scm/ScmContextListener.java | 19 +- .../java/sonia/scm/ScmUpgradeHandler.java | 268 ++++++++++++++++++ .../sonia/scm/group/xml/XmlGroupDatabase.java | 3 - .../repository/xml/XmlRepositoryDatabase.java | 3 - .../sonia/scm/user/xml/XmlUserDatabase.java | 3 - .../main/webapp/resources/js/sonia.group.js | 2 +- .../webapp/resources/js/sonia.repository.js | 2 +- .../main/webapp/resources/js/sonia.user.js | 4 +- .../main/webapp/resources/js/sonia.util.js | 15 +- 14 files changed, 310 insertions(+), 37 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/ScmUpgradeHandler.java diff --git a/scm-core/src/main/java/sonia/scm/group/Group.java b/scm-core/src/main/java/sonia/scm/group/Group.java index 66cdd6b355..6dc92801df 100644 --- a/scm-core/src/main/java/sonia/scm/group/Group.java +++ b/scm-core/src/main/java/sonia/scm/group/Group.java @@ -37,7 +37,6 @@ package sonia.scm.group; import sonia.scm.ModelObject; import sonia.scm.util.Util; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -49,7 +48,6 @@ import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * @@ -512,14 +510,12 @@ public class Group implements ModelObject, Iterable //~--- fields --------------------------------------------------------------- /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long creationDate; /** Field description */ private String description; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long lastModified; /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/repository/Changeset.java b/scm-core/src/main/java/sonia/scm/repository/Changeset.java index 59906a0349..3a5421598c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Changeset.java +++ b/scm-core/src/main/java/sonia/scm/repository/Changeset.java @@ -37,7 +37,6 @@ package sonia.scm.repository; import sonia.scm.Validateable; import sonia.scm.util.Util; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -48,7 +47,6 @@ import java.util.Date; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * @@ -316,7 +314,6 @@ public class Changeset implements Validateable, Cloneable, Serializable private String author; /** The date when the changeset was committed */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long date; /** The text of the changeset description */ diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index 165027a635..c5e2627d0b 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -38,7 +38,6 @@ package sonia.scm.repository; import sonia.scm.ModelObject; import sonia.scm.util.Util; import sonia.scm.util.ValidationUtil; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -50,7 +49,6 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * @@ -331,7 +329,7 @@ public class Repository implements ModelObject * * @return */ - public long getCreationDate() + public Long getCreationDate() { return creationDate; } @@ -459,7 +457,7 @@ public class Repository implements ModelObject * * @param creationDate */ - public void setCreationDate(long creationDate) + public void setCreationDate(Long creationDate) { this.creationDate = creationDate; } @@ -492,7 +490,7 @@ public class Repository implements ModelObject * * @param lastModified */ - public void setLastModified(long lastModified) + public void setLastModified(Long lastModified) { this.lastModified = lastModified; } @@ -558,7 +556,6 @@ public class Repository implements ModelObject private String contact; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long creationDate; /** Field description */ @@ -568,7 +565,6 @@ public class Repository implements ModelObject private String id; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long lastModified; /** Field description */ diff --git a/scm-core/src/main/java/sonia/scm/user/User.java b/scm-core/src/main/java/sonia/scm/user/User.java index bdd070f71c..67f8b599c6 100644 --- a/scm-core/src/main/java/sonia/scm/user/User.java +++ b/scm-core/src/main/java/sonia/scm/user/User.java @@ -38,7 +38,6 @@ package sonia.scm.user; import sonia.scm.ModelObject; import sonia.scm.util.Util; import sonia.scm.util.ValidationUtil; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -47,7 +46,6 @@ import java.security.Principal; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * @@ -314,7 +312,7 @@ public class User implements Principal, ModelObject * * @return */ - public long getCreationDate() + public Long getCreationDate() { return creationDate; } @@ -432,7 +430,7 @@ public class User implements Principal, ModelObject * * @param creationDate */ - public void setCreationDate(long creationDate) + public void setCreationDate(Long creationDate) { this.creationDate = creationDate; } @@ -454,7 +452,7 @@ public class User implements Principal, ModelObject * * @param lastModified */ - public void setLastModified(long lastModified) + public void setLastModified(Long lastModified) { this.lastModified = lastModified; } @@ -510,14 +508,12 @@ public class User implements Principal, ModelObject private boolean admin; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long creationDate; /** Field description */ private String displayName; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long lastModified; /** Field description */ diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index baef47f037..b93f6918c8 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -278,6 +278,7 @@ 1.11 1.0-beta-7 3.0.3 + Tomcat60 diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index de70c6e206..f708cf2fc1 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -40,6 +40,7 @@ import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.servlet.GuiceServletContextListener; +import sonia.scm.cache.CacheManager; import sonia.scm.group.GroupManager; import sonia.scm.plugin.DefaultPluginLoader; import sonia.scm.plugin.PluginLoader; @@ -55,7 +56,6 @@ import java.util.ArrayList; import java.util.List; import javax.servlet.ServletContextEvent; -import sonia.scm.cache.CacheManager; /** * @@ -92,12 +92,27 @@ public class ScmContextListener extends GuiceServletContextListener IOUtil.close(injector.getInstance(StoreFactory.class)); // close CacheManager - IOUtil.close( injector.getInstance( CacheManager.class ) ); + IOUtil.close(injector.getInstance(CacheManager.class)); } super.contextDestroyed(servletContextEvent); } + /** + * Method description + * + * + * @param servletContextEvent + */ + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) + { + ScmUpgradeHandler upgradeHandler = new ScmUpgradeHandler(); + + upgradeHandler.doUpgrade(); + super.contextInitialized(servletContextEvent); + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-webapp/src/main/java/sonia/scm/ScmUpgradeHandler.java b/scm-webapp/src/main/java/sonia/scm/ScmUpgradeHandler.java new file mode 100644 index 0000000000..5b2d2cafb6 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/ScmUpgradeHandler.java @@ -0,0 +1,268 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.xml.sax.SAXException; + +import sonia.scm.util.IOUtil; +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.text.ParseException; + +import java.util.Date; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +/** + * + * @author Sebastian Sdorra + */ +public class ScmUpgradeHandler +{ + + /** the logger for ScmUpgradeHandler */ + private static final Logger logger = + LoggerFactory.getLogger(ScmUpgradeHandler.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + public void doUpgrade() + { + File baseDirectory = SCMContext.getContext().getBaseDirectory(); + File configDirectory = new File(baseDirectory, "config"); + File versionFile = new File(configDirectory, "version.txt"); + + // pre version 1.2 + if (!versionFile.exists()) + { + if (logger.isInfoEnabled()) + { + logger.info("upgrade to version {}", + SCMContext.getContext().getVersion()); + } + + fixDate(configDirectory); + } + + writeVersionFile(versionFile); + } + + /** + * Method description + * + * + * @param value + * + * @return + */ + private String convertDate(String value) + { + if (Util.isNotEmpty(value)) + { + try + { + Date date = Util.parseDate(value); + + if (date != null) + { + value = Long.toString(date.getTime()); + } + } + catch (ParseException ex) + { + logger.warn("could not parse date", ex); + } + } + + return value; + } + + /** + * Method description + * + * + * @param configDirectory + */ + private void fixDate(File configDirectory) + { + try + { + DocumentBuilder builder = + DocumentBuilderFactory.newInstance().newDocumentBuilder(); + + fixDate(builder, configDirectory, "users.xml"); + fixDate(builder, configDirectory, "groups.xml"); + fixDate(builder, configDirectory, "repositories.xml"); + } + catch (Exception ex) + { + logger.error("could not parse document", ex); + } + } + + /** + * Method description + * + * + * @param builder + * @param configDirectory + * @param filename + * + * @throws IOException + * @throws SAXException + * @throws TransformerConfigurationException + * @throws TransformerException + */ + private void fixDate(DocumentBuilder builder, File configDirectory, + String filename) + throws SAXException, IOException, TransformerConfigurationException, + TransformerException + { + File configFile = new File(configDirectory, filename); + + if (configFile.exists()) + { + if (logger.isInfoEnabled()) + { + logger.info("fix date elements of {}", configFile.getPath()); + } + + Document document = builder.parse(configFile); + + fixDate(document, "lastModified"); + fixDate(document, "creationDate"); + fixDate(document, "creationTime"); + writeDocument(document, configFile); + } + } + + /** + * Method description + * + * + * @param document + * @param element + */ + private void fixDate(Document document, String element) + { + NodeList nodes = document.getElementsByTagName(element); + + if (nodes != null) + { + for (int i = 0; i < nodes.getLength(); i++) + { + Node node = nodes.item(i); + String value = node.getTextContent(); + + value = convertDate(value); + node.setTextContent(value); + } + } + } + + /** + * Method description + * + * + * @param document + * @param configFile + * + * @throws TransformerConfigurationException + * @throws TransformerException + */ + private void writeDocument(Document document, File configFile) + throws TransformerConfigurationException, TransformerException + { + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.transform(new DOMSource(document), + new StreamResult(configFile)); + } + + /** + * Method description + * + * + * @param versionFile + */ + private void writeVersionFile(File versionFile) + { + OutputStream output = null; + + try + { + output = new FileOutputStream(versionFile); + output.write(SCMContext.getContext().getVersion().getBytes()); + } + catch (IOException ex) + { + logger.error("could not write version file", ex); + } + finally + { + IOUtil.close(output); + } + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java b/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java index 4a11df1bc5..e7bbe0de9e 100644 --- a/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java +++ b/scm-webapp/src/main/java/sonia/scm/group/xml/XmlGroupDatabase.java @@ -36,7 +36,6 @@ package sonia.scm.group.xml; //~--- non-JDK imports -------------------------------------------------------- import sonia.scm.group.Group; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -185,7 +184,6 @@ public class XmlGroupDatabase //~--- fields --------------------------------------------------------------- /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long creationTime; /** Field description */ @@ -194,6 +192,5 @@ public class XmlGroupDatabase private Map groupMap = new LinkedHashMap(); /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long lastModified; } diff --git a/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java b/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java index 8a0e71e1c0..d0993a73ba 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/xml/XmlRepositoryDatabase.java @@ -36,7 +36,6 @@ package sonia.scm.repository.xml; //~--- non-JDK imports -------------------------------------------------------- import sonia.scm.repository.Repository; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -264,11 +263,9 @@ public class XmlRepositoryDatabase //~--- fields --------------------------------------------------------------- /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long creationTime; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long lastModified; /** Field description */ diff --git a/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java b/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java index 221d4f4c74..ab90f79e5a 100644 --- a/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java +++ b/scm-webapp/src/main/java/sonia/scm/user/xml/XmlUserDatabase.java @@ -36,7 +36,6 @@ package sonia.scm.user.xml; //~--- non-JDK imports -------------------------------------------------------- import sonia.scm.user.User; -import sonia.scm.xml.XmlTimestampDateAdapter; //~--- JDK imports ------------------------------------------------------------ @@ -185,11 +184,9 @@ public class XmlUserDatabase //~--- fields --------------------------------------------------------------- /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long creationTime; /** Field description */ - @XmlJavaTypeAdapter(XmlTimestampDateAdapter.class) private Long lastModified; /** Field description */ diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.group.js b/scm-webapp/src/main/webapp/resources/js/sonia.group.js index d488e37417..31e7b81e9a 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.group.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.group.js @@ -84,7 +84,7 @@ Sonia.group.Grid = Ext.extend(Sonia.rest.Grid, { {id: 'name', header: this.colNameText, dataIndex: 'name'}, {id: 'description', header: this.colDescriptionText, dataIndex: 'description', width: 300 }, {id: 'members', header: this.colMembersText, dataIndex: 'members', renderer: this.renderMembers}, - {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate'}, + {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate', renderer: Ext.util.Format.formatTimestamp}, {id: 'type', header: this.colTypeText, dataIndex: 'type', width: 80} ] }); diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.repository.js b/scm-webapp/src/main/webapp/resources/js/sonia.repository.js index c5949314fa..72d03a5e4e 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.repository.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.repository.js @@ -118,7 +118,7 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { {id: 'type', header: this.colTypeText, dataIndex: 'type', renderer: this.renderRepositoryType, width: 80}, {id: 'contact', header: this.colContactText, dataIndex: 'contact', renderer: this.renderMailto}, {id: 'description', header: this.colDescriptionText, dataIndex: 'description'}, - {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate'}, + {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate', renderer: Ext.util.Format.formatTimestamp}, {id: 'Url', header: this.colUrlText, dataIndex: 'url', renderer: this.renderUrl, width: 250} ] }); diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.user.js b/scm-webapp/src/main/webapp/resources/js/sonia.user.js index 91eb1c7c57..19cbd566a1 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.user.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.user.js @@ -91,8 +91,8 @@ Sonia.user.Grid = Ext.extend(Sonia.rest.Grid, { {id: 'displayName', header: this.colDisplayNameText, dataIndex: 'displayName', width: 250}, {id: 'mail', header: this.colMailText, dataIndex: 'mail', renderer: this.renderMailto, width: 200}, {id: 'admin', header: this.colAdminText, dataIndex: 'admin', renderer: this.renderCheckbox, width: 50}, - {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate'}, - {id: 'lastModified', header: this.colLastModifiedText, dataIndex: 'lastModified'}, + {id: 'creationDate', header: this.colCreationDateText, dataIndex: 'creationDate', renderer: Ext.util.Format.formatTimestamp}, + {id: 'lastModified', header: this.colLastModifiedText, dataIndex: 'lastModified', renderer: Ext.util.Format.formatTimestamp}, {id: 'type', header: this.colTypeText, dataIndex: 'type', width: 80} ] }); diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.util.js b/scm-webapp/src/main/webapp/resources/js/sonia.util.js index a4d30224a8..a43ab29029 100644 --- a/scm-webapp/src/main/webapp/resources/js/sonia.util.js +++ b/scm-webapp/src/main/webapp/resources/js/sonia.util.js @@ -31,6 +31,14 @@ Ext.apply(Ext.util.Format, { + formatTimestamp: function(value){ + var result = ''; + if ( value != null && (value > 0 ||value.length > 0)){ + result = Ext.util.Format.date(new Date(value), "Y-m-d H:i:s"); + } + return result; + }, + timeAgo : function(value){ var time_formats = [ @@ -54,7 +62,12 @@ var date = value; if (!Ext.isDate(date)){ - date = new Date(Date.parse(date)); + date = parseInt(date); + if ( date == 'NaN' ){ + date = Ext.parseDate(value) + } else { + date = new Date(date); + } } var seconds = (new Date - date) / 1000;