Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

copied bookmarks sample out of project tree

git-svn-id: https://svn.codehaus.org/grails/trunk@5105 1cfb16fd-6d17-0410-8ff1-b7e8e1e2867d
  • Loading branch information...
commit 3e0d92241d94ea8d382aee09d0f766a7064c8c7b 0 parents
graeme authored

Showing 233 changed files with 21,747 additions and 0 deletions. Show diff stats Hide diff stats

  1. +66 0 .classpath
  2. +23 0 .project
  3. +3 0  .settings/org.codehaus.groovy.eclipse.preferences.prefs
  4. +64 0 .settings/org.eclipse.jdt.core.prefs
  5. +21 0 README.txt
  6. +20 0 bookmarks.launch
  7. +8 0 grails-app/conf/ApplicationBootStrap.groovy
  8. +12 0 grails-app/conf/ApplicationDataSource.groovy
  9. +9 0 grails-app/conf/BookmarksUrlMappings.groovy
  10. +10 0 grails-app/conf/DevelopmentDataSource.groovy
  11. +10 0 grails-app/conf/ProductionDataSource.groovy
  12. +10 0 grails-app/conf/TestDataSource.groovy
  13. +37 0 grails-app/conf/log4j.development.properties
  14. +37 0 grails-app/conf/log4j.production.properties
  15. +37 0 grails-app/conf/log4j.test.properties
  16. +185 0 grails-app/controllers/BookmarkController.groovy
  17. +11 0 grails-app/controllers/SecureController.groovy
  18. +19 0 grails-app/controllers/SubscriptionController.groovy
  19. +73 0 grails-app/controllers/TagController.groovy
  20. +36 0 grails-app/controllers/UserController.groovy
  21. +20 0 grails-app/i18n/messages.properties
  22. +60 0 grails-app/jobs/SubscriptionJob.groovy
  23. +34 0 grails-app/services/BookmarkService.groovy
  24. +53 0 grails-app/services/DeliciousService.groovy
  25. +30 0 grails-app/taglib/BookmarkTagLib.groovy
  26. +25 0 grails-app/views/bookmark/_bookmark.gsp
  27. +16 0 grails-app/views/bookmark/_editor.gsp
  28. +7 0 grails-app/views/bookmark/_suggest.gsp
  29. +37 0 grails-app/views/bookmark/create.gsp
  30. +10 0 grails-app/views/bookmark/edit.gsp
  31. +36 0 grails-app/views/bookmark/list.gsp
  32. +1 0  grails-app/views/bookmark/show.gsp
  33. +46 0 grails-app/views/error.gsp
  34. +88 0 grails-app/views/layouts/main.gsp
  35. +3 0  grails-app/views/subscription/_subscription.gsp
  36. +32 0 grails-app/views/subscription/list.gsp
  37. +44 0 grails-app/views/tag/create.gsp
  38. +51 0 grails-app/views/tag/edit.gsp
  39. +50 0 grails-app/views/tag/list.gsp
  40. +56 0 grails-app/views/tag/show.gsp
  41. +35 0 grails-app/views/user/login.gsp
  42. +57 0 grails-app/views/user/register.gsp
  43. +180 0 grails-tests/BookmarkTests.groovy
  44. +20 0 grails-tests/DeliciousTests.groovy
  45. +59 0 grails-tests/SubscriptionTests.groovy
  46. +15 0 hibernate/hibernate.cfg.xml
  47. BIN  lib/acegi-security-1.0.1.jar
  48. BIN  lib/acegi-security-jetty-1.0.1.jar
  49. BIN  lib/acegi-security-tiger-1.0.1.jar
  50. BIN  lib/activation.jar
  51. BIN  lib/commons-codec-1.3.jar
  52. BIN  lib/commons-email-1.0.jar
  53. BIN  lib/commons-httpclient-3.0.1.jar
  54. BIN  lib/jaxen-1.1-beta-9.jar
  55. BIN  lib/jdom-1.0.jar
  56. BIN  lib/mail.jar
  57. BIN  lib/stax-api-1.0.1.jar
  58. BIN  lib/wsdl4j-1.5.2.jar
  59. BIN  lib/wss4j-1.5.0.jar
  60. BIN  lib/wstx-asl-3.0.1.jar
  61. BIN  lib/xfire-all-1.2.2.jar
  62. BIN  lib/xstream-1.2.jar
  63. +150 0 plugins/core/grails-app/taglib/ApplicationTagLib.groovy
  64. +602 0 plugins/core/grails-app/taglib/FormTagLib.groovy
  65. +544 0 plugins/core/grails-app/taglib/JavascriptTagLib.groovy
  66. +377 0 plugins/core/grails-app/taglib/RenderTagLib.groovy
  67. +41 0 plugins/core/grails-app/taglib/TagLibUtil.groovy
  68. +214 0 plugins/core/grails-app/taglib/UITagLib.groovy
  69. +293 0 plugins/core/grails-app/taglib/ValidationTagLib.groovy
  70. +11 0 plugins/core/grails-app/utils/HTMLCodec.groovy
  71. +7 0 plugins/core/grails-app/utils/JavaScriptCodec.groovy
  72. +22 0 plugins/core/grails-app/utils/URLCodec.groovy
  73. +179 0 spring/resources.xml
  74. +14 0 src/java/org/grails/bookmarks/Bookmark.aegis.xml
  75. +90 0 src/java/org/grails/bookmarks/Bookmark.java
  76. +8 0 src/java/org/grails/bookmarks/BookmarkConstraints.groovy
  77. +23 0 src/java/org/grails/bookmarks/IBookmarkService.java
  78. +44 0 src/java/org/grails/bookmarks/Subscription.java
  79. +31 0 src/java/org/grails/bookmarks/Tag.java
  80. +48 0 src/java/org/grails/bookmarks/TagReference.java
  81. +79 0 src/java/org/grails/bookmarks/User.java
  82. +128 0 src/java/org/grails/bookmarks/api/BookmarkXmlController.java
  83. +39 0 web-app/WEB-INF/applicationContext.xml
  84. +37 0 web-app/WEB-INF/log4j.properties
  85. +14 0 web-app/WEB-INF/sitemesh.xml
  86. +13 0 web-app/WEB-INF/test-applicationContext.xml
  87. +416 0 web-app/WEB-INF/tld/2.3/c.tld
  88. +442 0 web-app/WEB-INF/tld/2.3/fmt.tld
  89. +311 0 web-app/WEB-INF/tld/2.3/spring.tld
  90. +563 0 web-app/WEB-INF/tld/2.4/c.tld
  91. +671 0 web-app/WEB-INF/tld/2.4/fmt.tld
  92. +311 0 web-app/WEB-INF/tld/2.4/spring.tld
  93. +563 0 web-app/WEB-INF/tld/c.tld
  94. +671 0 web-app/WEB-INF/tld/fmt.tld
  95. +550 0 web-app/WEB-INF/tld/grails.tld
  96. +311 0 web-app/WEB-INF/tld/spring.tld
  97. +113 0 web-app/WEB-INF/web.template.xml
  98. +192 0 web-app/WEB-INF/web.xml
  99. +127 0 web-app/css/main.css
  100. +58 0 web-app/css/tree/check/tree.css
  101. +97 0 web-app/css/tree/default/tree.css
  102. +55 0 web-app/css/tree/folders/tree.css
  103. +58 0 web-app/css/tree/menu/tree.css
  104. BIN  web-app/images/grails_logo.jpg
  105. BIN  web-app/images/spinner.gif
  106. BIN  web-app/images/tree/bullet.gif
  107. BIN  web-app/images/tree/check/check0.gif
  108. BIN  web-app/images/tree/check/check1.gif
  109. BIN  web-app/images/tree/check/check2.gif
  110. BIN  web-app/images/tree/check/lm.gif
  111. BIN  web-app/images/tree/check/lmh.gif
  112. BIN  web-app/images/tree/check/ln.gif
  113. BIN  web-app/images/tree/check/loading.gif
  114. BIN  web-app/images/tree/check/lp.gif
  115. BIN  web-app/images/tree/check/lph.gif
  116. BIN  web-app/images/tree/check/tm.gif
  117. BIN  web-app/images/tree/check/tmh.gif
  118. BIN  web-app/images/tree/check/tn.gif
  119. BIN  web-app/images/tree/check/tp.gif
  120. BIN  web-app/images/tree/check/tph.gif
  121. BIN  web-app/images/tree/check/vline.gif
  122. BIN  web-app/images/tree/default/lm.gif
  123. BIN  web-app/images/tree/default/lmh.gif
  124. BIN  web-app/images/tree/default/ln.gif
  125. BIN  web-app/images/tree/default/loading.gif
  126. BIN  web-app/images/tree/default/lp.gif
  127. BIN  web-app/images/tree/default/lph.gif
  128. BIN  web-app/images/tree/default/tm.gif
  129. BIN  web-app/images/tree/default/tmh.gif
  130. BIN  web-app/images/tree/default/tn.gif
  131. BIN  web-app/images/tree/default/tp.gif
  132. BIN  web-app/images/tree/default/tph.gif
  133. BIN  web-app/images/tree/default/vline.gif
  134. BIN  web-app/images/tree/folders/lm.gif
  135. BIN  web-app/images/tree/folders/lmh.gif
  136. BIN  web-app/images/tree/folders/ln.gif
  137. BIN  web-app/images/tree/folders/loading.gif
  138. BIN  web-app/images/tree/folders/lp.gif
  139. BIN  web-app/images/tree/folders/lph.gif
  140. BIN  web-app/images/tree/folders/tm.gif
  141. BIN  web-app/images/tree/folders/tmh.gif
  142. BIN  web-app/images/tree/folders/tn.gif
  143. BIN  web-app/images/tree/folders/tp.gif
  144. BIN  web-app/images/tree/folders/tph.gif
  145. BIN  web-app/images/tree/folders/vline.gif
  146. BIN  web-app/images/tree/greybg.png
  147. BIN  web-app/images/tree/header.gif
  148. BIN  web-app/images/tree/logo.gif
  149. BIN  web-app/images/tree/menu/collapse.gif
  150. BIN  web-app/images/tree/menu/collapseh.gif
  151. BIN  web-app/images/tree/menu/collapseon.gif
  152. BIN  web-app/images/tree/menu/dash.gif
  153. BIN  web-app/images/tree/menu/expand.gif
  154. BIN  web-app/images/tree/menu/expandh.gif
  155. BIN  web-app/images/tree/menu/expandon.gif
  156. BIN  web-app/images/tree/menu/loading.gif
  157. BIN  web-app/images/tree/navHover2.png
  158. BIN  web-app/images/tree/qbottom.png
  159. BIN  web-app/images/tree/qmiddle.png
  160. BIN  web-app/images/tree/qtop.png
  161. +3 0  web-app/index.jsp
  162. +13 0 web-app/js/application.js
  163. +7 0 web-app/js/prototype/animation.js
  164. +101 0 web-app/js/prototype/builder.js
  165. +815 0 web-app/js/prototype/controls.js
  166. +915 0 web-app/js/prototype/dragdrop.js
  167. +958 0 web-app/js/prototype/effects.js
  168. +2,006 0 web-app/js/prototype/prototype.js
  169. +2,691 0 web-app/js/prototype/rico.js
  170. +47 0 web-app/js/prototype/scriptaculous.js
  171. +283 0 web-app/js/prototype/slider.js
  172. +383 0 web-app/js/prototype/unittest.js
  173. +7 0 web-app/js/yahoo/animation-min.js
  174. BIN  web-app/js/yahoo/assets/Thumbs.db
  175. BIN  web-app/js/yahoo/assets/alrt16_1.gif
  176. BIN  web-app/js/yahoo/assets/blck16_1.gif
  177. +163 0 web-app/js/yahoo/assets/calendar.css
  178. BIN  web-app/js/yahoo/assets/callt.gif
  179. BIN  web-app/js/yahoo/assets/calrt.gif
  180. BIN  web-app/js/yahoo/assets/calx.gif
  181. BIN  web-app/js/yahoo/assets/close12_1.gif
  182. +206 0 web-app/js/yahoo/assets/container.css
  183. BIN  web-app/js/yahoo/assets/hlp16_1.gif
  184. BIN  web-app/js/yahoo/assets/info16_1.gif
  185. BIN  web-app/js/yahoo/assets/lm.gif
  186. BIN  web-app/js/yahoo/assets/lmh.gif
  187. BIN  web-app/js/yahoo/assets/ln.gif
  188. BIN  web-app/js/yahoo/assets/loading.gif
  189. BIN  web-app/js/yahoo/assets/lp.gif
  190. BIN  web-app/js/yahoo/assets/lph.gif
  191. +264 0 web-app/js/yahoo/assets/menu.css
  192. BIN  web-app/js/yahoo/assets/menuarodwn9_clk_1.gif
  193. BIN  web-app/js/yahoo/assets/menuarodwn9_dim_1.gif
  194. BIN  web-app/js/yahoo/assets/menuarodwn9_nrm_1.gif
  195. BIN  web-app/js/yahoo/assets/menuarorght9_dim_1.gif
  196. BIN  web-app/js/yahoo/assets/menuarorght9_hov_1.gif
  197. BIN  web-app/js/yahoo/assets/menuarorght9_nrm_1.gif
  198. BIN  web-app/js/yahoo/assets/tip16_1.gif
  199. BIN  web-app/js/yahoo/assets/tm.gif
  200. BIN  web-app/js/yahoo/assets/tmh.gif
  201. BIN  web-app/js/yahoo/assets/tn.gif
  202. BIN  web-app/js/yahoo/assets/tp.gif
  203. BIN  web-app/js/yahoo/assets/tph.gif
  204. +98 0 web-app/js/yahoo/assets/tree.css
  205. BIN  web-app/js/yahoo/assets/vline.gif
  206. BIN  web-app/js/yahoo/assets/warn16_1.gif
  207. +211 0 web-app/js/yahoo/calendar-min.js
  208. +72 0 web-app/js/yahoo/connection-min.js
  209. +265 0 web-app/js/yahoo/container-min.js
  210. +137 0 web-app/js/yahoo/container_core-min.js
  211. +1 0  web-app/js/yahoo/dom-min.js
  212. +1 0  web-app/js/yahoo/dragdrop-min.js
  213. +1 0  web-app/js/yahoo/event-min.js
  214. +1 0  web-app/js/yahoo/menu-min.js
  215. +1 0  web-app/js/yahoo/slider-min.js
  216. +1 0  web-app/js/yahoo/treeview-min.js
  217. +1 0  web-app/js/yahoo/yahoo-min.js
  218. +16 0 webtest/conf/webtest.properties
  219. +629 0 webtest/reports/WebTestResults.html
  220. +460 0 webtest/reports/WebTestResults.xml
  221. +5 0 webtest/reports/readme.txt
  222. +40 0 webtest/reports/response_1159829438560_invoke.html
  223. +44 0 webtest/reports/response_1159829441998_clickLink.html
  224. +79 0 webtest/reports/response_1159829446196_clickButton.html
  225. +55 0 webtest/reports/response_1159829447832_clickLink.html
  226. +79 0 webtest/reports/response_1159829449533_clickLink.html
  227. +59 0 webtest/reports/response_1159829452976_clickButton.html
  228. +79 0 webtest/reports/response_1159829455395_clickButton.html
  229. +55 0 webtest/reports/response_1159829457001_clickLink.html
  230. +79 0 webtest/reports/response_1159829458642_clickLink.html
  231. +44 0 webtest/reports/response_1159829461056_clickButton.html
  232. +63 0 webtest/tests/BookmarkWebTest.groovy
  233. +36 0 webtest/tests/TestSuite.groovy
66 .classpath
... ... @@ -0,0 +1,66 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<classpath>
  3 + <classpathentry kind="src" path="src/java"/>
  4 + <classpathentry kind="src" path="src/groovy"/>
  5 + <classpathentry kind="src" path="grails-app/conf"/>
  6 + <classpathentry kind="src" path="grails-app/controllers"/>
  7 + <classpathentry kind="src" path="grails-app/domain"/>
  8 + <classpathentry kind="src" path="grails-app/services"/>
  9 + <classpathentry kind="src" path="grails-app/taglib"/>
  10 + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
  11 + <classpathentry kind="var" path="GRAILS_HOME/lib/antlr-2.7.6rc1.jar"/>
  12 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-cli-1.0.jar"/>
  13 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-collections-3.0.jar"/>
  14 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-dbcp-1.2.1.jar"/>
  15 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-pool-1.2.jar"/>
  16 + <classpathentry kind="var" path="GRAILS_HOME/lib/dom4j-1.6.1.jar"/>
  17 + <classpathentry kind="var" path="GRAILS_HOME/lib/ehcache-1.1.jar"/>
  18 + <classpathentry kind="var" path="GRAILS_HOME/lib/ejb3-persistence.jar"/>
  19 + <classpathentry kind="var" path="GRAILS_HOME/lib/groovy-all-1.0.1-SNAPSHOT.jar"/>
  20 + <classpathentry sourcepath="/HIBERNATE_HOME/src" kind="var" path="GRAILS_HOME/lib/hibernate3.jar"/>
  21 + <classpathentry kind="var" path="GRAILS_HOME/lib/hibernate-annotations.jar"/>
  22 + <classpathentry kind="var" path="GRAILS_HOME/lib/jasper-compiler.jar"/>
  23 + <classpathentry kind="var" path="GRAILS_HOME/lib/jasper-runtime.jar"/>
  24 + <classpathentry kind="var" path="GRAILS_HOME/lib/jdbc2_0-stdext.jar"/>
  25 + <classpathentry kind="var" path="GRAILS_HOME/lib/jstl-2.3.jar"/>
  26 + <classpathentry kind="var" path="GRAILS_HOME/lib/jstl-2.4.jar"/>
  27 + <classpathentry kind="var" path="GRAILS_HOME/lib/jta.jar"/>
  28 + <classpathentry kind="var" path="GRAILS_HOME/lib/log4j-1.2.8.jar"/>
  29 + <classpathentry kind="var" path="GRAILS_HOME/lib/ognl-2.7.jar"/>
  30 + <classpathentry kind="var" path="GRAILS_HOME/lib/org.mortbay.jetty.jar"/>
  31 + <classpathentry kind="var" path="GRAILS_HOME/lib/quartz-1.5.2.jar"/>
  32 + <classpathentry kind="var" path="GRAILS_HOME/lib/sitemesh-2.2.1.jar"/>
  33 + <classpathentry kind="var" path="GRAILS_HOME/lib/spring-binding.jar"/>
  34 + <classpathentry kind="var" path="GRAILS_HOME/lib/spring-mock.jar"/>
  35 + <classpathentry kind="var" path="GRAILS_HOME/lib/springmodules-sandbox.jar"/>
  36 + <classpathentry kind="var" path="GRAILS_HOME/lib/spring-webflow.jar"/>
  37 + <classpathentry kind="var" path="GRAILS_HOME/lib/standard-2.3.jar"/>
  38 + <classpathentry kind="var" path="GRAILS_HOME/lib/standard-2.4.jar"/>
  39 + <classpathentry kind="var" path="GRAILS_HOME/lib/xml-apis.jar"/>
  40 + <classpathentry kind="var" path="GRAILS_HOME/ant/lib/ant.jar"/>
  41 + <classpathentry sourcepath="/SPRING_HOME/src" kind="var" path="GRAILS_HOME/lib/spring-1.2.8.jar"/>
  42 + <classpathentry kind="var" path="GRAILS_HOME/lib/servletapi-2.4.jar"/>
  43 + <classpathentry kind="var" path="GRAILS_HOME/lib/oro-2.0.8.jar"/>
  44 + <classpathentry kind="var" path="GRAILS_HOME/lib/junit-3.8.jar"/>
  45 + <classpathentry kind="var" path="GRAILS_HOME/lib/hsqldb-1.8.0.5.jar"/>
  46 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-validator-1.3.0.jar"/>
  47 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-logging-1.1.jar"/>
  48 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-lang-2.1.jar"/>
  49 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-fileupload-1.1.1.jar"/>
  50 + <classpathentry kind="var" path="GRAILS_HOME/lib/commons-el-1.0.jar"/>
  51 + <classpathentry kind="var" path="GRAILS_HOME/lib/cglib-nodep-2.1_3.jar"/>
  52 + <classpathentry kind="var" path="GRAILS_HOME/lib/bsf-2.3.0.jar"/>
  53 + <classpathentry sourcepath="/GRAILS_HOME/src/web" kind="var" path="GRAILS_HOME/dist/grails-0.3-SNAPSHOT.jar"/>
  54 + <classpathentry kind="lib" path="lib/mail.jar"/>
  55 + <classpathentry kind="lib" path="lib/commons-httpclient-3.0.1.jar"/>
  56 + <classpathentry kind="lib" path="lib/commons-email-1.0.jar"/>
  57 + <classpathentry kind="lib" path="lib/commons-codec-1.3.jar"/>
  58 + <classpathentry kind="lib" path="lib/activation.jar"/>
  59 + <classpathentry kind="var" path="GRAILS_HOME/lib/jsp-api-2.0.jar"/>
  60 + <classpathentry kind="lib" path="lib/acegi-security-tiger-1.0.1.jar"/>
  61 + <classpathentry kind="lib" path="lib/acegi-security-jetty-1.0.1.jar"/>
  62 + <classpathentry kind="lib" path="lib/acegi-security-1.0.1.jar"/>
  63 + <classpathentry kind="lib" path="lib/xstream-1.2.jar"/>
  64 + <classpathentry kind="lib" path="lib/xfire-all-1.2.2.jar"/>
  65 + <classpathentry kind="output" path="bin"/>
  66 +</classpath>
23 .project
... ... @@ -0,0 +1,23 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<projectDescription>
  3 + <name>bookmarks</name>
  4 + <comment></comment>
  5 + <projects>
  6 + </projects>
  7 + <buildSpec>
  8 + <buildCommand>
  9 + <name>org.eclipse.jdt.core.javabuilder</name>
  10 + <arguments>
  11 + </arguments>
  12 + </buildCommand>
  13 + <buildCommand>
  14 + <name>org.codehaus.groovy.eclipse.groovyBuilder</name>
  15 + <arguments>
  16 + </arguments>
  17 + </buildCommand>
  18 + </buildSpec>
  19 + <natures>
  20 + <nature>org.eclipse.jdt.core.javanature</nature>
  21 + <nature>org.codehaus.groovy.eclipse.groovyNature</nature>
  22 + </natures>
  23 +</projectDescription>
3  .settings/org.codehaus.groovy.eclipse.preferences.prefs
... ... @@ -0,0 +1,3 @@
  1 +#Wed Oct 04 07:57:39 BST 2006
  2 +eclipse.preferences.version=1
  3 +groovy.compiler.output.path=bin
64 .settings/org.eclipse.jdt.core.prefs
... ... @@ -0,0 +1,64 @@
  1 +#Wed Oct 04 15:15:57 BST 2006
  2 +eclipse.preferences.version=1
  3 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean
  4 +org.eclipse.jdt.core.builder.duplicateResourceTask=warning
  5 +org.eclipse.jdt.core.builder.invalidClasspath=abort
  6 +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
  7 +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.DS_Store,tmp
  8 +org.eclipse.jdt.core.circularClasspath=error
  9 +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
  10 +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
  11 +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
  12 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
  13 +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
  14 +org.eclipse.jdt.core.compiler.problem.deprecation=warning
  15 +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
  16 +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
  17 +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
  18 +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
  19 +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
  20 +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
  21 +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
  22 +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
  23 +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
  24 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
  25 +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
  26 +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
  27 +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
  28 +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
  29 +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
  30 +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
  31 +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
  32 +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
  33 +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
  34 +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
  35 +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
  36 +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
  37 +org.eclipse.jdt.core.compiler.problem.nullReference=ignore
  38 +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
  39 +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
  40 +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
  41 +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
  42 +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
  43 +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
  44 +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
  45 +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
  46 +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
  47 +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
  48 +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
  49 +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
  50 +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
  51 +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
  52 +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
  53 +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
  54 +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
  55 +org.eclipse.jdt.core.compiler.problem.unusedImport=warning
  56 +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
  57 +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
  58 +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
  59 +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
  60 +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
  61 +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
  62 +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
  63 +org.eclipse.jdt.core.incompatibleJDKLevel=ignore
  64 +org.eclipse.jdt.core.incompleteClasspath=error
21 README.txt
... ... @@ -0,0 +1,21 @@
  1 +Bookmarks Sample Application
  2 +----------------------------
  3 +
  4 +This is the sample application from the book "The Defintive Guide to Grails" by
  5 +Graeme Rocher (see http://www.apress.com/book/bookDisplay.html?bID=10205)
  6 +
  7 +It shows integration with Java frameworks and services like Xfire, Acegi and Hibernate.
  8 +It also includes del.icio.us integration.
  9 +
  10 +To get started type
  11 +
  12 +grails run-app
  13 +
  14 +And navigate to:
  15 +
  16 +http://localhost:8080/bookmarks
  17 +
  18 +Register with the same user details that you registered with del.icio.us for (if you have an account).
  19 +Then login and start adding bookmarks, and searching del.icio.us.
  20 +
  21 +Enjoy!
20 bookmarks.launch
... ... @@ -0,0 +1,20 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
  3 +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="grails.util.GrailsMain"/>
  4 +<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
  5 +<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
  6 +<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot; javaProject=&quot;bookmarks&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
  7 +<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/bookmarks/web-app/WEB-INF&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
  8 +<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#13;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;bookmarks&quot;/&gt;&#13;&#10;&lt;/runtimeClasspathEntry&gt;&#13;&#10;"/>
  9 +</listAttribute>
  10 +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
  11 +<listEntry value="4"/>
  12 +</listAttribute>
  13 +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="bookmarks"/>
  14 +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dbase.dir=${project_loc} -Dserver.port=8080"/>
  15 +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
  16 +<listEntry value="/bookmarks"/>
  17 +</listAttribute>
  18 +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
  19 +</launchConfiguration>
  20 +
8 grails-app/conf/ApplicationBootStrap.groovy
... ... @@ -0,0 +1,8 @@
  1 +class ApplicationBootStrap {
  2 +
  3 + def init = { servletContext ->
  4 + System.setProperty("javax.xml.transform.TransformerFactory","org.apache.xalan.processor.TransformerFactoryImpl")
  5 + }
  6 + def destroy = {
  7 + }
  8 +}
12 grails-app/conf/ApplicationDataSource.groovy
... ... @@ -0,0 +1,12 @@
  1 +import org.codehaus.groovy.grails.orm.hibernate.cfg.*
  2 +
  3 +class ApplicationDataSource {
  4 + def configClass = GrailsAnnotationConfiguration.class
  5 +
  6 + boolean pooling = true
  7 + String dbCreate = "create-drop" // one of 'create', 'create-drop','update'
  8 + String url = "jdbc:hsqldb:mem:testDB"
  9 + String driverClassName = "org.hsqldb.jdbcDriver"
  10 + String username = "sa"
  11 + String password = ""
  12 +}
9 grails-app/conf/BookmarksUrlMappings.groovy
... ... @@ -0,0 +1,9 @@
  1 +class BookmarksUrlMappings {
  2 + static mappings = {
  3 + "/$controller/$action?/$id?"{
  4 + constraints {
  5 + // apply constraints here
  6 + }
  7 + }
  8 + }
  9 +}
10 grails-app/conf/DevelopmentDataSource.groovy
... ... @@ -0,0 +1,10 @@
  1 +import org.codehaus.groovy.grails.orm.hibernate.cfg.*
  2 +class DevelopmentDataSource {
  3 + def configClass = GrailsAnnotationConfiguration.class
  4 + boolean pooling = true
  5 + String dbCreate = "create-drop" // one of 'create', 'create-drop','update'
  6 + String url = "jdbc:hsqldb:mem:devDB"
  7 + String driverClassName = "org.hsqldb.jdbcDriver"
  8 + String username = "sa"
  9 + String password = ""
  10 +}
10 grails-app/conf/ProductionDataSource.groovy
... ... @@ -0,0 +1,10 @@
  1 +import org.codehaus.groovy.grails.orm.hibernate.cfg.*
  2 +class ProductionDataSource {
  3 + def configClass = GrailsAnnotationConfiguration.class
  4 + boolean pooling = true
  5 + String dbCreate = "update" // one of 'create', 'create-drop','update'
  6 + String url = "jdbc:hsqldb:file:prodDb"
  7 + String driverClassName = "org.hsqldb.jdbcDriver"
  8 + String username = "sa"
  9 + String password = ""
  10 +}
10 grails-app/conf/TestDataSource.groovy
... ... @@ -0,0 +1,10 @@
  1 +import org.codehaus.groovy.grails.orm.hibernate.cfg.*
  2 +class TestDataSource {
  3 + def configClass = GrailsAnnotationConfiguration.class
  4 + boolean pooling = true
  5 + String dbCreate = "update" // one of 'create', 'create-drop','update'
  6 + String url = "jdbc:hsqldb:mem:testDB"
  7 + String driverClassName = "org.hsqldb.jdbcDriver"
  8 + String username = "sa"
  9 + String password = ""
  10 +}
37 grails-app/conf/log4j.development.properties
... ... @@ -0,0 +1,37 @@
  1 +log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  2 +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  3 +# Enable logging for everything. Rarely useful
  4 +log4j.rootLogger=error, stdout
  5 +
  6 +
  7 +# Enable this logger to log Hibernate output
  8 +# handy to see its database interaction activity
  9 +#log4j.logger.org.hibernate=debug,stdout
  10 +#log4j.additivity.org.hibernate=false
  11 +
  12 +# Enable this logger to see what Spring does, occasionally useful
  13 +#log4j.logger.org.springframework=info,stdout
  14 +#log4j.additivity.org.springframework=false
  15 +
  16 +# This logger covers all of Grails' internals
  17 +# Enable to see whats going on underneath.
  18 +log4j.logger.org.codehaus.groovy.grails=info,stdout
  19 +log4j.additivity.org.codehaus.groovy.grails=false
  20 +
  21 +# This logger is useful if you just want to see what Grails
  22 +# configures with Spring at runtime. Setting to debug will show
  23 +# each bean that is configured
  24 +log4j.logger.org.codehaus.groovy.grails.commons.spring=info,stdout
  25 +log4j.additivity.org.codehaus.groovy.grails.commons.spring=false
  26 +
  27 +# Interesting Logger to see what some of the Grails factory beans are doing
  28 +log4j.logger.org.codehaus.groovy.grails.beans.factory=info,stdout
  29 +log4j.additivity.org.codehaus.groovy.grails.beans.factory=false
  30 +
  31 +# This logger outputs what Grails is doing dynamically under the covers
  32 +log4j.logger.org.codehaus.groovy.grails.commons.metaclass=info,stdout
  33 +log4j.additivity.org.codehaus.groovy.grails.commons.metaclass=false
  34 +
  35 +# This logger is for Grails' public APIs within the grails. package
  36 +log4j.logger.grails=info,stdout
  37 +log4j.additivity.grails=false
37 grails-app/conf/log4j.production.properties
... ... @@ -0,0 +1,37 @@
  1 +log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  2 +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  3 +# Enable logging for everything. Rarely useful
  4 +log4j.rootLogger=error, stdout
  5 +
  6 +
  7 +# Enable this logger to log Hibernate output
  8 +# handy to see its database interaction activity
  9 +#log4j.logger.org.hibernate=debug,stdout
  10 +#log4j.additivity.org.hibernate=false
  11 +
  12 +# Enable this logger to see what Spring does, occasionally useful
  13 +#log4j.logger.org.springframework=info,stdout
  14 +#log4j.additivity.org.springframework=false
  15 +
  16 +# This logger covers all of Grails' internals
  17 +# Enable to see whats going on underneath.
  18 +log4j.logger.org.codehaus.groovy.grails=info,stdout
  19 +log4j.additivity.org.codehaus.groovy.grails=false
  20 +
  21 +# This logger is useful if you just want to see what Grails
  22 +# configures with Spring at runtime. Setting to debug will show
  23 +# each bean that is configured
  24 +log4j.logger.org.codehaus.groovy.grails.commons.spring=info,stdout
  25 +log4j.additivity.org.codehaus.groovy.grails.commons.spring=false
  26 +
  27 +# Interesting Logger to see what some of the Grails factory beans are doing
  28 +log4j.logger.org.codehaus.groovy.grails.beans.factory=info,stdout
  29 +log4j.additivity.org.codehaus.groovy.grails.beans.factory=false
  30 +
  31 +# This logger outputs what Grails is doing dynamically under the covers
  32 +log4j.logger.org.codehaus.groovy.grails.commons.metaclass=info,stdout
  33 +log4j.additivity.org.codehaus.groovy.grails.commons.metaclass=false
  34 +
  35 +# This logger is for Grails' public APIs within the grails. package
  36 +log4j.logger.grails=info,stdout
  37 +log4j.additivity.grails=false
37 grails-app/conf/log4j.test.properties
... ... @@ -0,0 +1,37 @@
  1 +log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  2 +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  3 +# Enable logging for everything. Rarely useful
  4 +log4j.rootLogger=error, stdout
  5 +
  6 +
  7 +# Enable this logger to log Hibernate output
  8 +# handy to see its database interaction activity
  9 +#log4j.logger.org.hibernate=debug,stdout
  10 +#log4j.additivity.org.hibernate=false
  11 +
  12 +# Enable this logger to see what Spring does, occasionally useful
  13 +#log4j.logger.org.springframework=info,stdout
  14 +#log4j.additivity.org.springframework=false
  15 +
  16 +# This logger covers all of Grails' internals
  17 +# Enable to see whats going on underneath.
  18 +log4j.logger.org.codehaus.groovy.grails=info,stdout
  19 +log4j.additivity.org.codehaus.groovy.grails=false
  20 +
  21 +# This logger is useful if you just want to see what Grails
  22 +# configures with Spring at runtime. Setting to debug will show
  23 +# each bean that is configured
  24 +log4j.logger.org.codehaus.groovy.grails.commons.spring=info,stdout
  25 +log4j.additivity.org.codehaus.groovy.grails.commons.spring=false
  26 +
  27 +# Interesting Logger to see what some of the Grails factory beans are doing
  28 +log4j.logger.org.codehaus.groovy.grails.beans.factory=info,stdout
  29 +log4j.additivity.org.codehaus.groovy.grails.beans.factory=false
  30 +
  31 +# This logger outputs what Grails is doing dynamically under the covers
  32 +log4j.logger.org.codehaus.groovy.grails.commons.metaclass=info,stdout
  33 +log4j.additivity.org.codehaus.groovy.grails.commons.metaclass=false
  34 +
  35 +# This logger is for Grails' public APIs within the grails. package
  36 +log4j.logger.grails=info,stdout
  37 +log4j.additivity.grails=false
185 grails-app/controllers/BookmarkController.groovy
... ... @@ -0,0 +1,185 @@
  1 +import org.grails.bookmarks.*
  2 +
  3 +
  4 +class BookmarkController extends SecureController {
  5 +
  6 + def scaffold = Bookmark
  7 +
  8 + DeliciousService deliciousService
  9 +
  10 + //Map params = [:]
  11 + //Map flash = [:]
  12 + //Map session = [:]
  13 +
  14 + def create = {
  15 + def b = new Bookmark()
  16 + b.properties = params
  17 + def suggestions = b.url ? getSuggestions(b.url, b) : []
  18 + return [bookmark:b, suggestions:suggestions]
  19 + }
  20 + def preview = {
  21 + def b = Bookmark.get(params.id)
  22 + render {
  23 + iframe(src:b.url,width:640,height:480,border:0, 'iframes not supported by browse')
  24 + }
  25 + }
  26 + def edit = {
  27 + def b = Bookmark.get(params.id)
  28 + if(b) {
  29 + return [bookmark:b, suggestions: getSuggestions(b.url,b) ]
  30 + }
  31 + else {
  32 + render "bookmark not found for id ${params.id}"
  33 + }
  34 + }
  35 +
  36 + def delete = {
  37 + def b = Bookmark.get(params.id)
  38 + if(b) {
  39 + b.delete()
  40 + flash.message = "Bookmark ${b.id} deleted."
  41 + redirect(action:list)
  42 + }
  43 + else {
  44 + render "Bookmark not found"
  45 + }
  46 + }
  47 +
  48 + def update = {
  49 + def b = Bookmark.get(params.id)
  50 + if(b) {
  51 + b.properties = params
  52 + addTags(b)
  53 + if(b.save()) {
  54 + render(template:'bookmark', model:[bookmark:b])
  55 + }
  56 + else {
  57 + render(view:'edit', model:[bookmark:b])
  58 + }
  59 + }
  60 + else {
  61 + render "Bookmark not found"
  62 + }
  63 + }
  64 + def save = {
  65 + def b = new Bookmark()
  66 + b.properties = params
  67 + b.user = User.get(session.user.id)
  68 +
  69 + if(b.save()) {
  70 + if(params.tagTokens) {
  71 + addTags(b)
  72 + b.save()
  73 + }
  74 + redirect(action:list,id:b.id)
  75 + }
  76 + else {
  77 + render(view:'create',model:[bookmark:b])
  78 + }
  79 + }
  80 +
  81 + private addTags(Bookmark b) {
  82 + def tags = params.tagTokens?.trim()
  83 + if(tags?.indexOf(' ')) {
  84 + tags = tags.split(' ').toList()
  85 + tags = tags.unique()
  86 + tags.each {
  87 + Tag t = Tag.findByName(it)
  88 + if(!t)t = new Tag(name:it).save()
  89 +
  90 + b.addTagReference(new TagReference(bookmark:b, tag:t, user:b.user))
  91 + }
  92 + }
  93 + else {
  94 + Tag t = Tag.findByName(tags)
  95 + if(!t)t = new Tag(name:tags).save()
  96 +
  97 + b.addTagReference( new TagReference(bookmark:b, tag:t, user:b.user) )
  98 + }
  99 + }
  100 +
  101 + def list = {
  102 + if(!params.max)params.max=10
  103 + def fromDelicious
  104 + try {
  105 + fromDelicious = deliciousService?.findRecent(session.user)
  106 + }
  107 + catch(Exception e) {
  108 + println e.message
  109 + e.printStackTrace(System.out)
  110 + //log.error("Error communication with del.icio.us service: ${e.message}",e)
  111 + }
  112 +
  113 + [bookmarkList: Bookmark.findAllByUser(User.get(session['user'].id), params ), deliciousList: fromDelicious ]
  114 + }
  115 +
  116 + def search = {
  117 + def criteria = Bookmark.createCriteria()
  118 + def t = Tag.findByName(params.q)
  119 + def bookmarks = criteria.list {
  120 + or {
  121 + ilike('title',"%${params.q}%".toString())
  122 + ilike('notes',"%${params.q}%".toString())
  123 + if(t) {
  124 + tags {
  125 + eq('tag', t)
  126 + }
  127 + }
  128 + }
  129 + }
  130 + def fromDelicious
  131 + try {
  132 + fromDelicious = deliciousService?.findAllForTag(params.q,session.user)
  133 + }
  134 + catch(Exception e) {
  135 + println e.message
  136 + e.printStackTrace(System.out)
  137 + //log.error("Error communication with del.icio.us service: ${e.message}",e)
  138 + }
  139 +
  140 + render(view:'list',model:[ bookmarkList:bookmarks.adaptee.unique(),
  141 + deliciousResults:fromDelicious] )
  142 + }
  143 +
  144 + def updateNotes = {
  145 + def b = Bookmark.get(params.id)
  146 + if(b) {
  147 + b.notes = params.notes
  148 + b.save()
  149 + }
  150 + render( params.notes )
  151 + }
  152 +
  153 + def suggestTag = {
  154 + if(params.value?.trim()) {
  155 + if(!params.value?.startsWith("http://")) params.value = "http://${params.value}"
  156 +
  157 + def bookmark = params.id ? Bookmark.get(params.id) : null
  158 + try {
  159 + def url = bookmark ? bookmark.url : new URI(params.value)
  160 + def tags = getSuggestions(url,bookmark)
  161 +
  162 + render(template:'suggest',model:[tags:tags,bookmark:bookmark])
  163 + }
  164 + catch(Exception e) {
  165 + log.debug(e.message , e)
  166 + render ""
  167 + }
  168 + }
  169 + else {
  170 + render ""
  171 + }
  172 + }
  173 + private getSuggestions(url,bookmark) {
  174 + def tagRefs = TagReference.findAll('from TagReference where bookmark.url = ?', [url])
  175 + def tags
  176 + if(bookmark) {
  177 + tags = tagRefs.findAll { bookmark.tags?.contains(it.tag) }.tag.unique()
  178 + }
  179 + else {
  180 + tags = tagRefs.tag.unique()
  181 + }
  182 + return tags
  183 + }
  184 +}
  185 +
11 grails-app/controllers/SecureController.groovy
... ... @@ -0,0 +1,11 @@
  1 +import org.grails.bookmarks.*
  2 +
  3 +abstract class SecureController {
  4 + def beforeInterceptor = {
  5 + if(!session.user) {
  6 + session.user = User.findByLogin(request.remoteUser)
  7 + }
  8 + }
  9 +
  10 +}
  11 +
19 grails-app/controllers/SubscriptionController.groovy
... ... @@ -0,0 +1,19 @@
  1 +import org.grails.bookmarks.*
  2 +
  3 +class SubscriptionController extends SecureController {
  4 + def list = {
  5 + [ subscriptionList: Subscription.findAllByUser( session.user,params ) ]
  6 + }
  7 + def delete = {
  8 + def subscription = Subscription.get( params.id )
  9 + subscription?.delete()
  10 + render(template:"subscription", var:"subscription",collection:Subscription.findAllByUser( session.user ))
  11 + }
  12 + def save = {
  13 + def t = Tag.findByName(params.tagName)
  14 + if(!t)t= new Tag(name:params.tagName).save()
  15 + if(!Subscription.findByUserAndTag(session.user,t))
  16 + new Subscription(user:session.user, tag:t).save()
  17 + render(template:"subscription", var:"subscription",collection:Subscription.findAllByUser( session.user ))
  18 + }
  19 +}
73 grails-app/controllers/TagController.groovy
... ... @@ -0,0 +1,73 @@
  1 +import org.grails.bookmarks.*
  2 +
  3 +class TagController extends SecureController {
  4 + def index = { redirect(action:list,params:params) }
  5 +
  6 + def list = {
  7 + [ tagList: Tag.list( params ) ]
  8 + }
  9 +
  10 + def show = {
  11 + [ tag : Tag.get( params.id ) ]
  12 + }
  13 +
  14 + def delete = {
  15 + def tag = Tag.get( params.id )
  16 + if(tag) {
  17 + tag.delete()
  18 + flash.message = "Tag ${params.id} deleted."
  19 + redirect(action:list)
  20 + }
  21 + else {
  22 + flash.message = "Tag not found with id ${params.id}"
  23 + redirect(action:list)
  24 + }
  25 + }
  26 +
  27 + def edit = {
  28 + def tag = Tag.get( params.id )
  29 +
  30 + if(!tag) {
  31 + flash.message = "Tag not found with id ${params.id}"
  32 + redirect(action:list)
  33 + }
  34 + else {
  35 + return [ tag : tag ]
  36 + }
  37 + }
  38 +
  39 + def update = {
  40 + def tag = Tag.get( params.id )
  41 + if(tag) {
  42 + tag.properties = params
  43 + if(tag.save()) {
  44 + redirect(action:show,id:tag.id)
  45 + }
  46 + else {
  47 + render(view:'edit',model:[tag:tag])
  48 + }
  49 + }
  50 + else {
  51 + flash.message = "Tag not found with id ${params.id}"
  52 + redirect(action:edit,id:params.id)
  53 + }
  54 + }
  55 +
  56 + def create = {
  57 + def tag = new Tag()
  58 + tag.properties = params
  59 + return ['tag':tag]
  60 + }
  61 +
  62 + def save = {
  63 + def tag = new Tag()
  64 + tag.properties = params
  65 + if(tag.save()) {
  66 + redirect(action:show,id:tag.id)
  67 + }
  68 + else {
  69 + render(view:'create',model:[tag:tag])
  70 + }
  71 + }
  72 +
  73 +}
36 grails-app/controllers/UserController.groovy
... ... @@ -0,0 +1,36 @@
  1 +import org.grails.bookmarks.*
  2 +
  3 +class UserController {
  4 +
  5 + def accessDenied = {
  6 + flash.message = "Your account does not have permission to view this page"
  7 + redirect(controller:"bookmark")
  8 + }
  9 +
  10 + def login = {
  11 + if(session.user) {
  12 + redirect(controller:'bookmark')
  13 + }
  14 + }
  15 +
  16 + def register = {}
  17 +
  18 + def handleRegistration = {
  19 + def user = new User()
  20 + if(params.password != params.confirm) {
  21 + flash.message = "The two passwords you entered dont match!"
  22 + redirect(action:register)
  23 + }
  24 + else {
  25 + user.properties = params
  26 + if(user.save()) {
  27 + redirect(controller:'bookmark')
  28 + }
  29 + else {
  30 + flash.user = user
  31 + redirect(action:register)
  32 + }
  33 + }
  34 + }
  35 +}
  36 +
20 grails-app/i18n/messages.properties
... ... @@ -0,0 +1,20 @@
  1 +default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}]
  2 +default.invalid.url.message=Property [{0}] of class [{1}] with value [{2}] is not a valid URL
  3 +default.invalid.creditCard.message=Property [{0}] of class [{1}] with value [{2}] is not a valid credit card number
  4 +default.invalid.email.message=Property [{0}] of class [{1}] with value [{2}] is not a valid e-mail address.
  5 +default.invalid.message=Property [{0}] of class [{1}] is not a valid [{2}].
  6 +default.invalid.range.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid range from [{3}] to [{4}]
  7 +default.invalid.size.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
  8 +default.invalid.length.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid length range from [{3}] to [{4}]
  9 +default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}]
  10 +default.invalid.max.message=Property [{0}] of class [{1}] with value [{2}] exceeds maxim value [{3}]
  11 +default.invalid.max.length.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maxim length of [{3}]
  12 +default.invalid.min.length.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum length of [{3}]
  13 +default.invalid.max.size.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maxim size of [{3}]
  14 +default.invalid.min.size.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum size of [{3}]
  15 +default.not.inlist.message=Property [{0}] of class [{1}] with value [{2}] is not contained within the list [{3}]
  16 +default.blank.message=Property [{0}] of class [{1}] cannot be blank
  17 +default.not.equal.message=Property [{0}] of class [{1}] with value [{2}] cannot equal [{3}]
  18 +default.null.message=Property [{0}] of class [{1}] cannot be null
  19 +default.not.unique.message=Property [{0}] of class [{1}] with value [{2}] must be unique
  20 +default.not.editable.message=Property [{0}] of class [{1}] with value [{2}] cannot be changed from [{3}]
60 grails-app/jobs/SubscriptionJob.groovy
... ... @@ -0,0 +1,60 @@
  1 +import org.grails.bookmarks.*
  2 +
  3 +class SubscriptionJob {
  4 + static final EMAIL_SERVER = "localhost"
  5 +
  6 + def cronExpression = "0 0 6 ? * FRI"
  7 +
  8 + def execute() {
  9 + def criteria = Subscription.createCriteria()
  10 + def subscribedUsers = criteria.list {
  11 + projections {
  12 + distinct("user")
  13 + }
  14 + }
  15 + subscribedUsers.each { user ->
  16 + def subscribedTags = Subscription.findAllByUser(user).tag
  17 +
  18 + criteria = Bookmark.createCriteria()
  19 + def now = new Date()
  20 + def bookmarks = criteria.list {
  21 + notEqual("user", user)
  22 + between("dateCreated",now-7,now)
  23 + tags {
  24 + inList("tag", subscribedTags)
  25 + }
  26 + }
  27 + if(bookmarks) {
  28 + sendMail(user,"Latest Bookmarks") {
  29 + p("Hi $user!")
  30 + p("Below are the most recent bookmarks for the tags you're interested in!")
  31 + for(b in bookmarks) {
  32 + p {
  33 + a(href:b.url, b.title)
  34 + }
  35 + }
  36 + p("Enjoy the bookmarks!")
  37 + p("The Bookmarks Team")
  38 + }
  39 + }
  40 + }
  41 + }
  42 +
  43 + def sendMail(User to,String subject,Closure bodyContent) {
  44 + def sw = new StringWriter()
  45 + def mkp = new groovy.xml.MarkupBuilder(new PrintWriter(sw))
  46 + mkp.html {
  47 + body(bodyContent)
  48 + }
  49 +
  50 + def email = new org.apache.commons.mail.HtmlEmail(
  51 + hostName: EMAIL_SERVER,
  52 + subject : subject,
  53 + htmlMsg : sw.toString()
  54 + )
  55 + email.setFrom("noreply@bookmarks.grail.org" , "Grails Bookmarks Application")
  56 + email.addTo(to.email, "$to")
  57 + println("Sending email: $sw")
  58 + email.send()
  59 + }
  60 +}
34 grails-app/services/BookmarkService.groovy
... ... @@ -0,0 +1,34 @@
  1 +import org.grails.bookmarks.Bookmark
  2 +import org.grails.bookmarks.User
  3 +import org.grails.bookmarks.Tag
  4 +
  5 +class BookmarkService implements org.grails.bookmarks.IBookmarkService {
  6 +
  7 + boolean transactional = false
  8 +
  9 + List findAllForTag(String tag,User user) {
  10 + def t = tag ? Tag.findByName(tag) : null
  11 + if(user) user = User.findByLogin(user.login)
  12 + List bookmarks = Collections.EMPTY_LIST
  13 + if(t && user) {
  14 + def criteria = Bookmark.createCriteria()
  15 + bookmarks = criteria.list {
  16 + eq('user',user)
  17 + tags {
  18 + eq('tag', t)
  19 + }
  20 + }
  21 + }
  22 + return bookmarks
  23 + }
  24 +
  25 + List findRecent(User user) {
  26 + def now = new Date()
  27 + if(user) user = User.findByLogin(user.login)
  28 + if(user) {
  29 + return Bookmark
  30 + .findAllByUserAndDateCreatedBetween(user,now-7,now)
  31 + }
  32 + }
  33 +}
  34 +
53 grails-app/services/DeliciousService.groovy
... ... @@ -0,0 +1,53 @@
  1 +import org.grails.bookmarks.*
  2 +import org.apache.commons.httpclient.*
  3 +import org.apache.commons.httpclient.auth.AuthScope
  4 +import org.apache.commons.httpclient.methods.GetMethod
  5 +
  6 +class DeliciousService implements IBookmarkService {
  7 +
  8 + static final API = "https://api.del.icio.us/v1"
  9 +
  10 + boolean transactional = false
  11 +
  12 + List findAllForTag(String tag,User user) {
  13 + return withDelicious(name:"posts/all",params:[tag:tag],user:user) { xml ->
  14 + def bookmarks = []
  15 + xml.post.each {
  16 + bookmarks << new Bookmark(title:"${it.@description}",url:"${it.@href}")
  17 + }
  18 + return bookmarks
  19 + }
  20 + }
  21 +
  22 + List findRecent(User user) {
  23 + return withDelicious(name:"posts/recent",params:[count:5],user:user) { xml ->
  24 + def bookmarks = []
  25 + xml.post.each {
  26 + bookmarks << new Bookmark(title:"${it.@description}",url:"${it.@href}")
  27 + }
  28 + return bookmarks
  29 + }
  30 + }
  31 +
  32 + private withDelicious(args,callable) {
  33 + if(!args.user) throw new IllegalArgumentException("Property [user] is required and cannot be null")
  34 +
  35 +
  36 + def url = "${API}/${args.name}?"
  37 + args.params?.each {k,v->
  38 + url+="&$k=$v"
  39 + }
  40 +
  41 + def client = new HttpClient()
  42 + client
  43 + .state
  44 + .setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(args.user.login, args.user.password))
  45 +
  46 + def get = new GetMethod(url)
  47 + get.doAuthentication = true
  48 + client.executeMethod(get)
  49 +
  50 + callable( new XmlSlurper().parse(get.responseBodyAsStream) )
  51 + }
  52 +}
  53 +
30 grails-app/taglib/BookmarkTagLib.groovy
... ... @@ -0,0 +1,30 @@
  1 +class BookmarkTagLib {
  2 + Writer out
  3 +
  4 + def repeat = { attrs,body ->
  5 + attrs.times?.toInteger().times {
  6 + out << body(it)
  7 + }
  8 + }
  9 + def editInPlace = { attrs, body ->
  10 + def rows = attrs.rows ? attrs.rows : 0;
  11 + def cols = attrs.cols ? attrs.cols : 0;
  12 + def id = attrs.remove('id')
  13 + out << "<span id='${id}'>"
  14 + out << body()
  15 + out << "</span>"
  16 + out << "<script type='text/javascript'>"
  17 + out << "new Ajax.InPlaceEditor('${id}', '"
  18 + out << createLink(attrs)
  19 + out << "',{"
  20 + if(rows)
  21 + out << "rows:${rows},"
  22 + if(cols)
  23 + out << "cols:${cols},"
  24 + if(attrs.paramName) {
  25 + out << "callback: function(form, value) { return '${attrs.paramName}=' + escape(value) }"
  26 + }
  27 + out << "});"
  28 + out << "</script>"
  29 + }
  30 +}
25 grails-app/views/bookmark/_bookmark.gsp
... ... @@ -0,0 +1,25 @@
  1 +<div id="bookmark${bookmark.id}">
  2 + <div id="link${bookmark.id}">
  3 + <a href="${bookmark.url}">${bookmark.title}</a>
  4 + <g:if test="${bookmark.id}"> -
  5 + <g:remoteLink onComplete="Effect.BlindDown('bookmark${bookmark.id}');" action="edit" id="${bookmark.id}" update="bookmark${bookmark.id}">edit</g:remoteLink> |
  6 + <g:link action="delete" id="${bookmark.id}"
  7 + onclick="return confirm('Are you sure you want to delete this bookmark?')">delete</g:link> |
  8 + <a href="#" onmouseover="${remoteFunction(action:'preview',
  9 + id:bookmark.id,
  10 + update:'preview' + bookmark.id,
  11 + onComplete:'Effect.Appear(preview'+bookmark.id+')')};"
  12 + onmouseout="Effect.Fade('preview${bookmark.id}');">preview</a>
  13 + </g:if>
  14 + </div>
  15 + <div id="notes">
  16 + <g:editInPlace id="notes${bookmark.id}"
  17 + url="[action:'updateNotes',id:bookmark.id]"
  18 + rows="5"
  19 + cols= "10"
  20 + paramName="notes">${bookmark.notes}</g:editInPlace>
  21 +
  22 + </div>
  23 + <div id="preview${bookmark.id}">
  24 + </div>
  25 +</div>
16 grails-app/views/bookmark/_editor.gsp
... ... @@ -0,0 +1,16 @@
  1 +<div id="editor">
  2 + <p>Title: <input type="text" name="title" value="${bookmark?.title}"/></p>
  3 + <p>URL: <g:remoteField action="suggestTag" update="suggestions" name="url" value="${bookmark?.url}"/></p>
  4 + <p>Notes:</p>
  5 + <p><textarea name="notes" col="1" row="1">${bookmark?.notes}</textarea></p>
  6 + <p>Tags:</p>
  7 + <p><input type="text" name="tagTokens" id="tags${bookmark?.id}" /></p>
  8 +
  9 + <div id="suggestions${bookmark?.id}">
  10 + <g:each in="${suggestions?}">
  11 + <span class="suggestion">
  12 + <a href="#" onclick="$('tags${bookmark.id}.value += this.value+" "');this.style.display='none';">${it}</a>
  13 + </span>
  14 + </g:each>
  15 + </div>
  16 +</div>
7 grails-app/views/bookmark/_suggest.gsp
... ... @@ -0,0 +1,7 @@
  1 +<g:if test="${tags}"><h3>Suggestions:</h3></g:if>
  2 +<g:each var="t" in="${tags?}">
  3 + <span id="${t.id}" class="suggestion">
  4 + <a href="javascript:void(0);"
  5 + onclick="$('tags${bookmark?.id ? bookmark.id : ''}').value+=' '+this.innerHTML;this.style.display='none';">${t}</a>
  6 + </span>
  7 +</g:each>
37 grails-app/views/bookmark/create.gsp
... ... @@ -0,0 +1,37 @@
  1 +