diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..c4f73e690c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/.idea/* +/target/* +/build.properties +/build.log +/tmp/* \ No newline at end of file diff --git a/build.properties b/build.properties new file mode 100644 index 0000000000..ac279f753a --- /dev/null +++ b/build.properties @@ -0,0 +1,213 @@ +# This is the properties-file for building imCMS with ant. +# You just have to fill in the blanks. +# You shouldn't change any defaults unless you know what you are doing. + +# Database schema version. +db-schema-version = 4.17 + +# Denies multiple login for same user. To enable this option change property value to true. +deny-multiple-user-login = false + +#Server host +server-name = http://localhost:8080 + +# Database parameters + +db-host = localhost +db-name = imcmsrb4 +db-user = root +db-pass = root +db-maxconnections = 20 + +# For MSSQL +#db-target = mssql +#db-port = 1433 +#db-driver = net.sourceforge.jtds.jdbc.Driver +#db-url-without-db-name = jdbc:jtds:sqlserver://${db-host}:${db-port}/;AppName=imCMS +#db-url = ${db-url-without-db-name};DatabaseName=${db-name} + +# For MySQL +db-target = mysql +db-port = 3306 +db-driver = com.mysql.jdbc.Driver +db-url-without-db-name = jdbc:mysql://${db-host}:${db-port}/ +db-url = ${db-url-without-db-name}${db-name}?characterEncoding=utf8 + +cgi-metadata-url = https://m00-mg-local.testidp.funktionstjanster.se/samlv2/idp/metadata/0/0 +authentication-configuration = loginPassword,cgi +cgi-user-role-name = BankID +external-authenticator= +external-user-and-role-registry= +#Azure Active Directory authentication parameter +aad.client.id=92a11e03-7eb3-420e-9a8a-1c874307a9a2 +aad.secret.key=2l8MLkts2Y77x+ClvyQg5KzKzYxpURoYUADTi/tfiRs= +aad.tenant.id=sergmaximchukgmail.onmicrosoft.com + +# LDAP-authentication-parameters + +ldap-url = ldap://localhost:389/CN=Users,DC=example,DC=com +ldap-bind-dn = +ldap-password = +ldap-test-user = +ldap-test-password = +ldap-read-timeout-millis = 5000 +ldap-max-connections = 20 +ldap-connection-expiry-seconds = 540 +ldap-user-object-class = inetOrgPerson +ldap-attribute-login-name = uid + +# For Microsoft Active Directory +#ldap-user-object-class = user +#ldap-attribute-login-name = sAMAccountName + + +secondary-external-authenticator = +secondary-external-user-and-role-registry = + +# Secondary LDAP-authentication-parameters + +secondary-ldap-url = ldap://localhost:389/CN=Users,DC=example,DC=com +secondary-ldap-bind-dn = +secondary-ldap-password = +secondary-ldap-test-user = +secondary-ldap-test-password = +secondary-ldap-user-object-class = inetOrgPerson +secondary-ldap-attribute-login-name = uid + +# For Microsoft Active Directory +#secondary-ldap-user-object-class = user +#secondary-ldap-attribute-login-name = sAMAccountName + + +sso-enabled = false + +sso-use-local-jaas-config = true +sso-jaas-config-name = Imcms +sso-jaas-principal-name = +sso-jaas-principal-password = + +sso-use-local-krb-config = true +sso-krb-realm = +sso-krb-kdc = + +sso-kerberos-debug = false + + +# The smtp-server used for sending mails. + +smtp-server = + + +# The name and e-mail-address of the servermaster. + +servermaster-name = +servermaster-email = + + +# The name and e-mail-address of the webmaster. +# Defaults to the values for the servermaster. + +webmaster-name = ${servermaster-name} +webmaster-email = ${servermaster-email} + + +# The default language to use when build the webapp ( swe | eng ) + +defaultlanguage = eng + + +# The imCMS documents is usually on the imCMS public site, http://doc.imcms.net/ +# If you want to install a local server for handling (modifying) the documents +# change this: + +documentation-host = doc.imcms.net + + +# URL to the separate image archive application, as seen by the clients browser. +# For example: test.com/image-archive/archive +# +# [":" ] "/" "/archive" +image-archive-url = + +# IDs of the roles that are allowed to see the "Choose from image archive" button in image edit page, delimited by ",". +# If not specified, everyone is allowed. +image-archive-allowed-role-ids = + +# IDs of the roles that are allowed to see the "Choose file" (old archive) button in image edit page, delimited by ",". +# If not specified, everyone is allowed. +choose-file-allowed-role-ids = + +# ImageMagick is a software suite for creating, editing and composing images. It can be downloaded from http://www.imagemagick.org. +# It is used by both image archive and image handling. +# This path should lead to where ImageMagick is installed, and is required only on windows. +# For example: c:/program files/imagemagick-6.4.9-q16 +image-magick-path = + +# Maximum size in bytes of cache for images created in the text editor (xinha). By default 500 MB. +image-cache-max-size = 524288000 + +# Enables login passwords encryption +# Type: boolean; optional; default: false +# Any non-true value or absence of value is treated as false. +# When enabled +# --passwords are stored in encrypted form. +# --any unencrypted passwords will be encrypted on system start/restart. +# Since 4.0.7 +login-password-encryption-enabled = + +# Shared salt used in login passwords encryption. +# Type: string; optional; default: blank +# An additional, shared 'salt' used for all internal users' login passwords encryption. +# WARNING! +# Assigning a different value on a running system with enabled password encryption +# will immediately lead to inability to login for all internal users whom passwords are already encrypted. +# See description of [login-password-encryption-enabled] property. +# Since 4.0.7 +login-password-encryption-salt = + +# Password reset lifespan in hours, after rest link is created and sent by email +# Type: positive int; optional; default: 24 (hours) +# Since 4.0.7 +login-password-reset-lifespan = + +# Allows superadmins to reset their passwords. +# Type: boolean; optional; default: false +# Any non-true value or absence of value is treated as false. +# Since 4.0.7 +superadmin-login-password-reset-allowed = + +# Maximum number of cached image size objects. +image-size-cache-objects = 10000 + +# Comma separated list of mime types +# Since 4.2.4 +index-disabled-file-mimes = + +# Comma separated list of filename extensions +# Since 4.2.4 +index-disabled-file-extensions = + +# Error logger url. +error-logger-url = + +#SMS Gateway settings +sms.gateway.username = +sms.gateway.password = +sms.gateway.url = +sms.gateway.originAddress = +sms.gateway.defaultCountryCode = + +#2FA settings +2fa.cookie.lifetime = + +# Filters + +# Type: boolean; optional; default: true +csrf-include = true + +# Type: boolean; optional; default: true +xss-include = true + +AllowFileAdmin = + +w3c.validation = true diff --git a/build.properties.template b/build.properties.template index 4ae6b01500..d09b8d91db 100644 --- a/build.properties.template +++ b/build.properties.template @@ -2,26 +2,15 @@ # You just have to fill in the blanks. # You shouldn't change any defaults unless you know what you are doing. - -# The deployment directory (parent of the webapp directory). -# Do *not* use back-slashes ('\'). Use forward-slashes ('/'). -# You only need this if you want to use "ant install" and "ant install-war". - -deployroot = - - -# The name of the webapp. Used for filenames and URIs. - -webappname = imcms - - -# The deployed web application diretory - -webapproot = ${deployroot}/${webappname} +# Database schema version. +db-schema-version = 4.17 # Denies multiple login for same user. To enable this option change property value to true. deny-multiple-user-login = false +#Server host +server-name = http://localhost:8080 + # Database parameters db-host = localhost @@ -31,19 +20,23 @@ db-pass = db-maxconnections = 20 # For MSSQL -db-target = mssql -db-port = 1433 -db-driver = net.sourceforge.jtds.jdbc.Driver -db-url-without-db-name = jdbc:jtds:sqlserver://${db-host}:${db-port}/;AppName=imCMS -db-url = ${db-url-without-db-name};DatabaseName=${db-name} +#db-target = mssql +#db-port = 1433 +#db-driver = net.sourceforge.jtds.jdbc.Driver +#db-url-without-db-name = jdbc:jtds:sqlserver://${db-host}:${db-port}/;AppName=imCMS +#db-url = ${db-url-without-db-name};DatabaseName=${db-name} # For MySQL -#db-target = mysql -#db-port = 3306 -#db-driver = com.mysql.jdbc.Driver -#db-url-without-db-name = jdbc:mysql://${db-host}:${db-port}/ -#db-url = ${db-url-without-db-name}${db-name}?characterEncoding=utf8 +db-target = mysql +db-port = 3306 +db-driver = com.mysql.jdbc.Driver +db-url-without-db-name = jdbc:mysql://${db-host}:${db-port}/ +db-url = ${db-url-without-db-name}${db-name}?characterEncoding=utf8 +cgi-metadata-url = https://m00-mg-local.testidp.funktionstjanster.se/samlv2/idp/metadata/0/0 +#Add '2FA' to enable sms authentication +authentication-configuration = loginPassword,cgi +cgi-user-role-name = BankID external-authenticator = external-user-and-role-registry = @@ -55,6 +48,9 @@ ldap-bind-dn = ldap-password = ldap-test-user = ldap-test-password = +ldap-read-timeout-millis = 5000 +ldap-max-connections = 20 +ldap-connection-expiry-seconds = 540 ldap-user-object-class = inetOrgPerson ldap-attribute-login-name = uid @@ -81,6 +77,20 @@ secondary-ldap-attribute-login-name = uid #secondary-ldap-attribute-login-name = sAMAccountName +sso-enabled = false + +sso-use-local-jaas-config = true +sso-jaas-config-name = Imcms +sso-jaas-principal-name = +sso-jaas-principal-password = + +sso-use-local-krb-config = true +sso-krb-realm = +sso-krb-kdc = + +sso-kerberos-debug = false + + # The smtp-server used for sending mails. smtp-server = @@ -104,11 +114,6 @@ webmaster-email = ${servermaster-email} defaultlanguage = eng -# The root-URI of the webapp, relative to the server root-URI (/). - -rooturl = /${webappname} - - # The imCMS documents is usually on the imCMS public site, http://doc.imcms.net/ # If you want to install a local server for handling (modifying) the documents # change this: @@ -116,37 +121,82 @@ rooturl = /${webappname} documentation-host = doc.imcms.net -# Whether the build should be optimized or not. - -optimize = on - - -# Whether to leave debug info in or not. - -debug = on - - -# Whether to compile with deprecation warnings on or not. - -deprecation = on - - -# For JUnit-tests to work, you need to add junit.jar to the classpath of ant. -# If this is impossible, uncomment the following property. -# Note that this will prevent tests from running. - -#no-junit-task-available - - -# Which log4j-config-file to use. -# You might want to change this to log4j-debug.xml to turn on debug-logs. - -log4j-config = log4j-nodebug.xml - - -# Tomcat settings for quick deployment during development - -tomcat-admin-username = admin -tomcat-admin-password = -tomcat-webapp-manager-url = http://localhost:8080/manager -tomcat-deployroot-local-directory = +# URL to the separate image archive application, as seen by the clients browser. +# For example: test.com/image-archive/archive +# +# [":" ] "/" "/archive" +image-archive-url = + +# IDs of the roles that are allowed to see the "Choose from image archive" button in image edit page, delimited by ",". +# If not specified, everyone is allowed. +image-archive-allowed-role-ids = + +# IDs of the roles that are allowed to see the "Choose file" (old archive) button in image edit page, delimited by ",". +# If not specified, everyone is allowed. +choose-file-allowed-role-ids = + +# ImageMagick is a software suite for creating, editing and composing images. It can be downloaded from http://www.imagemagick.org. +# It is used by both image archive and image handling. +# This path should lead to where ImageMagick is installed, and is required only on windows. +# For example: c:/program files/imagemagick-6.4.9-q16 +image-magick-path = + +# Maximum size in bytes of cache for images created in the text editor (xinha). By default 500 MB. +image-cache-max-size = 524288000 + +# Enables login passwords encryption +# Type: boolean; optional; default: false +# Any non-true value or absence of value is treated as false. +# When enabled +# --passwords are stored in encrypted form. +# --any unencrypted passwords will be encrypted on system start/restart. +# Since 4.0.7 +login-password-encryption-enabled = + +# Shared salt used in login passwords encryption. +# Type: string; optional; default: blank +# An additional, shared 'salt' used for all internal users' login passwords encryption. +# WARNING! +# Assigning a different value on a running system with enabled password encryption +# will immediately lead to inability to login for all internal users whom passwords are already encrypted. +# See description of [login-password-encryption-enabled] property. +# Since 4.0.7 +login-password-encryption-salt = + +# Password reset lifespan in hours, after rest link is created and sent by email +# Type: positive int; optional; default: 24 (hours) +# Since 4.0.7 +login-password-reset-lifespan = + +# Allows superadmins to reset their passwords. +# Type: boolean; optional; default: false +# Any non-true value or absence of value is treated as false. +# Since 4.0.7 +superadmin-login-password-reset-allowed = + +# Maximum number of cached image size objects. +image-size-cache-objects = 10000 + +# Comma separated list of mime types +# Since 4.2.4 +index-disabled-file-mimes = + +# Comma separated list of filename extensions +# Since 4.2.4 +index-disabled-file-extensions = + +# Error logger url. +error-logger-url = + +#SMS Gateway settings +sms.gateway.username = +sms.gateway.password = +sms.gateway.url = +sms.gateway.originAddress = +sms.gateway.defaultCountryCode = + +#2FA settings +2fa.cookie.lifetime = + +# comma separated user ids allowed to access FileAdmin +AllowFileAdmin = \ No newline at end of file diff --git a/build.xml b/build.xml index 4f41bb8746..48ff6ca741 100644 --- a/build.xml +++ b/build.xml @@ -86,8 +86,6 @@ - - @@ -96,7 +94,7 @@ - + @@ -125,7 +123,12 @@ - + + + + + + @@ -192,17 +195,17 @@ - CREATE DATABASE ${db-name} + + - @@ -216,6 +219,8 @@ + + @@ -313,7 +318,7 @@ @@ -376,6 +381,10 @@ + + + + @@ -520,6 +529,7 @@ + @@ -536,7 +546,6 @@ depends="check-build-properties,init-version-properties"> - @@ -549,12 +558,24 @@ + + + + + + + + + + + + @@ -569,6 +590,20 @@ + + + + + + + + + + + + + + @@ -577,6 +612,11 @@ + + + + + diff --git a/docs/BUILD.TXT b/docs/BUILD.TXT index 5a8caed171..6643bc1e60 100644 --- a/docs/BUILD.TXT +++ b/docs/BUILD.TXT @@ -3,7 +3,7 @@ Building imCMS: Prerequisites: - * Install the Java Development Kit version 1.4 or later. + * Install the Java Development Kit version 1.5 or later. * Install Apache Ant 1.6.2 or later. diff --git a/docs/CHANGES.HTML b/docs/CHANGES.HTML new file mode 100644 index 0000000000..f10746c784 --- /dev/null +++ b/docs/CHANGES.HTML @@ -0,0 +1,3749 @@ + + + + + Changes in imCMS + + + + +

+ Changes in version 4.0.0

+

Of + importance + to + users

+
    +
  • + +

    + The HTMLArea text field editor was no longer supported and has been replaced with Xinha. + + (Issue 4596) +

    +
  • +
+

Of + importance + to + administrators

+
    +
  • + +

    + imCMS now automatically upgrades the database on startup. + When upgrading from version 3.0 or later, no manual running of SQL scripts is required. + + (Issue 206) +

    +
  • +
  • + +

    + The default character encoding has been changed from windows-1252 to UTF-8. + + (Issue 4491, Issue 4593) +

    +
  • +
+

Of + interest + to + users

+
    +
  • + +

    + Fixed a crash when trying to add a link to a document that doesn't exist. + + (Issue 4677) +

    +
  • +
  • + +

    + Created new "dual list" user interface for setting document categories. + + (Issue 3437) +

    +
  • +
  • + +

    + Created a new user interface for editing menus. + Menus are now edited on a separate page from the containing text document. + + (Issue 2939, Issue 4605) +

    +
  • +
  • + +

    + Menus can now be sorted in order of published datetime. + + (Issue 2155) +

    +
  • +
  • + +

    + The "Edit permissions for new documents" was wrongly displayed for non-text documents. + + (Issue 4636) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + The template administration user interface would crash if demo template directory was missing. + It will now be created if needed. + + (Issue 4724) +

    +
  • +
  • + +

    + Use english language error page if no user language is available. + + (Issue 4595) +

    +
  • +
  • + +

    + The maximum length for a category name was changed from 50 characters to 128. + + (Issue 4687) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Added API method Image.toHtmlTag() for + generating the html tag for an Image. + + (Issue 4712) +

    +
  • +
  • + +

    + Added + "title" + attribute to <img> + with the same content as the + "alt" + attribute. + + (Issue 4623) +

    +
  • +
  • + +

    + Removed non-XHTML compatible + "border" + attribute from <img>, + instead passing through + "style" + , + "class" + , and + "usemap" + attributes + from the <imcms:image> in the template. + + (Issue 4579) +

    +
  • +
  • + +

    + Line breaks in text fields now generate "<br />" instead of "<BR>", + providing XHTML compatibility. + + (Issue 4581) +

    +
  • +
  • + +

    +UserService.saveUser(User) did not respect the UserAdmin role. + + (Issue 4553) +

    +
  • +
+

+ Changes in version 3.2.0

+

Of + interest + to + users

+
    +
  • + +

    + Added "by published datetime" sorting to menus. + + (Issue 2155) +

    +
  • +
  • + +

    + Fixed "NullPointerException in FrequencyOrderedBag" crash. + + (Issue 4500) +

    +
  • +
  • + +

    + Fixed crash caused by menuitems not being properly removed + when deleting a document. + + (Issue 4498) +

    +
  • +
  • + +

    + Fixed crash caused by documents not being removed from the cache + when their template was deleted. + + (Issue 4800) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + Fixed image preview in the file administrator. + + (Issue 4833) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Added capability to send HTML mail. + + (Issue 4412) +

    +
  • +
  • + +

    + Mails now use UTF-8 encoding. + + (Issue 4412) +

    +
  • +
  • + +

    + Fixed a typo in TEMPLATE_SYNTAX.TXT. + + (Issue 4505) +

    +
  • +
  • + +

    + Fixed a bug preventing users with the UserAdmin role + from editing users through the API. + + (Issue 4553) +

    +
  • +
  • + +

    + Fixed a bug making it impossible to change sort keys for menu items + through the API. + + (Issue 4804) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Made the error page output less redundant by only displaying one stack trace. + + (Issue 4506) +

    +
  • +
+

+ Changes in version 3.1.2

+

Of + interest + to + users

+
    +
  • + +

    + Fixed bug that made it impossible to create new documents if there was a category-type defined. + + (Issue 4380) +

    +
  • +
  • + +

    + Made option "linked for unauthorized users" work in searches as well as in menus. + + (Issue 4385) +

    +
  • +
  • + +

    + Fixed bug that caused template ids not to be cloned when cloning text documents. + This means that for example changing the template for a newly created text document + also changes the template of the parent in the cache. + + (Issue 4401) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Fixed error when running api example "document_search.jsp" + + (Issue 4415) +

    +
  • +
  • + +

    + Fixed bug that excluded documents without a valid archived datetime from search result. + + (Issue 4352) +

    +
  • +
  • + +

    + Made the list returned by DocumentService.getDocuments(SearchQuery) modifiable. + + (Issue 4386) +

    +
  • +
  • + +

    + Fixed bug when trying to sort search result on "meta_headline". + Added new non-tokenized field "meta_headline_keyword" to use for sorting on + document headlines. + + (Issue 4415) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Upgrade imcode-db to version 0.3. + + (Issue 4389) +

    +
  • +
+

+ Changes in version 3.1.1

+

Of + interest + to + users

+
    +
  • + +

    + Fixed missing version number in help links. + + (Issue 4305) +

    +
  • +
  • + +

    + Fixed a bug which prevented sort keys for menuitems from being saved. + + (Issue 4313) +

    +
  • +
+

+ Changes in version 3.1.0

+

Of + interest + to + users

+
    +
  • + +

    + You can now search in PDF files, as well as in Microsoft Word, Excel, and Powerpoint files. + + (Issue 1855) +

    +
  • +
  • + +

    + Performance has been improved, so searching for documents should be much faster. + + (Issue 4135) +

    +
  • +
  • + +

    + Fixed a NullPointerException when browsing search result, for example when searching for images. + + (Issue 2926) +

    +
  • +
  • + +

    + Fixed a problem with image filenames containing spaces. + + (Issue 4148) +

    +
  • +
  • + +

    + Fixed an exception when entering an invalid text document id for an include. + + (Issue 4212) +

    +
  • +
  • + +

    + Fixed a bug where menus would cache their documents, + so changes to documents would not be visible in menus immediately. + + (Issue 4092) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + You can now search for users by role, title, company, and email address. + + (Issue 4140, Issue 4142) +

    +
  • +
  • + +

    + Made sure that temporary upload files are removed in a timely manner. + + (Issue 4235) +

    +
  • +
  • + +

    + Fixed a bug where a superadmin which was also useradmin couldn't edit all roles for a user. + + (Issue 4117) +

    +
  • +
  • + +

    + Fixed a bug where the file manager would fail to change directories if the webapp + was situated in a symlinked path. + + (Issue 4278) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Documents are now lazily loaded, + so as to not retrieve more from the database than is needed. + + (Issue 4135) +

    +
  • +
  • + +

    + Removed the unused addon property from build.properties.template. + + (Issue 4233) +

    +
  • +
+

+ Changes in version 3.0.1

+

Of + interest + to + users

+
    +
  • + +

    + Image-paths are URL-encoded to fix problems with image-paths containing non-ASCII characters. + + (Issue 3646) +

    +
  • +
  • + +

    + Users with "restricted 1/2" permissions on a page could not save a text document + if it linked to documents the user couldn't link to. + + (Issue 3773) +

    +
  • +
  • + +

    + Searches on the "phase" field of a document, such as "phase:published" or "phase:new", + would search based on the time that the document was indexed, not the time of the search. + Such queries are now rewritten on the fly to fix this. + + (Issue 3691) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + If there was an error while deploying, the deploy failed completely. + Now the deploy succeeds, and the error appears in the browser instead. + + (Issue 3706) +

    +
  • +
  • + +

    + Fixed a problem with default values in the SQL script for MySQL 5. + + (Issue 3643) +

    +
  • +
  • + +

    + Ignore IPv6 and other non IPv4-addresses instead of choking on them. + + (Issue 3681) +

    +
  • +
  • + +

    + Added MySQL sample to server.properties. + + (Issue 3705) +

    +
  • +
  • + +

    + The upgrade SQL script diff-2-3.sql did not work in some cases, + due to some foreign keys to the 'users' table changing name. + + (Issue 3707) +

    +
  • +
  • + +

    + The imCMS advertisement at the top of every page was not output when the html tag contained attributes. + + (Issue 3778) +

    +
  • +
  • + +

    + An attempt to reduce ThreadDeath errors with Tomcat has been done, + by providing only commons-logging-api and calling + LogFactory.releaseAll() on shutdown. + + (Issue 3860) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Source is now included for our own libraries. + + (Issue 3708) +

    +
  • +
  • + +

    + The ddlutils and commons-betwixt libraries have been updated to newer non-released versions + from the Apache Subversion repository, so we don't have to keep the ddlutils version patched by us. + + (Issue 3914) +

    +
  • +
+

+ Changes in version 3.0.0

+

Of + importance + to + administrators

+
    +
  • + +

    + Removed deprecated features "conference", "billboard", "chat", "shop", "poll", "qengine", "fortune". + Warning! If you are using these features, all data for them will be deleted in the upgrade! + + (Issue 3347) +

    +
  • +
  • + +

    + imCMS may now also be run on MySQL. + In theory it may run on any DBMS which has a JDBC 3.0 compliant driver, + but this has not been tested. + + (Issue 1288) +

    +
  • +
  • + +

    + The setting LdapUserAttribute.CountyCouncil in server.properties + has been replaced by LdapUserAttribute.Province. + + (Issue 3537) +

    +
  • +
+

Of + importance + to + site developers

+
    +
  • + +

    + Many methods no longer throw NoPermissionException, + notably most accessors of Document and its subclasses. + Permissions are instead checked when saving the document. + + (Issue 2980) +

    +
  • +
+

Of + interest + to + users

+
    +
  • +

    + The text editor now runs the MS Word-code removal filter every time you paste. +

    +
  • +
  • + +

    + Linking a document for which you had no permissions was impossible + regardless of whether the document was "linkableByOtherUsers". +

    +

    + This has been worked around so that you can add a document by entering its id, + if a search for that id doesn't match another document. + + (Issue 3385) +

    +
  • +
  • + +

    + The reset button in the text editor did not work. + + (Issue 3469) +

    +
  • +
  • + +

    + Removed broken undo/redo support in the text editor until properly supported by upstream. + + (Issue 3468) +

    +
  • +
  • + +

    + Integrated jsCalendar (http://www.dynarch.com/projects/calendar/) for selecting datetimes. + + (Issue 3442) +

    +
  • +
  • + +

    + If a user with "restricted 1" or "restricted 2" permissions created a document, + the default "default template" was ignored. + + (Issue 3409) +

    +
  • +
  • + +

    + Added a new default tab "Create new" to "My pages", + which doesn't list documents, but allows creating new documents. + + (Issue 2975) +

    +
  • +
  • + +

    + The text editor ctrl-key combinations would ignore the alt-key. + + (Issue 3094) +

    +
  • +
  • + +

    + A non-numeric prefix in a tree menu sort key would cause an exception. + + (Issue 2924) +

    +
  • +
  • + +

    + Copying a document did not copy its menus. + + (Issue 2992) +

    +
  • +
  • + +

    + If a category type was changed it would not affect editing cached documents. + + (Issue 3526) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + Accessing /servlet/Version now + prints the versions of java, the servlet container, and the database along with the imCMS version. + + (Issue 3519) +

    +
  • +
  • + +

    + It was impossible to delete some directories in the file manager. + + (Issue 3509) +

    +
  • +
  • + +

    + Disconnect from database when the webapp is shut down. + + (Issue 3511) +

    +
  • +
  • + +

    + Pressing "Add" or "Remove" when assigning templates to template groups with no templates listed + would throw an exception. + + (Issue 3479) +

    +
  • +
  • + +

    + Refactored login/access_denied.jsp and login/no_permission.jsp + into login/index.jsp. + + (Issue 3467) +

    +
  • +
  • + +

    + Renaming templates to already existing name would throw an exception. + + (Issue 3466) +

    +
  • +
  • + +

    + Allow superadmin to edit his/her own roles. + + (Issue 2935) +

    +
  • +
  • + +

    + Removed "List new/modified documents", and moved its functionality to the search form. + + (Issue 3421) +

    +
  • +
  • + +

    + If a role was removed, editing permissions for a cached document with that role would throw an exception. + + (Issue 3420) +

    +
  • +
  • + +

    + Prevent multiple users from being created with the same name. + + (Issue 3150) +

    +
  • +
  • + +

    + Users with the useradmin role could edit any user under certain conditions. + + (Issue 2757) +

    +
  • +
  • + +

    + Scheduled indexing may now be disabled by setting IndexingSchedulePeriodInMinutes + in server.properties to + "0" + . + + (Issue 3144) +

    +
  • +
  • + +

    + Build index in subdirectories of WEB-INF/index instead of in WEB-INF/index.new. + + (Issue 3491) +

    +
  • +
  • + +

    + For each reload of the webapp a new background indexing thread would be started, + leading to multiple concurrent indexings. + This has been worked around so that an indexing thread terminates + if it notices that the index has been changed. + + (Issue 3155) +

    +
  • +
  • + +

    + Some error pages were shown as html code. + + (Issue 3501) +

    +
  • +
  • + +

    + Fixed spurious NullPointerExceptions in "LRUMap.reuseMapping()" due to unsynchronized access. + + (Issue 2923) +

    +
  • +
  • + +

    + Documents were not removed from the index when deleted. + + (Issue 3182) +

    +
  • +
  • + +

    + Increased space for system message to 1000 characters. + + (Issue 3072) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Added the method DatabaseService.getDataSource() + for accessing the underlying DataSource. + + (Issue 3527) +

    +
  • +
  • + +

    + The login page now passes along parameters "next_meta" and "next_url", + either of which can be used to redirect the user after login. + + (Issue 3433) +

    +
  • +
  • + +

    + Added the following methods to com.imcode.imcms.api.Document: +

    +
      +
    • +Document.getKeywords() +
    • +
    • +Document.setKeywords(Set) +
    • +
    • +Document.isLinkableByOtherUsers() +
    • +
    • +Document.setLinkableByOtherUsers(boolean) +
    • +
    • +Document.isSearchDisabled() +
    • +
    • +Document.setSearchDisabled(boolean) +
    • +
    +

    + (Issue 2930, Issue 2931, Issue 2932) +

    +
  • +
  • + +

    + Deprecated the method TextDocument.MenuItem.getManualNumber(), + and added the replacement methods TextDocument.MenuItem.setSortKey(Integer) + and TextDocument.MenuItem.getSortKey(). + + (Issue 2927) +

    +
  • +
  • + +

    + Added method TextDocument.MenuItem.setTreeKey(TreeKey). + + (Issue 2928) +

    +
  • +
  • + +

    + Deprecated methods Document.setStatus(int) and Document.getStatus(). + Added the replacement methods Document.setPublicationStatus(PublicationStatus) + and Document.getPublicationStatus() and the class Document.PublicationStatus. + + (Issue 3037) +

    +
  • +
  • + +

    + Deprecated methods Document.setPermissionSetIdForRole(Role,int) + and Document.getPermissionSetIdForRole(Role). + Added the replacement methods Document.setPermissionSetTypeForRole(Role,DocumentPermissionSetType) + and Document.getPermissionSetTypeForRole(Role) + and the class DocumentPermissionSetType. +

    +

    + Deprecated method DocumentPermissionSet.getType() with no replacement. + + (Issue 3037) +

    +
  • +
  • + +

    + Deprecated methods User.setCountyCouncil(String) + and User.getCountyCouncil(). + Added the replacement methods User.setProvince(String) + and User.getProvince(). + + (Issue 3537) +

    +
  • +
  • + +

    + Added method DocumentService.deleteDocument(Document). + + (Issue 3428) +

    +
  • +
  • + +

    + Added method UserService.getUser(int). + + (Issue 2929) +

    +
  • +
  • + +

    + You can now set the creator of a new Document. + + (Issue 3012) +

    +
  • +
  • + +

    + Added class LuceneQuery which allows using the Lucene API directly. + + (Issue 2364) +

    +
  • +
  • + +

    + Including a non-existent path using an include-tag would throw a NullPointerException. + + (Issue 3490) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + SQL DDL is now generated from XML source using Apache DdlUtils. +

    +

    + SQL procedures previously stored in the database are now loaded from disk. + Many of them have been removed. + + (Issue 1288, Issue 3436) +

    +
  • +
  • + +

    + Refactored parts of the database layer into a separate library named imcode-db. + + (Issue 3454) +

    +
  • +
  • + +

    + Removed the tools classes and extracted libraries imcode-util and imcode-ant-tasks. + + (Issue 3304) +

    +
  • +
  • + +

    + A document is always fetched from the database inside of a transaction. + + (Issue 3162) +

    +
  • +
  • + +

    + JSPs are now compiled during the build to find errors. + + (Issue 2089) +

    +
  • +
  • + +

    + Checkstyle is run during the build to find style errors. + + (Issue 3443) +

    +
  • +
  • + +

    + Building with a platform default encoding other than iso-8859-1 would fail. + + (Issue 3459, Issue 3462) +

    +
  • +
  • + +

    + A ServletContextListener is used to start up, instead of a load-on-startup servlet. + + (Issue 3510) +

    +
  • +
  • + +

    + The links on the first welcome page will now be accurate regardless of context path. + + (Issue 3514) +

    +
  • +
+

+ Changes in version 2a.0.0

+

Of + interest + to + users

+
    +
  • + +

    + Fixed a NullPointerException when trying to view a textpage containing a + filedocument-image that had been deleted. + + (Issue 3125) +

    +
  • +
  • + +

    + Made <?imcms:include file="..."?> recursively parse tags. + + (Issue 3122) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    +UserService.getUser(String) now returns null for non-existing users. + + (Issue 3167) +

    +
  • +
+

+ Changes in version 2.2.0

+

Of + interest + to + users

+
    +
  • + +

    + Added "Save" and "Save and close" buttons to text editor. + + (Issue 2937) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + When including other documents, + the TextDocumentViewing in the request was replaced, + so that subsequent TextDocumentViewings + in the including document came from the included document. + + (Issue 3062) +

    +
  • +
+

+ Changes in version 2.1.1

+

Of + interest + to + users

+
    +
  • + +

    + Fixed a problem where a user would lose all his roles when editing himself. + + (Issue 2925) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + There was a mistake made with the + ContentManagementSystem.runAsSuperadmin(ContentManagementSystemRunnable) + method so it actually did not work at all. + + (Issue 2901) +

    +
  • +
+

+ Changes in version 2.1.0

+

Of + importance + to + administrators

+
    +
  • + +

    + Fixed a security hole that could let an attacker overwrite any file in the system. + + (Issue 2891) +

    +
  • +
+

Of + interest + to + users

+
    +
  • + +

    + Only read permission on a document was required to add it to a menu. + Now at least restricted 2 is required. + + (Issue 2895) +

    +
  • +
  • + +

    + Fixed a bug that made it impossible to set "edit texts" permission for restricted 1 or 2. + + (Issue 2885) +

    +
  • +
  • + +

    + Fixed a bug that would cause text in text fields to be interpreted as velocity code when + displayed for editing. + + (Issue 2892) +

    +
  • +
  • + +

    + Made enter submit a text field when using "rows='1'". + + (Issue 2881) +

    +
  • +
  • + +

    + Fixed a javascript error when editing texts and using the + "formats" + attribute. + + (Issue 2879) +

    +
  • +
  • + +

    + The text editor would insert spurious <br />-tags when the text was empty. + They are now removed when saving and when switching formats. + + (Issue 2890) +

    +
  • +
  • + +

    + Fixed an exception when trying to edit a non-existing document. + + (Issue 2898) +

    +
  • +
+

Of + interest + to + template creators

+
    +
  • + +

    + Allow velocity code in all tag attributes. + See TEMPLATE_SYNTAX.TXT for details. + + (Issue 2785) +

    +
  • +
  • + +

    + Whitespace in + "label" + -attributes are now normalized, + i.e. consecutive runs of whitespace are replaced by a single space. + This is a workaround for newlines in the + "label" + -attribute + not being handled correctly in some places. + + (Issue 2874) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + Fixed a bug where deleted documents would remain in the cache. + + (Issue 2882) +

    +
  • +
  • + +

    + Allow role names of up to 60 characters, and display more than three roles at a time. + + (Issue 2889) +

    +
  • +
  • + +

    + Fixed a bug that caused text in templates to be interpreted as velocity code when displayed for editing. + + (Issue 2888) +

    +
  • +
  • + +

    + Updated jTDS to version 1.0. + + (Issue 2883) +

    +
  • +
  • + +

    + Fixed a problem where references to removed documents + were retained in menus, causing NullPointerExceptions. + + (Issue 2894) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Added package com.imcode.imcms.api.contrib, + containing class DateTextFieldTextDocumentComparator, + contributed by Anders Flodell and Pontus Amberg at Vetenskapsrådet. + + (Issue 2897) +

    +
  • +
  • + +

    + Added class ContentManagementSystemRunnable and + method ContentManagementSystem.runAsSuperadmin(ContentManagementSystemRunnable) + to allow code that has been signed by an administrator to run with superadmin-privileges. +

    +

    + The following things are required to run code with superadmin-privileges: +

    +
      +
    • +KeyStorePath in server.properties must be the path of a keystore.
    • +
    • The class implementing ContentManagementSystemRunnable must be signed (e.g. inside a signed jar-file).
    • +
    • All certificates used for signing the class must be found in the keystore.
    • +
    +

    + See http://java.sun.com/docs/books/tutorial/jar/sign/ + for more information about signing jar files. + + (Issue 2875) +

    +
  • +
  • + +

    + Made it possible to edit categories through the API. +

    +

    + Added methods setName(), setDescription(), + and setImage() to Category. +

    +

    + Added method DocumentService.saveCategory(Category). +

    +

    + Deprecated method DocumentService.createNewCategory(String, String, String, CategoryType). + Use Category.Category(String, CategoryType) + and DocumentService.saveCategory(Category) instead. + + (Issue 2790) +

    +
  • +
  • + +

    + Methods UserService.getRole(int) and UserService.getRole(String) + no longer require superadmin-permissions. + + (Issue 2884) +

    +
  • +
  • + +

    + Methods TextDocument.Menu.addDocument(Document) + and TextDocument.Menu.removeDocument(Document) erroneously required + edit-permissions for the document added or removed, instead of the menu document as intended. + + (Issue 2893) +

    +
  • +
  • + +

    + Added fields section_id, category, category_type, + and category_type_id to search index. + + (Issue 2887) +

    +
  • +
  • + +

    + Added the constants Document.LifeCyclePhase.NEW, + Document.LifeCyclePhase.APPROVED, + Document.LifeCyclePhase.DISAPPROVED, + Document.LifeCyclePhase.PUBLISHED, + Document.LifeCyclePhase.ARCHIVED, + and Document.LifeCyclePhase.UNPUBLISHED, + to be used as values in searches on the field "phase". + + (Issue 2880) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + The java code in the tools directory were not built with + source="1.4" and target="1.4". + This caused parts of imCMS to break when compiled with java 1.5 and run on java 1.4. + + (Issue 2878) +

    +
  • +
+

+ Changes in version 2.0.0

+

Of + importance + to + users

+
    +
  • + +

    + New url format for documents: /imcms/1001 instead of /imcms/servlet/GetDoc?meta_id=1001. + The old format still works, but this means that relative links in pages are likely to break. + + (Issue 1163) +

    +
  • +
  • + +

    + To alleviate broken relative links, /imcms/GetDoc?meta_id=1001 now works as well as /imcms/servlet/GetDoc?meta_id=1001. + + (Issue 2727) +

    +
  • +
+

Of + importance + to + administrators

+
    +
  • + +

    + We're now using jTDS instead of Microsofts JDBC driver. + The Microsoft driver may still somewhat work, + but it is strongly recommended that you use jTDS instead. + To do this, change the following values in server.properties: +

    +
      +
    • Set JdbcDriver to + "net.sourceforge.jtds.jdbc.Driver" +
    • +
    • Set JdbcUrl to + + "jdbc:jtds:sqlserver://<host>:<port>/;AppName=imCMS;DatabaseName=<databasename>" + + substituting correct values for <host>, + <port>, and <databasename>.
    • +
    +

    + (Issue 1850) +

    +
  • +
  • + +

    + We require javamail 1.3 or later, but Tomcat 4.1.30 and earlier includes javamail 1.2, + which overrides our included implementation (GNU classpathx javamail). +

    +

    + If you're using Tomcat 4.1.30 or earlier, you can do one of three things: +

    +
      +
    • Recommended: Upgrade Tomcat to version 4.1.31 or later.
    • +
    • Remove mail.jar and activation.jar from tomcat/common/lib. + If you use any web applications that require any of them, you can put them in the WEB-INF/lib directory of those applications. + imCMS will use its own implementation.
    • +
    • Replace mail.jar in the directory tomcat/common/lib with mail.jar from JavaMail 1.3 or later. + JavaMail can be downloaded from http://java.sun.com/products/javamail/downloads/ +
    • +
    +

    + If you are using another servlet engine that includes an older implementation of javamail, + similar action may be required. + + (Issue 2859) +

    +
  • +
  • + +

    + Specifically, the new url format is + <contextpath><prefix><document-id>, + e.g. /imcms<prefix>1001. + The <prefix> can be set with the setting DocumentPathPrefix in server.properties. + The default is + "/" + . Comment this out to disable the new url format. + + (Issue 2733) +

    +
  • +
  • + +

    + The latest documents requested from the database are now cached in memory. + This makes imCMS much faster, but means that changes to the database won't be seen. + The maximum number of documents cached can be set using + DocumentCacheMaxSize in server.properties. + The default is to cache at most 100 documents. + + (Issue 2083, Issue 2864) +

    +
  • +
  • + +

    + All the class-files that used to live in WEB-INF/classes + are now packaged in one jar file in WEB-INF/lib. + + (Issue 2746) +

    +
  • +
  • + +

    + Some objects were put in sessions when editing documents, and never removed. + These are now removed when no longer needed. This might reduce memory usage a bit. + + (Issue 2750) +

    +
  • +
+

Of + interest + to + users

+
    +
  • + +

    + A new function called "My pages" gives you an easy overview of your documents. + It is accessible through the "admin" button for users + which have any role that has permission to access "My pages". + + (Issue 2578) +

    +
  • +
  • + +

    + A new better html editor (http://www.dynarch.com/projects/htmlarea/) + which also supports Mozilla browsers has been incorporated. + + (Issue 2548) +

    +
  • +
  • + +

    + The search page now allows much more advanced searches. + + (Issue 2578) +

    +
  • +
  • + +

    + File extension "dot" is now recognized as a Microsoft Word file. + + (Issue 2681) +

    +
  • +
  • + +

    + File extension "ppt" is now recognized as a Microsoft Powerpoint file. + + (Issue 2743) +

    +
  • +
  • + +

    + Updated the look of the user interface a bit, notably the adminbuttons and the template dialog. + + (Issue 2796) +

    +
  • +
  • + +

    + One can now on the permission page set a default template to be used for new text documents. + + (Issue 2451) +

    +
  • +
  • + +

    + Don't display a broken image for an empty image field. + + (Issue 2567) +

    +
  • +
  • + +

    + Fixed problem with previewing images with non-ASCII characters in the name in the image browser. + + (Issue 2653) +

    +
  • +
  • + +

    + Don't show button to upload images if lacking permission to do so. + + (Issue 2734) +

    +
  • +
  • + +

    + Changed certain file uploading error messages to be somewhat clearer. + + (Issue 2591) +

    +
  • +
  • + +

    + Fixed a problem where users were allowed to access the document "page info" without proper permissions. + + (Issue 2680) +

    +
  • +
  • + +

    + Set creation date to "now" for copies of documents. + + (Issue 2737) +

    +
  • +
  • + +

    + Fixed help message on "file edit page". + + (Issue 2682) +

    +
  • +
  • + +

    + The OK button on the document "page info" page was unclickable in Safari on Mac due to a javascript. + + (Issue 2703) +

    +
  • +
  • + +

    + Hide categories on "page info" page if none exist. + + (Issue 2794) +

    +
  • +
  • + +

    + Added shortcut buttons to set dates to "Now" on "page info" page. + + (Issue 2794) +

    +
  • +
  • + +

    + The creator and some dates were not set properly for copied documents. + + (Issue 2803) +

    +
  • +
  • + +

    + Removed misleading instructions on how to create documents. + + (Issue 2799) +

    +
  • +
  • + +

    + Fixed problem with data for browser documents not being saved on creation. + + (Issue 2839) +

    +
  • +
  • + +

    + Missing schemes are now automatically added to urls. + + (Issue 2860) +

    +
  • +
  • + +

    + The link checker now handles relative and schemeless urls. + + (Issue 2861) +

    +
  • +
  • + +

    + When editing menus, for each menu display two numbers. +

    +

    + One number is the number of documents a visitor to the site would see in the menu, + and the other number is the number of documents the current user can see when editing the menu. + + (Issue 2800) +

    +
  • +
  • + +

    + Allow setting the link target when editing a file document. + + (Issue 2771) +

    +
  • +
+

Of + interest + to + template creators

+
    +
  • + +

    + Added the file TEMPLATE_SYNTAX.TXT containing a basic reference to the template tags. + + (Issue 2689) +

    +
  • +
  • + +

    + Local includes can now be made using <?imcms:include path="/relative/to/context/path"?>. + These don't require a http-request to localhost as url-includes do, + are a magnitude more efficient, and don't spam the access-log. + + (Issue 2684) +

    +
  • +
  • + +

    + Jakarta Velocity can now be used in templates, between <?imcms:velocity?> ... <?/imcms:velocity?> tags. + See the file TEMPLATE_SYNTAX.TXT for details. + + (Issue 2668) +

    +
  • +
  • + +

    + Attributes + "pre" + and + "post" + + can now be used on <?imcms:menu?>. + + (Issue 2668) +

    +
  • +
  • + +

    + Attributes in tags can now be html-escaped, like so: <?imcms:text label="&quot;quoted text&quot;"?>. + + (Issue 2783) +

    +
  • +
  • + +

    + New attribute for <?imcms:menu?>: + "defaulttemplate" + - specify the name of a template to use for new text documents created in this menu. + + (Issue 2689) +

    +
  • +
  • + +

    + New attribute for <?imcms:text?>: + "formats" + - specify what editor modes are available. + + (Issue 2709) +

    +
  • +
  • + +

    + New attribute for <?imcms:text?>: + "rows" + - indicate the preferred number of rows to the editor. + + (Issue 2764) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + When something went wrong during initialization, a useless generic "NoClassDefFoundError" was given. + + (Issue 2669) +

    +
  • +
  • + +

    + Certain html files were not viewable in the file manager. + + (Issue 2661) +

    +
  • +
  • + +

    + Fixed a problem in the diff-1.10.2-1.11.sql database upgrade script. + + (Issue 2692) +

    +
  • +
  • + +

    + Fixed an error when trying to edit a user. + + (Issue 2696) +

    +
  • +
  • + +

    + Make sure a useradmin only can list users he can edit. + + (Issue 2757) +

    +
  • +
  • + +

    + Sometimes when using the file administrator, some files would be unremovable. + Trying to remove them will now give a rather nasty error message instead of failing silently. + This still needs improvement. + + (Issue 2442) +

    +
  • +
  • + +

    + The link checker is now multithreaded, and one can choose to list only broken links. + Also, one can specify a range of document ids to check. + + (Issue 2587, Issue 2789) +

    +
  • +
  • + +

    + Use a default value of + "1440" + (24 hours) for IndexingSchedulePeriodInMinutes + if missing from server.properties. + + (Issue 2786) +

    +
  • +
  • + +

    + Reversed sort order of "List new/updated pages". + + (Issue 2842) +

    +
  • +
  • + +

    + Allow to set no roles for users, leaving only the "Users"-role. + + (Issue 2806) +

    +
  • +
  • + +

    + Fixed a problem with mismatched filenames in the chat on case-sensitive filesystems. + + (Issue 2845) +

    +
  • +
  • + +

    + Empty passwords are no longer allowed for external authentication, e.g. LDAP. + + (Issue 2847) +

    +
  • +
  • + +

    + Updated the look of the "Edit external user" page. + + (Issue 2334) +

    +
  • +
  • + +

    + Fixed a problem with modified date of a document only being updated on every second save. + + (Issue 2858) +

    +
  • +
  • + +

    + The checksums in WEB-INF/version.txt are now in WEB-INF/checksums.txt instead, + and are not output by the "Version" servlet. + + (Issue 2865) +

    +
  • +
  • + +

    + Made a "RebuildIndex" servlet for rebuilding the index, + and fixed the "Restart" servlet to do a more thorough/proper restart of imCMS. + + (Issue 2855) +

    +
  • +
  • + +

    + Don't allow removing a template group that contains templates. + + (Issue 2836) +

    +
  • +
  • + +

    + Don't print password to log when failing to log in to an LDAP server. + + (Issue 2828) +

    +
  • +
  • + +

    + List users in order of last name and first name instead of by id. + + (Issue 2821) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Created package com.imcode.util with generic non-imCMS-specific utilities: +

    +
    +
    +ChainableReversibleNullComparator +
    +
    + - Moved here from com.imcode.imcms.api.util +
    +
    +ComparatorWrapper +
    +
    + - Moved here from com.imcode.imcms.api.util +
    +
    +HumanReadable +
    +
    + - Get human readable byte sizes and time spans.
    +
    +ImageSize +
    +
    + - Get the size of an image in somewhat more efficient manner than ImageIO.read().
    +
    +MultipartHttpServletRequest +
    +
    + - Extends HttpServletRequest for file upload with support from Jakarta Commons-FileUpload.
    +
    +

    + (Issue 2493) +

    +
  • +
  • + +

    + Users can now change their own attributes. + + (Issue 2708) +

    +
  • +
  • + +

    + Added classes: +

    +
    +
    +Role +
    +
    + - Represents a user-role.
    +
    +SaveException +
    +
    + - Thrown when something can't be saved.
    +
    +AlreadyExistsException +
    +
    + - Extends SaveException.
    +
    +TextDocumentViewing +
    +
    + - Accessible in included JSPs and velocity code. Represents one viewing of a text document.
    +
    +

    + (Issue 2676, Issue 2776) +

    +
  • +
  • +

    + Changed classes: +

    +
    +
    +MaxCategoriesOfTypeExceededException +
    +
    + - Extends SaveException +
    +
    +CategoryAlreadyExistsException +
    +
    + - Extends AlreadyExistsException +
    +
    +CategoryTypeAlreadyExistsException +
    +
    + - Extends AlreadyExistsException +
    +
    +UserAlreadyExistsException +
    +
    + - Extends AlreadyExistsException +
    +
    +RoleAlreadyExistsException +
    +
    + - Extends AlreadyExistsException +
    +
    +
  • +
  • +

    + Deprecated classes: +

    +
    +
    +com.imcode.imcms.api.util.ChainableReversibleNullComparator +
    +
    + - Moved to com.imcode.util +
    +
    +com.imcode.imcms.api.util.ComparatorWrapper +
    +
    + - Moved to com.imcode.util
    +
    +
  • +
  • + +

    + Added methods: +

    +
    +
    +ContentManagementSystem.fromRequest(ServletRequest) +
    +
    + - Get the ContentManagementSystem.
    +
    +Document.setPermissionSetIdForRole(Role,int)m
    +
    + - Replaces Document.setPermissionSetForRole(String,int) +
    +
    +Document.getPermissionSetIdForRole(Role) +
    +
    + - Get the permission set id for a role
    +
    +DocumentService.getSection(String) +
    +
    + - Get a section by name.
    +
    +Section.getId() +
    +
    + - Get the id for a section.
    +
    +TextDocument.Menu.getVisibleDocuments() +
    +
    + - Returns the documents visible in the menu.
    +
    +TextDocument.Menu.getVisibleMenuItems() +
    +
    + - Returns the menuitems visible in the menu.
    +
    +User.getRoles() +
    +
    + - Get the user's roles.
    +
    +User.setRoles(Role[]) +
    +
    + - Set the user's roles.
    +
    +User.hasRole(Role) +
    +
    + - Returns true if the user has the role.
    +
    +User.addRole(Role) +
    +
    + - Add a role to the user.
    +
    +User.removeRole(Role) +
    +
    + - Remove a role from the user.
    +
    +UserService.createNewRole(String) +
    +
    + - Create a new role
    +
    +UserService.deleteRole(Role) +
    +
    + - Delete a role, requires superadmin permission.
    +
    +UserService.getAllRoles() +
    +
    + - Returns all roles in the system, requires superadmin permission.
    +
    +UserService.getAllUsersWithRole(Role) +
    +
    + - Get all users with the given permission.
    +
    +UserService.getRole(int) +
    +
    + - Get a role by id, requires superadmin permission.
    +
    +UserService.getRole(String) +
    +
    + - Get a role by name, requires superadmin permission.
    +
    +UserService.saveRole(Role) +
    +
    + - Save changes to the role, requires superadmin permission.
    +
    +UserService.createNewUser(String, String) +
    +
    + - Create a new user.
    +
    +UserService.saveUser(User) +
    +
    + - Save a new or existing user, requires superadmin permission.
    +
    +User.set* +
    +
    + - Added a bunch of setters.
    +
    +User.get* +
    +
    + - Added a few missing getters.
    +
    +

    + (Issue 2648, Issue 2648, Issue 2677, Issue 2827, Issue 2827) +

    +
  • +
  • + +

    + Changed methods: +

    +
    +
    +DocumentService.saveChanges(Document) +
    +
    + - Throws SaveException instead of MaxCategoriesOfTypeExceededException.
    +
    +TextDocument.setInclude(int,TextDocument) +
    +
    + - Now requires you to call DocumentService.saveChanges() afterwards.
    +
    +TextDocument.Menu.getDocuments() +
    +
    + - Returns the same documents as can be seen when editing the menu.
    +
    +TextDocument.Menu.getMenuItems() +
    +
    + - Returns the same menuitems as can be seen when editing the menu. No longer throws NoPermissionException.
    +
    +UserService.addNewRole(String) +
    +
    + - Returns the new role.
    +
    +

    + (Issue 2827, Issue 2827) +

    +
  • +
  • + +

    + Undeprecated methods: +

    +
    +
    +TextDocument.setTemplate(Template) +
    +
    + - Use when you don't care about setting a template group.
    +
    +

    + (Issue 2791) +

    +
  • +
  • +

    + Deprecated methods: +

    +
    +
    +Document.setPermissionSetForRole(String,int) +
    +
    + - Use Document.setPermissionSetIdForRole(Role,int).
    +
    +User.getRoleNames() +
    +
    + - Use User.getRoles() +
    +
    +User.hasRole(String) +
    +
    + - Use User.hasRole(Role) +
    +
    +UserService.deleteRole(String) +
    +
    + - Use UserService.deleteRole(Role) +
    +
    +UserService.getAllUserWithRole(String) +
    +
    + - Use UserService.getAllUsersWithRole(Role) +
    +
    +UserService.getRoleNames(User) +
    +
    + - Use User.getRoles() +
    +
    +UserService.getAllRolesNames() +
    +
    + - Use UserService.getAllRoles() +
    +
    +UserService.setUserRoles(User,String[]) +
    +
    + - Use User.setRoles(Role[]) +
    +
    +UserService.addNewRole(String) +
    +
    + - Use UserService.createNewRole(String) and UserService.saveRole(Role) +
    +
    +
  • +
  • +

    + Removed methods: +

    +
    +
    DocumentService.createAndSaveNewTextDocument(Document)
    +
    + - Use DocumentService.createNewTextDocument() and DocumentService.saveChanges(Document) +
    +
    DocumentService.createAndSaveNewUrlDocument(Document)
    +
    + - Use DocumentService.createNewUrlDocument() and DocumentService.saveChanges(Document) +
    +
    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Unit tests are now enabled in the build by default. + + (Issue 2664) +

    +
  • +
  • + +

    + Target "copy-web" in an addon build.xml is now run when running the "web"-target in the main build.xml. + + (Issue 2674) +

    +
  • +
  • + +

    + Use jsp for "edit text" page. + + (Issue 2549) +

    +
  • +
  • + +

    + Added a unique index on column "login_name" in table "users". + + (Issue 2663) +

    +
  • +
  • + +

    + Compileable with java 1.5. + + (Issue 2687) +

    +
  • +
  • + +

    + Updated jars to the latest versions, and made sure all have understandable names with version numbers. + + (Issue 2686) +

    +
  • +
  • + +

    + Getting the size of an image was very slow. + + (Issue 2685) +

    +
  • +
  • +

    + The column "role_id" in the table "roles" is now an identity column, and "role_name" is varchar(60). +

    +
  • +
  • + +

    + Don't update menus in database if they don't differ from the cache when saving a text-document. + + (Issue 2672) +

    +
  • +
  • + +

    + Fixed a problem where clones of users would share the same set of roles. + + (Issue 2701) +

    +
  • +
  • + +

    + Added possibility to set permissions for roles. + + (Issue 2705) +

    +
  • +
  • + +

    + Fixed hardcoded urls to the documentation site in the default template. + + (Issue 2718) +

    +
  • +
  • + +

    + Removed table "roles_permissions", no longer needed. + + (Issue 2705) +

    +
  • +
  • + +

    + All users are now always considered to have the "Users" role regardless of what the database says. + + (Issue 2770) +

    +
  • +
  • + +

    + Made an ant-target "distcheck" for verifying that the source distribution is buildable. + + (Issue 2774) +

    +
  • +
  • + +

    + Made it easier to build with LDAP enabled + + (Issue 2818) +

    +
  • +
  • + +

    + Texts are doubly indexed: With and without HTML-tags. + + (Issue 2775) +

    +
  • +
  • + +

    + Introduced the concept of LifeCyclePhase for a DocumentDomainObject (indexed as "phase"), + corresponding to what users think of as "status". + + (Issue 2855) +

    +
  • +
  • + +

    + A group can now be used as the to-address of e-mails. + + (Issue 2798) +

    +
  • +
  • + +

    + The changelog (previously CHANGES.TXT, now CHANGES.HTML) + is now generated from an xml-file using an xsl-stylesheet. + + (Issue 2765) +

    +
  • +
+

+ Changes in version 1.11.1

+

Of + interest + to + administrators

+
    +
  • + +

    + In the fix to bug 2452 in 1.11.0, we changed the way files in file documents are saved to disk, forgetting backwards-compatibility. Administrators had to remove the "_se"-suffix from all files under "WEB-INF/uploads", or the files would not be found after an upgrade. This was fixed so the "_se" suffix is recognized again, and will be automatically removed when the file document is saved. Removing the suffix from the files on upgrade is still recommended. + + (Issue 2452, Issue 2650) +

    +
  • +
  • + +

    + On a related note, don't show "WEB-INF/uploads" in "FileAdmin" by default. + + (Issue 2640) +

    +
  • +
  • + +

    + Made "/RD/*"-paths (as seen in the log) work again. + + (Issue 2633) +

    +
  • +
+

+ Changes in version 1.11.0

+

Of + importance + to + administrators

+
    +
  • + +

    + The "SelectMethod" in the JdbcUrl in "server.properties" MUST be set to "SelectMethod=cursor", otherwise you will get the error "Can't start a cloned connection while in manual transaction mode." when you try to save a document. This is due to the new transaction code. The default used to be "SelectMethod=direct". + + (Issue 2569) +

    +
  • +
+

Of + interest + to + users

+
    +
  • + +

    + Made it possible to upload several files in one filedocument. + + (Issue 2452) +

    +
  • +
  • + +

    + Fixed a race condition that could cause menus to be cleared when editing a text-document. + + (Issue 2569) +

    +
  • +
  • + +

    + File-extension "xls" on uploaded files is now recognized as a Microsoft Excel Spreadsheet. + + (Issue 2534) +

    +
  • +
  • + +

    + Fixed a problem with viewing uploaded PDF files with Adobe Acrobat 6.0.1. + + (Issue 2511) +

    +
  • +
  • + +

    + Fixed exception when trying to create an HTML-document. + + (Issue 2543) +

    +
  • +
  • + +

    + Changed some swedish names for different document types. + + (Issue 1496) +

    +
  • +
  • + +

    + Some form elements looked strange in "page info" in Internet Explorer 5.2 on Macintosh. + + (Issue 2391) +

    +
  • +
  • + +

    + Fixed a bug that made it hard to remove images. + + (Issue 2567) +

    +
  • +
  • + +

    + Show file-size on file-document-files and images. + + (Issue 2520) +

    +
  • +
  • + +

    + Distinguish directories in "FileAdmin" with gray background color, sort files and directories in alphabetical order, and make file-sizes more readable. + + (Issue 2572) +

    +
  • +
  • + +

    + Fixed a bug making it impossible to delete a text-document with more than one menu. + + (Issue 2585) +

    +
  • +
  • + +

    + HTML is now removed from text-fields before indexing, so a search for "foo bar" will now also find "<em>foo</em> bar". + + (Issue 2593) +

    +
  • +
  • + +

    + Changed swedish name of text-document, "Ny sida" to "Textsida". + + (Issue 1496) +

    +
  • +
  • + +

    + Image-preview in old image archive was broken. + + (Issue 2628) +

    +
  • +
  • + +

    + Submitting the form several times (i.e. by double-clicking) when creating a new document no longer results in an error message and several documents created. + + (Issue 2607) +

    +
  • +
+

Of + interest + to + template creators

+
    +
  • + +

    + Put the imCMS-commercial html-comment (imcms_message.html) before the <html>-tag instead of the before doctype declaration. + + (Issue 2623) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + Disallow editing of user "user". + + (Issue 2479) +

    +
  • +
  • + +

    + Fixed a bug that made it impossible to create a category. + + (Issue 2514) +

    +
  • +
  • + +

    + Fixed a bug that prevented changing a category-type from multi-choice to single-choice. + + (Issue 2515) +

    +
  • +
  • + +

    + Database connections are now tested before use. This allows imCMS to survive database server restarts. + + (Issue 2144) +

    +
  • +
  • + +

    + "IndexingSchedulePeriodInMinutes" in "server.properties" now controls the time period between reindexings in minutes. + + (Issue 2614) +

    +
  • +
  • + +

    + Reindexing is no longer performed on startup unless needed. + + (Issue 2625) +

    +
  • +
  • + +

    + Added a little note about running SQL-scripts to INSTALL.TXT. + + (Issue 2484) +

    +
  • +
  • + +

    + The admin button is now visible for users with role "Useradmin" again. + + (Issue 2629) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • +

    + Category now implements Comparable. Compares by name, ignoring case. +

    +
  • +
  • + +

    + UserService.getUser(String) no longer requires superadmin permissions. + + (Issue 2527) +

    +
  • +
  • + +

    + Added classes: + - MailService - provides methods for sending e-mail. + - Mail - represents a mail to be sent with MailService. Uses javax.activation.DataSource for attachments. + - MailException - thrown by MailService. + - FileDocument - represents a filedocument + - FileDocument.FileDocumentFile - represents a single file in a filedocument. Implements javax.activation.DataSource. + + (Issue 2490, Issue 2490, Issue 2551, Issue 2551, Issue 2551) +

    +
  • +
  • + +

    + Added methods: + - ContentManagementSystem.getMailService() - + - DocumentService.createNewFileDocument() - + - DocumentService.getXmlDomForDocument() - returns an org.w3c.dom.Document representing a document. Currently only works with text-documents. + - Image.getSrc(String contextPath) - returns image-src with contextPath prepended. + - Image.getSrcRelativeToContextPath() - returns image-src without contextPath prepended. + - Image.getSize() - returns the size of the image in bytes. + - User.getId() - returns the user id. + - User.isDefaultUser() - returns true if the user is the default user ("user/user"). + - DocumentPermissionSet.getEditMenusPermission() - returns true if this permission-set allows editing of menus. + - DocumentPermissionSet.setEditMenusPermission(boolean) - sets whether this permission-set allows editing of menus. + + (Issue 2490, Issue 2491, Issue 2491, Issue 2491, Issue 2551, Issue 2551, Issue 2609, Issue 2609, Issue 2616, Issue 2616) +

    +
  • +
  • + +

    + Removed methods: + - Image.getSrc() - use Image.getSrc(String contextPath) or Image.getSrcRelativeToContextPath() + - Image.getSrcUrl() - use Image.getSrc(String contextPath) or Image.getSrcRelativeToContextPath() This was necessary to completely remove imCMS dependence on a specific context path. + + (Issue 2491, Issue 2491) +

    +
  • +
  • +

    + Removed deprecated fields: + - Document.Comparator.ACTIVATED_DATETIME - use Document.Comparator.PUBLICATION_START_DATETIME +

    +
  • +
  • + +

    + Removed deprecated methods + - Document.setModifiedDateTime(Date) - use Document.setModifiedDatetime(Date) + - Document.getModifiedDateTime() - use Document.getModifiedDatetime() + - Document.getCreatedDateTime() - use Document.getCreatedDatetime() + - TextDocument.getMenuSortOrder() - use Menu.getSortOrder() + - TextDocument.setMenuSortOrder(int) - use Menu.setSortOrder(int) + - DocumentPermissionSet.getEditHeadlinePermission() - use DocumentPermissionSet.getEditDocumentInformationPermission() + - DocumentPermissionSet.setEditHeadlinePermission(boolean) - use DocumentPermissionSet.setEditDocumentInformationPermission(boolean) + - DocumentPermissionSet.getEditableMenuDocumentTypeNames() - removed, returning type-names is broken. + + (Issue 2560, Issue 2560, Issue 2609, Issue 2609, Issue 2609) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + The document-deletion procedure is now run in an transaction. + + (Issue 2495) +

    +
  • +
  • + +

    + It's now possible to send attachments with mails. This uses the Java Activation Framework (javax.activation) and JavaMail API implementations from the GNU classpathx project. + + (Issue 2542) +

    +
  • +
  • + +

    + Replaced imCMS own image-parsing routines with javax.imageio.ImageIO + + (Issue 2493) +

    +
  • +
  • + +

    + Started to change the database API to allow for transactions. + + (Issue 2569) +

    +
  • +
  • + +

    + Text document menus are now saved inside a transaction. + + (Issue 2569) +

    +
  • +
+

+ Changes in version 1.10.3

+

Of + interest + to + site developers

+
    +
  • +

    + Added constants for use in search-strings: + - TextDocument.TYPE_ID + - UrlDocument.TYPE_ID +

    +
  • +
  • + +

    + Added methods: + - boolean User.isSuperAdmin() + - boolean User.canEdit(Document) + - String[] User.getRoleNames() + - DocumentService.createNewTextDocument(Document) + - DocumentService.createNewUrlDocument(Document) + + (Issue 2521, Issue 2521) +

    +
  • +
  • +

    + Deprecated methods: + - DocumentService.createAndSaveNewTextDocument(Document) + - DocumentService.createAndSaveNewUrlDocument(Document) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + The ldap implementation should no longer be dependent on Microsoft Active Directory. Rewrote a big part of the ldap-configuration in "server.properties": + - "LdapUserName" is replaced by "LdapBindDn", + - "LdapUserObjectClass" is set to "inetOrgPerson" by default. + - "LdapUserIdentifyingAttribute" is replaced by "LdapUserAttribute.LoginName" which is only required if not using 'uid' in the "inetOrgPerson" objectclass. Ldap-attributes can now be arbitrarily mapped to user-properties. See the comments in "server.properties" for details. + + (Issue 1981, Issue 2516) +

    +
  • +
  • + +

    + Fixed a bug where removing a single phone number from a user had no effect. + + (Issue 2471) +

    +
  • +
  • + +

    + Use dos-style line-endings in the text-files in the zip file, and unix-style line-endings in the tarball. + + (Issue 2485) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Instead of empty strings, use "localhost" for default database-host and "imcms" for default database-name. + + (Issue 2488) +

    +
  • +
+

+ Changes in version 1.10.2

+

Of + interest + to + site developers

+
    +
  • + +

    + Added method Image.isEmpty() to determine whether an image is empty or not. + + (Issue 2344) +

    +
  • +
  • + +

    + Image.getWidth() and Image.getHeight() now return the actual size of the image as it will be displayed, instead of 0, unless the actual size couldn't be determined. + + (Issue 2475) +

    +
  • +
  • + +

    + Fixed a bug which caused includes to be done with the included document in adminmode. + + (Issue 2449) +

    +
  • +
  • + +

    + Image-tags containing filedocument-images are hidden from users without permissions to the filedocument. + + (Issue 2454) +

    +
  • +
  • + +

    + Fixed a mistake which prevented the imCMS-advertisement in "imcms_message.html" from being output at the beginning of every page. + + (Issue 2445) +

    +
  • +
  • + +

    + Allow files with extensions "jsp" and "js" to be edited in the file administrator ("FileAdmin"). + + (Issue 2406) +

    +
  • +
  • + +

    + Build a zip file/tarball so people don't have to download more than one file. + + (Issue 2460) +

    +
  • +
  • + +

    + Fixed a number of problems with the conference login. + + (Issue 2419) +

    +
  • +
  • + +

    + Fixed a bug with the linkeditor in browsers other than Internet Explorer. + + (Issue 2462) +

    +
  • +
  • + +

    + Made the html-editor optional through the use of a cookie. + + (Issue 2327) +

    +
  • +
  • + +

    + Fixed a bug with creating external links in the html-editor. + + (Issue 2418) +

    +
  • +
  • +

    + Fixed a couple of bugs related to creating new conferences and new conference-users. +

    +
  • +
  • + +

    + Made listing many users somewhat quicker. + + (Issue 2316) +

    +
  • +
+

+ Changes in version 1.10.1

+

Of + interest + to +

+
    +
  • + +

    + Fixed exception and possible menu-deletion when trying to readd an already existing document to a menu sorted by "manual" order. + + (Issue 2443) +

    +
  • +
  • +

    + Included both english and swedish sql scripts in the distribution. +

    +
  • +
+

+ Changes in version 1.10.0

+

Of + interest + to + users

+
    +
  • + +

    + Filedocuments of types "png", "gif", or "jpeg" can now be used as images. + + (Issue 2128) +

    +
  • +
  • + +

    + Completely redid the image-selecting interface to allow for the new filedocuments-as-images paradigm. + + (Issue 2128) +

    +
  • +
  • + +

    + Replaced dropdown for selecting document publisher with a user-select dialog, and made the document creator settable in the same manner. + + (Issue 2149) +

    +
  • +
  • + +

    + Allow filedocument filenames of up to 255 characters, truncating somewhat intelligently if needed. + + (Issue 2088) +

    +
  • +
  • + +

    + Only show links to documents which the user has at least read permission on, or which are visible to non-authorized users. + + (Issue 2387) +

    +
  • +
  • + +

    + Fixed exception when adding documents to a menu sorted by "manual" order. + + (Issue 2390) +

    +
  • +
  • + +

    + Setting the modified time of a document is now possible, but it will still be updated the next time the document is modified. + + (Issue 2367) +

    +
  • +
+

Of + interest + to + template creators

+
    +
  • + +

    + The label attribute now works for the include-tag: <?imcms:include label="Include label"?> + + (Issue 1622) +

    +
  • +
  • + +

    + The outputdescription-attribute of the documentcategories tag now takes two values, "true" or "only": + - "true": <?imcms:documentcategories outputdescription="true"?> will output "categoryname - categorydescription" + - "only": <?imcms:documentcategories outputdescription="only"?> will output "categorydescription" + - Not present: <?imcms:documentcategories?> will output "categoryname". + + (Issue 2151) +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • + +

    + The file "host.properties" is gone, and everything is put in "server.properties". + + (Issue 2424) +

    +
  • +
  • + +

    + Worked a little more on indexing robustness. + + (Issue 2354) +

    +
  • +
  • + +

    + Made the indexing work at a lower priority. + + (Issue 2362) +

    +
  • +
  • + +

    + Remove documents from the index when deleted. + + (Issue 2365) +

    +
  • +
  • + +

    + Fixed a bug in the linkchecker where some broken links would be flagged as OK. + + (Issue 2336) +

    +
  • +
  • + +

    + If "SessionCookieDomain" is set in "server.properties", a second JSESSIONID cookie will be set with the given domain. + + (Issue 1886) +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • + +

    + Added methods TextDocument.getTextFields(), TextDocument.getImages(), and TextDocument.getIncludes() + + (Issue 2344) +

    +
  • +
  • + +

    + Added accessors Document.setVisibleInMenusForUnauthorizedUsers(boolean visibleInMenusForUnauthorizedUsers) and Document.isVisibleInMenusForUnauthorizedUsers() + + (Issue 2351) +

    +
  • +
  • + +

    + Added accessor Document.setCreator(User creator) + + (Issue 2388) +

    +
  • +
  • + +

    + Added method Document.getDocumentPermissionSetForUser() + + (Issue 2153) +

    +
  • +
  • + +

    + Added accessors TextDocument.Menu.getSortOrder() and TextDocument.Menu.setSortOrder(int sortOrder) + + (Issue 2438) +

    +
  • +
  • + +

    + Added method TextDocument.getMenus() + + (Issue 2438) +

    +
  • +
+

Of + interest + to + developers

+
    +
  • + +

    + Removed user-"categories". + + (Issue 2149) +

    +
  • +
  • + +

    + Refactored the code for creating and editing documents. + + (Issue 2039) +

    +
  • +
+

+ Changes in version 1.9.3

+

Of + interest + to +

+
    +
  • + +

    + Only show links to documents which the user has at least read permission on, or which are visible to non-authorized users. + + (Issue 2387) +

    +
  • +
+

+ Changes in version 1.9.2

+

Of + interest + to +

+
    +
  • + +

    + Fixed exception when adding documents to a menu sorted by "manual" order. + + (Issue 2390) +

    +
  • +
  • + +

    + Remove documents from the index when deleted. + + (Issue 2365) +

    +
  • +
+

+ Changes in version 1.9.1

+

Of + interest + to +

+
    +
  • +

    + Made the indexing a little more robust. +

    +
  • +
+

+ Changes in version 1.9.0

+

Of + interest + to + users

+
    +
  • +

    + Simple/advanced view toggle for docinfo. +

    +
  • +
  • +

    + Admin-pages will now work on non-javascript-enabled browsers. +

    +
  • +
  • +

    + All admin-pages now use the new blue/white look. +

    +
  • +
  • +

    + The link checker will now also check linked images and urls in text-fields. +

    +
  • +
  • +

    + "Administer conferences" functionality moved to "List new/updated pages". +

    +
  • +
  • +

    + The session counter now counts sessions, not logins. This means that each visitor is only counted once per browser session, instead of once when entering the site and then again when logging in. +

    +
  • +
+

Of + interest + to + template creators

+
    +
  • +

    + New template tag: <?imcms:contextpath?> will be replaced by the "context path" of the webapp. The context path is the root path to the webapp, usually the name of the webapp preceded by a slash, for example "/imcms". This is useful when one wants to construct an absolute URL. Example: <img src="<?imcms:contextpath?>/images/imCMSpower.gif" alt="Powered by imCMS"> +

    +
  • +
+

Of + interest + to + administrators

+
    +
  • +

    + The webapp should now be possible to rename without having to change any templates. +

    +
  • +
  • +

    + We now return correct HTTP status codes: 404 for "Not found", and 403 for "Forbidden/Permission denied". +

    +
  • +
  • +

    + Changed database parameters to allow for different database-drivers: The parameters "Url", "Host", "Port", "DatabaseName" in imcms/WEB-INF/conf/server.properties were replaced by the single option "JdbcUrl", which for the Microsoft JDBC driver maps to the old parameters as follows: jdbc:microsoft:sqlserver://<Host>:<Port>;DatabaseName=<DatabaseName> +

    +
  • +
  • +

    + The "MaxConnectionCount" in server.properties is ignored by the Microsoft JDBC Driver, unless one sets the driver parameter "SelectMethod" to "cursor". To do this, append ";SelectMethod=cursor" (note the semicolon) to the JdbcUrl. The default is "SelectMethod=direct", and this causes the MS JDBC driver to clone connections internally. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;313220 for more information. +

    +
  • +
  • +

    + Conference, billboard, and chat should now work on case sensitive filesystems, for example on linux. +

    +
  • +
  • +

    + Reindexing of documents is now scheduled every 24 hours from startup. Reindexing is done to a new directory, "imcms/WEB-INF/index.new", which replaces the current index "imcms/WEB-INF/index" when complete. +

    +
  • +
+

Of + interest + to + site developers

+
    +
  • +

    + Moved the apisamples from "/apisamples/" to "/imcms/docs/apisamples/". +

    +
  • +
  • +

    + DocumentService.saveChanges(Document) is now synchronized as a poor mans transaction to prevent database conflicts. +

    +
  • +
  • +

    + Added method DocumentService.getCategoryType(int categoryTypeId) +

    +
  • +
  • +

    + Added method DocumentService.createNewCategoryType(String name, int maxChoices) +

    +
  • +
  • +

    + Added method DocumentService.createNewCategory(String name, String description, String imageUrl, CategoryType categoryType) +

    +
  • +
  • +

    + Added method TemplateService.getAllTemplateGroups() +

    +
  • +
  • +

    + Added accessors Template.getId() and TemplateGroup.getId(). +

    +
  • +
  • +

    + Added convenience method DocumentService.parseLuceneSearchQuery(String) which returns a SearchQuery parsed according to Lucene syntax, see http://jakarta.apache.org/lucene/docs/queryparsersyntax.html +

    +
  • +
+

Of + interest + to + developers

+
    +
  • +

    + Cleaned up the file organization in the project. +

    +
  • +
  • +

    + Renamed all the ant-targets using more consistent names. +

    +
  • +
  • +

    + The API now has its own connection pool, so developers using the API can't accidentally starve the system of connections. +

    +
  • +
  • +

    + Jakarta Velocity (http://jakarta.apache.org/velocity/) can now be used in admintemplates and JSP-pages. +

    +
  • +
  • +

    + Searchable tokens in the index may now only consist of letters, digits, and underscores, instead of non-whitespace. This makes html index a little bit better, so that for example <b>bold</b> is indexed as two words ("b" and "bold"). +

    +
  • +
+ + diff --git a/docs/INSTALL.TXT b/docs/INSTALL.TXT index c84752ad10..004a3307ba 100644 --- a/docs/INSTALL.TXT +++ b/docs/INSTALL.TXT @@ -3,7 +3,7 @@ Installing imCMS: Prerequisites: - * Install the Java Development Kit version 1.4 or later. + * Install the Java Development Kit version 1.5 or later. * Install Apache Tomcat 4 or later, or another servlet-api 2.3 (or later) compatible servlet engine. @@ -45,6 +45,7 @@ Setting up imCMS: * Edit the file "server.properties" in the directory "tomcat/webapps/imcms/WEB-INF/conf", and set the database parameters ("JdbcDriver", "JdbcUrl", "User", "Password", "MaxConnectionCount") according to your setup. + Set "server-name" to show where imcms installed for example - "http://localhost:8080" Set "SmtpServer" to the hostname of your SMTP (outgoing mail) server. * If you want to add a file-extension to be recognized as a mime-type by imCMS, @@ -65,5 +66,11 @@ Running: * When the database setup is finished you should see the welcome page. +if you wont to use CGI service (BankID and etc) follow this steps: + 1. Run IDEA. + 2. Make key combination ALT+F12 + 3. In Opened Terminal Window write command cd %JAVA_HOME%. If nothing has happened - execute command “C:†where C – java_home parent disk name + 4. Execute command “keytool -alias {sitename} -importcert –file {pathtocertificate}/***.crt†where {pathtocertificate} – path to certificate, as file extension can by any certificate extension, {sitename} – site address, that certificating by + You're done! diff --git a/docs/_test__iso_8859-1.txt b/docs/_test__iso_8859-1.txt new file mode 100644 index 0000000000..87deefb593 --- /dev/null +++ b/docs/_test__iso_8859-1.txt @@ -0,0 +1,9 @@ +ISO 8859-1 : Lorem ipsum dolor sit amet, consectetur adipiscing eöit. Cras quis eros dolor. Mauris quis lorem a urna aliquaä dignissåm sit amet ac tårpis. Suspendisse pharetra adipiäcing neque a accumsan! +Nulåa dapibus elementum turpås, ut eleifenö nåque euismåd id. In pärttiéor libero ac quam tincidunt ac bibendum quam aliquet. Cras quam lectus, éharetra vitae imperdéet eget, aliquam vitae justo. +Suspendisse gravida feliä eu enim adiéisciög id oråaäe niöi sagittiö. + + Moäbä vitae neque eöet lacus dictum tristique. + Aliquam tempus egestas dui, et iééulis nunc pretium ac. + Phaselluå ut tortor eu ärcu pharetra öuscipié? + +Préesent eu sem nibh. diff --git a/docs/_test__utf-8.txt b/docs/_test__utf-8.txt new file mode 100644 index 0000000000..f3bcedfcf7 --- /dev/null +++ b/docs/_test__utf-8.txt @@ -0,0 +1,9 @@ +UTF-8 : Lorem ipsum dolor sit amet, consectetur adipiscing eöit. Cras quis eros dolor. Mauris quis lorem a urna aliquaä dignissÃ¥m sit amet ac tÃ¥rpis. Suspendisse pharetra adipiäcing neque a accumsan! +NulÃ¥a dapibus elementum turpÃ¥s, ut eleifenö nÃ¥que euismÃ¥d id. In pärttiéor libero ac quam tincidunt ac bibendum quam aliquet. Cras quam lectus, éharetra vitae imperdéet eget, aliquam vitae justo. +Suspendisse gravida feliä eu enim adiéisciög id orÃ¥aäe niöi sagittiö. + + Moäbä vitae neque eöet lacus dictum tristique. + Aliquam tempus egestas dui, et iééulis nunc pretium ac. + PhaselluÃ¥ ut tortor eu ärcu pharetra öuscipié? + +Préesent eu sem nibh. diff --git a/docs/html_bankid_login_cgi/images/1x1.gif b/docs/html_bankid_login_cgi/images/1x1.gif new file mode 100644 index 0000000000..1d11fa9ada Binary files /dev/null and b/docs/html_bankid_login_cgi/images/1x1.gif differ diff --git a/docs/html_bankid_login_cgi/images/arrow_right.png b/docs/html_bankid_login_cgi/images/arrow_right.png new file mode 100644 index 0000000000..c737f59cc0 Binary files /dev/null and b/docs/html_bankid_login_cgi/images/arrow_right.png differ diff --git a/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom.gif b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom.gif new file mode 100644 index 0000000000..7d2e5cee36 Binary files /dev/null and b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom.gif differ diff --git a/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom_left.gif b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom_left.gif new file mode 100644 index 0000000000..1553ee34b1 Binary files /dev/null and b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom_left.gif differ diff --git a/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom_right.gif b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom_right.gif new file mode 100644 index 0000000000..2ce42ca2ef Binary files /dev/null and b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_bottom_right.gif differ diff --git a/docs/html_bankid_login_cgi/images/imcms_admin_shadow_right.gif b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_right.gif new file mode 100644 index 0000000000..9f4b969341 Binary files /dev/null and b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_right.gif differ diff --git a/docs/html_bankid_login_cgi/images/imcms_admin_shadow_right_top.gif b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_right_top.gif new file mode 100644 index 0000000000..58c1f91a93 Binary files /dev/null and b/docs/html_bankid_login_cgi/images/imcms_admin_shadow_right_top.gif differ diff --git a/docs/html_bankid_login_cgi/images/logo_imcms_admin.gif b/docs/html_bankid_login_cgi/images/logo_imcms_admin.gif new file mode 100644 index 0000000000..23a5a1c193 Binary files /dev/null and b/docs/html_bankid_login_cgi/images/logo_imcms_admin.gif differ diff --git a/lib/commons-beanutils-1.7.0.jar b/lib/commons-beanutils-1.7.0.jar deleted file mode 100644 index b1b89c9c92..0000000000 Binary files a/lib/commons-beanutils-1.7.0.jar and /dev/null differ diff --git a/lib/commons-betwixt-0.8.jar b/lib/commons-betwixt-0.8.jar deleted file mode 100644 index ab00040b7b..0000000000 Binary files a/lib/commons-betwixt-0.8.jar and /dev/null differ diff --git a/lib/commons-collections-3.1.jar b/lib/commons-collections-3.1.jar deleted file mode 100644 index 41e230feea..0000000000 Binary files a/lib/commons-collections-3.1.jar and /dev/null differ diff --git a/lib/commons-dbcp-1.2.1.jar b/lib/commons-dbcp-1.2.1.jar deleted file mode 100644 index 08440c02e5..0000000000 Binary files a/lib/commons-dbcp-1.2.1.jar and /dev/null differ diff --git a/lib/commons-dbutils-1.0.jar b/lib/commons-dbutils-1.0.jar deleted file mode 100644 index be1a49a519..0000000000 Binary files a/lib/commons-dbutils-1.0.jar and /dev/null differ diff --git a/lib/commons-digester-1.7.jar b/lib/commons-digester-1.7.jar deleted file mode 100644 index 1783dbea23..0000000000 Binary files a/lib/commons-digester-1.7.jar and /dev/null differ diff --git a/lib/commons-email-1.0.jar b/lib/commons-email-1.0.jar deleted file mode 100644 index c19e70504b..0000000000 Binary files a/lib/commons-email-1.0.jar and /dev/null differ diff --git a/lib/commons-fileupload-1.2.jar b/lib/commons-fileupload-1.2.jar deleted file mode 100644 index 12539f5edb..0000000000 Binary files a/lib/commons-fileupload-1.2.jar and /dev/null differ diff --git a/lib/commons-httpclient-2.0.2.jar b/lib/commons-httpclient-2.0.2.jar deleted file mode 100644 index c5c52adfca..0000000000 Binary files a/lib/commons-httpclient-2.0.2.jar and /dev/null differ diff --git a/lib/commons-io-1.1.jar b/lib/commons-io-1.1.jar deleted file mode 100644 index 624fc1a724..0000000000 Binary files a/lib/commons-io-1.1.jar and /dev/null differ diff --git a/lib/commons-lang-2.1.jar b/lib/commons-lang-2.1.jar deleted file mode 100644 index 87b80ab5db..0000000000 Binary files a/lib/commons-lang-2.1.jar and /dev/null differ diff --git a/lib/commons-logging-api-1.0.5-alpha1.jar b/lib/commons-logging-api-1.0.5-alpha1.jar deleted file mode 100644 index cba5d3fe38..0000000000 Binary files a/lib/commons-logging-api-1.0.5-alpha1.jar and /dev/null differ diff --git a/lib/commons-pool-1.2.jar b/lib/commons-pool-1.2.jar deleted file mode 100644 index 4ba534c90e..0000000000 Binary files a/lib/commons-pool-1.2.jar and /dev/null differ diff --git a/lib/ddlutils-imcms-svn20060906-src.jar b/lib/ddlutils-imcms-svn20060906-src.jar deleted file mode 100644 index 5de5f94f57..0000000000 Binary files a/lib/ddlutils-imcms-svn20060906-src.jar and /dev/null differ diff --git a/lib/ddlutils-imcms-svn20060906.jar b/lib/ddlutils-imcms-svn20060906.jar deleted file mode 100644 index 5ff189ea76..0000000000 Binary files a/lib/ddlutils-imcms-svn20060906.jar and /dev/null differ diff --git a/lib/gnu-activation-1.0.jar b/lib/gnu-activation-1.0.jar deleted file mode 100644 index b1a72c1dfc..0000000000 Binary files a/lib/gnu-activation-1.0.jar and /dev/null differ diff --git a/lib/gnu-crypto-javax-security-2.0.1.jar b/lib/gnu-crypto-javax-security-2.0.1.jar deleted file mode 100644 index 2b0d549a4a..0000000000 Binary files a/lib/gnu-crypto-javax-security-2.0.1.jar and /dev/null differ diff --git a/lib/gnu-inetlib-1.1.jar b/lib/gnu-inetlib-1.1.jar deleted file mode 100644 index 89c796dd62..0000000000 Binary files a/lib/gnu-inetlib-1.1.jar and /dev/null differ diff --git a/lib/gnu-mail-1.0.jar b/lib/gnu-mail-1.0.jar deleted file mode 100644 index ae395c102e..0000000000 Binary files a/lib/gnu-mail-1.0.jar and /dev/null differ diff --git a/lib/gnu-mail-providers-1.0.jar b/lib/gnu-mail-providers-1.0.jar deleted file mode 100644 index 75d9a90643..0000000000 Binary files a/lib/gnu-mail-providers-1.0.jar and /dev/null differ diff --git a/lib/imcode-db-0.3-src.tar.gz b/lib/imcode-db-0.3-src.tar.gz deleted file mode 100644 index 94e7828faf..0000000000 Binary files a/lib/imcode-db-0.3-src.tar.gz and /dev/null differ diff --git a/lib/imcode-db-0.3.jar b/lib/imcode-db-0.3.jar deleted file mode 100644 index 09e137b321..0000000000 Binary files a/lib/imcode-db-0.3.jar and /dev/null differ diff --git a/lib/imcode-ldap-0.1-src.tar.gz b/lib/imcode-ldap-0.1-src.tar.gz deleted file mode 100644 index 46fb119dc4..0000000000 Binary files a/lib/imcode-ldap-0.1-src.tar.gz and /dev/null differ diff --git a/lib/imcode-ldap-0.1.jar b/lib/imcode-ldap-0.1.jar deleted file mode 100644 index d565290f3f..0000000000 Binary files a/lib/imcode-ldap-0.1.jar and /dev/null differ diff --git a/lib/imcode-util-2.0-src.tar.gz b/lib/imcode-util-2.0-src.tar.gz deleted file mode 100644 index 83f7498fdd..0000000000 Binary files a/lib/imcode-util-2.0-src.tar.gz and /dev/null differ diff --git a/lib/imcode-util-2.0.1.jar b/lib/imcode-util-2.0.1.jar deleted file mode 100644 index ec7bca5500..0000000000 Binary files a/lib/imcode-util-2.0.1.jar and /dev/null differ diff --git a/lib/jakarta-oro-2.0.8.jar b/lib/jakarta-oro-2.0.8.jar deleted file mode 100644 index 23488d2600..0000000000 Binary files a/lib/jakarta-oro-2.0.8.jar and /dev/null differ diff --git a/lib/jstl-1.1.2.jar b/lib/jstl-1.1.2.jar deleted file mode 100644 index a02abecc8b..0000000000 Binary files a/lib/jstl-1.1.2.jar and /dev/null differ diff --git a/lib/jtds-1.1.jar b/lib/jtds-1.1.jar deleted file mode 100644 index 41766cbf26..0000000000 Binary files a/lib/jtds-1.1.jar and /dev/null differ diff --git a/lib/log4j-1.2.12.jar b/lib/log4j-1.2.12.jar deleted file mode 100644 index 9b5a720088..0000000000 Binary files a/lib/log4j-1.2.12.jar and /dev/null differ diff --git a/lib/lucene-1.4.3.jar b/lib/lucene-1.4.3.jar deleted file mode 100644 index 58add9901b..0000000000 Binary files a/lib/lucene-1.4.3.jar and /dev/null differ diff --git a/lib/mysql-connector-java-3.1.7-bin.jar b/lib/mysql-connector-java-3.1.7-bin.jar deleted file mode 100644 index b939771131..0000000000 Binary files a/lib/mysql-connector-java-3.1.7-bin.jar and /dev/null differ diff --git a/lib/nodist/junit.jar b/lib/nodist/junit.jar deleted file mode 100644 index 674d71e89e..0000000000 Binary files a/lib/nodist/junit.jar and /dev/null differ diff --git a/lib/noinstall/ant-contrib-0.6.jar b/lib/noinstall/ant-contrib-0.6.jar deleted file mode 100644 index db90b0aae8..0000000000 Binary files a/lib/noinstall/ant-contrib-0.6.jar and /dev/null differ diff --git a/lib/noinstall/antlr-2.7.5.jar b/lib/noinstall/antlr-2.7.5.jar deleted file mode 100644 index fbe5e3cd38..0000000000 Binary files a/lib/noinstall/antlr-2.7.5.jar and /dev/null differ diff --git a/lib/noinstall/catalina-ant.jar b/lib/noinstall/catalina-ant.jar deleted file mode 100644 index bb0055926a..0000000000 Binary files a/lib/noinstall/catalina-ant.jar and /dev/null differ diff --git a/lib/noinstall/checkstyle-4.3.jar b/lib/noinstall/checkstyle-4.3.jar deleted file mode 100644 index c72639cd03..0000000000 Binary files a/lib/noinstall/checkstyle-4.3.jar and /dev/null differ diff --git a/lib/noinstall/commons-digester-1.7.jar b/lib/noinstall/commons-digester-1.7.jar deleted file mode 100644 index 1783dbea23..0000000000 Binary files a/lib/noinstall/commons-digester-1.7.jar and /dev/null differ diff --git a/lib/noinstall/commons-el-1.0.jar b/lib/noinstall/commons-el-1.0.jar deleted file mode 100644 index 608ed796ca..0000000000 Binary files a/lib/noinstall/commons-el-1.0.jar and /dev/null differ diff --git a/lib/noinstall/imcode-ant-tasks-1.3-src.tar.gz b/lib/noinstall/imcode-ant-tasks-1.3-src.tar.gz deleted file mode 100644 index 8902f7bff6..0000000000 Binary files a/lib/noinstall/imcode-ant-tasks-1.3-src.tar.gz and /dev/null differ diff --git a/lib/noinstall/imcode-ant-tasks-1.3.jar b/lib/noinstall/imcode-ant-tasks-1.3.jar deleted file mode 100644 index 4448ed9a8a..0000000000 Binary files a/lib/noinstall/imcode-ant-tasks-1.3.jar and /dev/null differ diff --git a/lib/noinstall/jakarta-regexp-1.3.jar b/lib/noinstall/jakarta-regexp-1.3.jar deleted file mode 100644 index d653a388c9..0000000000 Binary files a/lib/noinstall/jakarta-regexp-1.3.jar and /dev/null differ diff --git a/lib/noinstall/jasper-compiler-5.0.28.jar b/lib/noinstall/jasper-compiler-5.0.28.jar deleted file mode 100644 index 96ec53852d..0000000000 Binary files a/lib/noinstall/jasper-compiler-5.0.28.jar and /dev/null differ diff --git a/lib/noinstall/jasper-runtime-5.0.28.jar b/lib/noinstall/jasper-runtime-5.0.28.jar deleted file mode 100644 index 5c3b4bfff7..0000000000 Binary files a/lib/noinstall/jasper-runtime-5.0.28.jar and /dev/null differ diff --git a/lib/noinstall/jsp-api-2.0.jar b/lib/noinstall/jsp-api-2.0.jar deleted file mode 100644 index 3d0c81fef3..0000000000 Binary files a/lib/noinstall/jsp-api-2.0.jar and /dev/null differ diff --git a/lib/noinstall/servlet-api-2.4.jar b/lib/noinstall/servlet-api-2.4.jar deleted file mode 100644 index dd326d3611..0000000000 Binary files a/lib/noinstall/servlet-api-2.4.jar and /dev/null differ diff --git a/lib/pdfbox-0.7.2.jar b/lib/pdfbox-0.7.2.jar deleted file mode 100644 index 6d4b513fcc..0000000000 Binary files a/lib/pdfbox-0.7.2.jar and /dev/null differ diff --git a/lib/poi-3.0-alpha1.jar b/lib/poi-3.0-alpha1.jar deleted file mode 100644 index 4bfbbb8667..0000000000 Binary files a/lib/poi-3.0-alpha1.jar and /dev/null differ diff --git a/lib/poi-scratchpad-3.0-alpha1.jar b/lib/poi-scratchpad-3.0-alpha1.jar deleted file mode 100644 index d266fdb474..0000000000 Binary files a/lib/poi-scratchpad-3.0-alpha1.jar and /dev/null differ diff --git a/lib/standard-1.1.2.jar b/lib/standard-1.1.2.jar deleted file mode 100644 index bc528acb94..0000000000 Binary files a/lib/standard-1.1.2.jar and /dev/null differ diff --git a/lib/velocity-1.4.jar b/lib/velocity-1.4.jar deleted file mode 100644 index 04ec9d2f85..0000000000 Binary files a/lib/velocity-1.4.jar and /dev/null differ diff --git a/pom-ant.xml b/pom-ant.xml new file mode 100644 index 0000000000..19ec686664 --- /dev/null +++ b/pom-ant.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
<database defaultIdMethod="native" name="imcms">${line.separator}
+ +
</database>${line.separator}
+
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000..e2561d4704 --- /dev/null +++ b/pom.xml @@ -0,0 +1,989 @@ + + + + + + 4.0.0 + com.imcode.imcms + imcms + war + 4.6.2-SNAPSHOT + imCMS + + + sp.rainbow.org + https://sp.rainbow.org:8443/sso/acs + + https://m00-mg-local.testidp.funktionstjanster.se/samlv2/idp/req/0/0 + /logout + ${project.build.directory}/${project.build.finalName} + + UTF-8 + UTF-8 + + 1.8 + 1.8 + true + true + + false + + + log4j2-nodebug.xml + + 1.7.36 + + + 7.5.4.v20111024 + 9090 + ${project.name} + 9696 + 0 + /${project.artifactId} + + 8.5.2 + + 8888 + /${project.artifactId} + manager + manager + + + + + debug + + -Xlint + true + log4j2-debug.xml + + + + + + + + + org.apache.logging.log4j + log4j-core + 2.17.2 + + + + org.slf4j + slf4j-reload4j + 1.7.36 + + + org.slf4j + slf4j-api + 1.7.36 + runtime + + + + commons-logging + commons-logging + 1.2 + runtime + + + + + org.apache.tika + tika-core + 2.4.1 + + + org.apache.tika + tika-parsers-standard-package + 2.4.1 + + + + commons-io + commons-io + 2.11.0 + + + + + joda-time + joda-time + 2.1 + + + + + com.google.guava + guava + 11.0.2 + + + + junit + junit + 4.9 + test + + + + xml-apis + xml-apis + 1.4.01 + + + + org.opensaml + opensaml + 2.6.4 + + + commons-logging + commons-logging + + + bcprov-jdk15on + org.bouncycastle + + + commons-codec + commons-codec + + + commons-httpclient + commons-httpclient + + + commons-lang + commons-lang + + + + + + org.projectlombok + lombok + 1.18.0 + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.14.1 + + + + com.fasterxml.jackson.core + jackson-databind + 2.14.1 + + + + + com.microsoft.azure + adal4j + 1.6.3 + + + commons-codec + commons-codec + + + org.apache.commons + commons-lang3 + + + + + + + com.nimbusds + oauth2-oidc-sdk + 5.24.2 + + + commons-collections4 + org.apache.commons + + + org.apache.commons + commons-lang3 + + + + + + + com.squareup.okhttp3 + okhttp + 3.11.0 + + + + + commons-beanutils + commons-beanutils + 1.8.3 + + + commons-logging + commons-logging + + + + + + commons-betwixt + commons-betwixt + 0.8 + + + commons-logging + commons-logging + + + commons-beanutils-core + commons-beanutils + + + + + + commons-codec + commons-codec + 1.15 + + + + commons-collections + commons-collections + 3.2.1 + + + + org.apache.commons + commons-collections4 + 4.4 + + + + org.apache.commons + commons-dbcp2 + 2.2.0 + + + commons-logging + commons-logging + + + + + + commons-dbutils + commons-dbutils + 1.7 + + + + commons-digester + commons-digester + 2.1 + + + xml-apis + xml-apis + + + commons-logging + commons-logging + + + + + + + org.apache.commons + commons-email + 1.3 + + + + + commons-validator + commons-validator + 1.4.1 + + + commons-logging + commons-logging + + + + + + commons-fileupload + commons-fileupload + 1.2.2 + + + + commons-httpclient + commons-httpclient + 3.1 + + + commons-logging + commons-logging + + + commons-codec + commons-codec + + + + + + org.apache.httpcomponents + httpclient + 4.5.2 + + + commons-logging + commons-logging + + + commons-codec + commons-codec + + + + + + org.apache.httpcomponents + httpcore + 4.4.4 + + + + net.jcip + jcip-annotations + 1.0 + + + + commons-lang + commons-lang + 2.6 + + + + org.apache.commons + commons-text + 1.10.0 + + + com.google.guava + guava + 31.1-jre + + + org.apache.commons + commons-pool2 + 2.5.0 + + + + + ddlutils-imcms + ddlutils-imcms + svn20060906 + + + + gnu-crypto-javax-security + gnu-crypto-javax-security + 2.0.1 + + + + + + + + + + org.codehaus.guessencoding + guessencoding + 1.4 + + + + + com.imcode.db + imcode-db + 0.6 + + + commons-collections4 + org.apache.commons + + + org.apache.commons + commons-lang3 + + + commons-dbutils + commons-dbutils + + + + + + com.imcode.net.ldap + imcode-ldap + 1.1-SNAPSHOT + + + + com.imcode.util + imcode-util + 2.0.4 + + + commons-io + commons-io + + + + + + + oro + oro + 2.0.8 + + + + com.googlecode.json-simple + json-simple + 1.1 + + + + com.google.code.gson + gson + 2.2 + + + + javax.servlet + jstl + 1.1.2 + + + + net.sourceforge.jtds + jtds + 1.2 + + + + org.apache.lucene + lucene-core + ${lucene.version} + + + + org.apache.lucene + lucene-queryparser + ${lucene.version} + + + + org.apache.lucene + lucene-analyzers-common + ${lucene.version} + + + + mysql + mysql-connector-java + 5.1.21 + + + + taglibs + standard + 1.1.2 + + + + velocity + velocity + 1.4 + + + velocity-dep + velocity + + + + + + javax.servlet.jsp + jsp-api + 2.0 + provided + + + + javax.servlet + servlet-api + 2.5 + provided + + + + + + ${project.artifactId} + server/src + + + + + + + + + + + + + + + + + + + + + + maven-compiler-plugin + 3.0 + + ${maven.compiler.source} + ${maven.compiler.target} + ${javac.deprecation} + ${javac.args} + + + + + maven-deploy-plugin + 2.8.2 + + + org.apache.maven.wagon + wagon-ssh + 2.10 + + + + + + + + + + + + + + maven-surefire-plugin + 2.12 + + + **/*$* + **/test/casual/* + **/test/external/* + + + + + + maven-war-plugin + 2.2 + + true + true + ${generated.webapp.dir} + + + + + maven-antrun-plugin + 1.7 + + + ant-contrib + ant-contrib + 1.0b3 + + + ant + ant + + + + + + com.imcode.ant.tasks + imcode-ant-tasks + 1.3 + + + + com.imcode.util + imcode-util + 2.0.1 + + + + + + clean-generated-webapp-dir + pre-clean + + + + + + + run + + + + + validate-build-properties + validate + + + + + + + + + + + + + + + + + + + 'build.properties.template' is newer than 'build.properties'. (See docs/BUILD.TXT + for details.) + Copy 'build.properties.template' content into 'build.properties' and edit it! + + + + + run + + + + + generate-webapp-directory-content + process-sources + + + + + + + + + + + + + + + + + run + + + + + + + maven-checkstyle-plugin + 2.9.1 + + ${basedir}/docs/checkstyle.xml + + + + + maven-javadoc-plugin + 2.8.1 + + + + + imCMS API ${project.version} + + + + + maven-source-plugin + 2.2.1 + + + attach-sources + verify + + jar-no-fork + + + + + **/Mock*.java + **/Test*.java + **/*Test.java + **/*TestCase.java + **/test/**/*.* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.2.2 + + Issue 7753: + @{project.version} + + deploy + + + + + + + + org.apache.tomcat.maven + tomcat6-maven-plugin + 2.1 + + ${generated.webapp.dir} + ${tomcat.port} + ${tomcat.contextPath} + ${tomcat.username} + ${tomcat.password} + true + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.1 + + ${generated.webapp.dir} + ${tomcat.port} + ${tomcat.contextPath} + ${tomcat.username} + ${tomcat.password} + true + + + + + + org.apache.maven.wagon + wagon-ssh-external + 2.6 + + + + + + + imcode + https://repo.imcode.com/maven2 + + + + + + imcode + https://repo.imcode.com/maven2 + + false + + + never + + + + + + + imcode + imCode Internal Repository + sftp://repo.imcode.com:2022/srv/www/repo.imcode.com/maven2 + + + + + scm:git:https://github.com/imCodePartnerAB/imcms.git + scm:git:https://github.com/imCodePartnerAB/imcms.git + + + + + diff --git a/server/src/com/imcode/imcms/addon/ui/DocumentPaging.java b/server/src/com/imcode/imcms/addon/ui/DocumentPaging.java new file mode 100644 index 0000000000..e79bbe42cb --- /dev/null +++ b/server/src/com/imcode/imcms/addon/ui/DocumentPaging.java @@ -0,0 +1,257 @@ +package com.imcode.imcms.addon.ui; + +/** + * Created by IntelliJ IDEA. + * User: Tommy Ullberg, imCode + * Mail: tommy@imcode.com + * Date: 2010-mar-31 + * Time: 15:12:27 + */ +public class DocumentPaging { + String thisPagesPath = ""; + int currentPageNumber = 0; + int docListSize = 0; + int hitsPerPage = 10; + int shortVisPagesCount = 3; + int maxVisPagesCount = 12; + String spaceBetween = ""; + String divId = ""; + String divClass = "paging"; + String textPrev = "«"; + String titlePrev = "F\u00f6reg\u00e5ende"; + String textNext = "»"; + String titleNext = "N\u00e4sta"; + + public DocumentPaging(String thisPagesPath, int currentPageNumber, int docListSize, int hitsPerPage) { + this.thisPagesPath = thisPagesPath; + this.currentPageNumber = currentPageNumber; + this.docListSize = docListSize; + this.hitsPerPage = hitsPerPage; + } + + public void setThisPagesPath(String thisPagesPath) { + this.thisPagesPath = thisPagesPath; + } + + public void setCurrentPageNumber(int currentPageNumber) { + this.currentPageNumber = currentPageNumber; + } + + public void setDocListSize(int docListSize) { + this.docListSize = docListSize; + } + + public void setHitsPerPage(int hitsPerPage) { + this.hitsPerPage = hitsPerPage; + } + + public void setShortVisPagesCount(int shortVisPagesCount) { + this.shortVisPagesCount = shortVisPagesCount; + } + + public void setMaxVisPagesCount(int maxVisPagesCount) { + this.maxVisPagesCount = maxVisPagesCount; + } + + public void setSpaceBetween(String spaceBetween) { + this.spaceBetween = spaceBetween; + } + + public void setDivId(String divId) { + this.divId = divId; + } + + public void setDivClass(String divClass) { + this.divClass = divClass; + } + + public void setTextPrev(String textPrev) { + this.textPrev = textPrev; + } + + public void setTitlePrev(String titlePrev) { + this.titlePrev = titlePrev; + } + + public void setTextNext(String textNext) { + this.textNext = textNext; + } + + public void setTitleNext(String titleNext) { + this.titleNext = titleNext; + } + + public String getPagingLinksAsHtml() { + + if (currentPageNumber < 1) { + currentPageNumber = 1; + } + int iNbrOfPages = (int) Math.ceil((double) docListSize / (double) hitsPerPage); + + //int shortVisPagesCount ; // this = N => NNN...nnnnnnnnnnn OR NNN...nnnnnnnn...NNN + int midVisPagesCount = (maxVisPagesCount - (2 * shortVisPagesCount) - 2); // // this = N => nnn...NNNNNNNN...nnn + int longVisPagesCount = (maxVisPagesCount - shortVisPagesCount - 1); // this = N => nnn...NNNNNNNNNNN OR NNNNNNNNNNN...nnn + + StringBuffer sb = new StringBuffer(); + int i; + + String debug = ""; + + // hide paging if only one page + if (iNbrOfPages >= 1) { + sb.append(""); + + /* ******************************************************************************************* + * Prev button * + ******************************************************************************************* */ + + if (currentPageNumber != 1) { + sb.append(spaceBetween + "" + textPrev + ""); + } else { + sb.append(spaceBetween + "" + textPrev + ""); + } + + /* ******************************************************************************************* + * No special paging - Less than MAX * + ******************************************************************************************* */ + + if (iNbrOfPages <= maxVisPagesCount) { + debug += "
group1"; + // numbers + for (i = 0; i < iNbrOfPages; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + ""); + } + } + + } else { + + /* ******************************************************************************************* + * 2 group paging - First - LONG FIRST + SHORT LAST * + ******************************************************************************************* */ + + if (currentPageNumber < longVisPagesCount) { + debug += "
group2"; + // numbers + for (i = 0; i < longVisPagesCount; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + ""); + } + } + + sb.append(spaceBetween + "..."); + + // numbers + for (i = iNbrOfPages - shortVisPagesCount; i < iNbrOfPages; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + ""); + } + } + + /* ******************************************************************************************* + * 2 group paging - Last - SHORT FIRST + LONG LAST * + ******************************************************************************************* */ + + } else if (currentPageNumber >= iNbrOfPages - shortVisPagesCount) { + debug += "
group3"; + // numbers + for (i = 0; i < shortVisPagesCount; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + ""); + } + } + + sb.append(spaceBetween + "..."); + + // numbers + for (i = iNbrOfPages - longVisPagesCount; i < iNbrOfPages; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + " "); + } + } + + /* ******************************************************************************************* + * 3 group paging - SHORT FIRST + MID + SHORT LAST * + ******************************************************************************************* */ + + } else { + debug += "
group4"; + // numbers + for (i = 0; i < shortVisPagesCount; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + ""); + } + } + + sb.append(spaceBetween + "..."); + + // numbers + for (i = currentPageNumber - (midVisPagesCount / 2); i < currentPageNumber + (midVisPagesCount / 2); i++) + { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + "" + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + ""); + } + } + + sb.append(spaceBetween + "..."); + + // numbers + for (i = iNbrOfPages - shortVisPagesCount; i < iNbrOfPages; i++) { + String singleDigitClass = (1 == ((i + 1) + "").length()) ? " class=\"oneDigit\"" : ""; + String singleDigitCl = (1 == ((i + 1) + "").length()) ? " oneDigit" : ""; + if (i != currentPageNumber - 1) { + sb.append(spaceBetween + " " + (i + 1) + ""); + } else { + sb.append(spaceBetween + "" + (i + 1) + " "); + } + } + + } + } + + /* ******************************************************************************************* + * Next button * + ******************************************************************************************* */ + + if (currentPageNumber < iNbrOfPages) { + sb.append(spaceBetween + "" + textNext + ""); + } else { + sb.append(spaceBetween + "" + textNext + ""); + } + //sb.append("iNbrOfPages: " + iNbrOfPages + "
currentPageNumber: " + currentPageNumber + "
debug: " + debug) ; + sb.append(""); + + // builds string + return sb.toString(); + } + return ""; + } +} diff --git a/server/src/com/imcode/imcms/api/AliasAlreadyExistsException.java b/server/src/com/imcode/imcms/api/AliasAlreadyExistsException.java index 40b403f803..43d401d6d6 100644 --- a/server/src/com/imcode/imcms/api/AliasAlreadyExistsException.java +++ b/server/src/com/imcode/imcms/api/AliasAlreadyExistsException.java @@ -1,5 +1,8 @@ package com.imcode.imcms.api; +/** + * Usually thrown when saving a {@link Document}. Signals that there's already another document in imcms with an alias that the document that's being saved has. + */ public class AliasAlreadyExistsException extends SaveException { public AliasAlreadyExistsException(Throwable cause) { super("Alias already exists.", cause); diff --git a/server/src/com/imcode/imcms/api/AlreadyExistsException.java b/server/src/com/imcode/imcms/api/AlreadyExistsException.java index 5fe1aa37fd..c0421dcebf 100644 --- a/server/src/com/imcode/imcms/api/AlreadyExistsException.java +++ b/server/src/com/imcode/imcms/api/AlreadyExistsException.java @@ -1,11 +1,13 @@ package com.imcode.imcms.api; /** + * General exception produced when duplicate entries of some sort are not acceptable in the cms. + * * @since 2.0 */ public class AlreadyExistsException extends SaveException { public AlreadyExistsException(String message, Throwable cause) { - super( message, cause ); + super(message, cause); } } diff --git a/server/src/com/imcode/imcms/api/BadQueryException.java b/server/src/com/imcode/imcms/api/BadQueryException.java index 889636d018..beba96773b 100644 --- a/server/src/com/imcode/imcms/api/BadQueryException.java +++ b/server/src/com/imcode/imcms/api/BadQueryException.java @@ -6,12 +6,15 @@ */ package com.imcode.imcms.api; -import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.queryparser.classic.ParseException; +/** + * Thrown when parse errors are encountered. + */ public class BadQueryException extends Exception { - public BadQueryException( String queryString, ParseException cause ) { - super("Bad query: "+queryString,cause) ; + public BadQueryException(String queryString, ParseException cause) { + super("Bad query: " + queryString, cause); } } \ No newline at end of file diff --git a/server/src/com/imcode/imcms/api/Category.java b/server/src/com/imcode/imcms/api/Category.java index 602fd8bccc..0250c2004b 100644 --- a/server/src/com/imcode/imcms/api/Category.java +++ b/server/src/com/imcode/imcms/api/Category.java @@ -3,32 +3,56 @@ import imcode.server.document.CategoryDomainObject; /** + * Represents a category in imcms. + * * @author kreiger */ public class Category implements Comparable { - private final CategoryDomainObject internalCategory ; + private final CategoryDomainObject internalCategory; - public Category( String name, CategoryType categoryType ) { - this.internalCategory = new CategoryDomainObject( 0, name, "","", categoryType.getInternal() ); + /** + * Constructs a Category from the given name and {@link CategoryType} + * + * @param name a String with name for this category + * @param categoryType a {@link CategoryType} + */ + public Category(String name, CategoryType categoryType) { + this.internalCategory = new CategoryDomainObject(0, name, "", "", categoryType.getInternal()); } - Category( CategoryDomainObject internalCategory ) { - this.internalCategory = internalCategory ; + Category(CategoryDomainObject internalCategory) { + this.internalCategory = internalCategory; } CategoryDomainObject getInternal() { - return internalCategory ; + return internalCategory; } + /** + * Returns this category's name + * + * @return a string with this category's name + */ public String getName() { - return internalCategory.getName() ; + return internalCategory.getName(); } + /** + * Sets this category's name + * + * @param name name for this category + */ public void setName(String name) { - internalCategory.setName( name ); + internalCategory.setName(name); } + /** + * Compares the specified object with this category for equality. + * + * @param o the object to be compared for equality with this category + * @return true if the specified object is a Category and it's id is the same as this category's id, false otherwise + */ public boolean equals(Object o) { if (this == o) { return true; @@ -43,35 +67,79 @@ public boolean equals(Object o) { } + /** + * Returns this category's hashcode + * + * @return hash code value in the form of this category's id + */ public int hashCode() { return internalCategory.hashCode(); } + /** + * Returns string representation of this category in the form + * of {@link com.imcode.imcms.api.CategoryType#getName()} + ":" + {@link com.imcode.imcms.api.Category#getName()} + * + * @return a string representation of this category + */ public String toString() { return internalCategory.toString(); } + /** + * Returns this category's description + * + * @return this category's description or an empty string + */ public String getDescription() { - return internalCategory.getDescription() ; + return internalCategory.getDescription(); } + /** + * Sets the description of this category + * + * @param description this category's description + */ + public void setDescription(String description) { + internalCategory.setDescription(description); + } + + /** + * Returns this category's id + * + * @return this category's id + */ public int getId() { return internalCategory.getId(); } - public String getImage(){ + /** + * Get image url. The url is not used internally anywhere in the cms, just stored as string. + * + * @return image url or an empty string if it's not set + */ + public String getImage() { return internalCategory.getImageUrl(); } - public void setImage( String imageUrl ) { - internalCategory.setImageUrl( imageUrl ); - } - - public void setDescription( String description ) { - internalCategory.setDescription( description ); + /** + * Sets the image url of this category + * + * @param imageUrl url, relative or absolute + */ + public void setImage(String imageUrl) { + internalCategory.setImageUrl(imageUrl); } - public int compareTo( Object o ) { - return internalCategory.compareTo( ((Category)o).internalCategory ) ; + /** + * Compares this Category to the given Object. + * + * @param o the Object to be compared with + * @return 0 if the argument is a Category and it's name is equal ignoring case to this category's name. Value less than 0 + * if the argument's name is lexicographically greater(ignoring case) than this category's name. Value more than 0 + * if the argument's name is lexicographically less(ignoring case) than this category's name. + */ + public int compareTo(Object o) { + return internalCategory.compareTo(((Category) o).internalCategory); } } diff --git a/server/src/com/imcode/imcms/api/CategoryAlreadyExistsException.java b/server/src/com/imcode/imcms/api/CategoryAlreadyExistsException.java index d2c20adbc2..468a4cd57e 100644 --- a/server/src/com/imcode/imcms/api/CategoryAlreadyExistsException.java +++ b/server/src/com/imcode/imcms/api/CategoryAlreadyExistsException.java @@ -1,7 +1,11 @@ package com.imcode.imcms.api; +/** + * Usually thrown when saving a {@link Category}. Signals that there's already a category under it's {@link CategoryType} + * with the same name. + */ public class CategoryAlreadyExistsException extends AlreadyExistsException { - public CategoryAlreadyExistsException( String message ) { - super( message, null ); + public CategoryAlreadyExistsException(String message) { + super(message, null); } } diff --git a/server/src/com/imcode/imcms/api/CategoryType.java b/server/src/com/imcode/imcms/api/CategoryType.java index ad2c91ea11..05a6d47855 100644 --- a/server/src/com/imcode/imcms/api/CategoryType.java +++ b/server/src/com/imcode/imcms/api/CategoryType.java @@ -3,6 +3,9 @@ import imcode.server.document.CategoryTypeDomainObject; /** + * Represents a category type. Category types help distinguish between Categories with the same name. + * They also control if the categories belonging to them can be inherited or used in image archive. + * * @author kreiger */ public class CategoryType { @@ -16,19 +19,49 @@ CategoryTypeDomainObject getInternal() { return internalCategoryType; } + /** + * Returns string representation on this category type, calls {@link com.imcode.imcms.api.CategoryType#getName()} + * + * @return string representation on this category type + */ public String toString() { - return internalCategoryType.toString() ; - } + return internalCategoryType.toString(); + } + /** + * Returns category type's name + * + * @return category type's name + */ public String getName() { - return internalCategoryType.getName() ; + return internalCategoryType.getName(); } + /** + * Returns category type's id + * + * @return category type's id + */ public int getId() { return internalCategoryType.getId(); } + /** + * Indicates whether the categories of this category type are inherited by new documents when a document that + * has categories of this type is used as parent. + * + * @return true if this category type's categories are inherited, false otherwise + */ public boolean isInherited() { return internalCategoryType.isInherited(); } + + /** + * Indicates whether this category type can be used in image archive + * + * @return true if this category type can be used in image archive + */ + public boolean isImageArchive() { + return internalCategoryType.isImageArchive(); + } } diff --git a/server/src/com/imcode/imcms/api/CategoryTypeAlreadyExistsException.java b/server/src/com/imcode/imcms/api/CategoryTypeAlreadyExistsException.java index fc96cd6c68..da184105a3 100644 --- a/server/src/com/imcode/imcms/api/CategoryTypeAlreadyExistsException.java +++ b/server/src/com/imcode/imcms/api/CategoryTypeAlreadyExistsException.java @@ -1,7 +1,11 @@ package com.imcode.imcms.api; +/** + * Usually thrown when creating a {@link CategoryType}. + * Signals that the new category type's name already belongs to another category type. + */ public class CategoryTypeAlreadyExistsException extends AlreadyExistsException { - public CategoryTypeAlreadyExistsException( String message ) { - super( message, null ); + public CategoryTypeAlreadyExistsException(String message) { + super(message, null); } } diff --git a/server/src/com/imcode/imcms/api/ContentManagementSystem.java b/server/src/com/imcode/imcms/api/ContentManagementSystem.java index c8b5b6705b..23973e1489 100644 --- a/server/src/com/imcode/imcms/api/ContentManagementSystem.java +++ b/server/src/com/imcode/imcms/api/ContentManagementSystem.java @@ -4,51 +4,52 @@ import imcode.server.ImcmsServices; import imcode.server.user.UserDomainObject; import imcode.util.Utility; +import org.apache.commons.lang.StringUtils; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +/** + * Abstract class acting as a base for full ContentManagementSystem implementations. Provides methods for getting ContentManagementSystem + * for a given user, and retrieval of previously created ContentManagementSystem. + * Provides means of running {@link ContentManagementSystemRunnable} with super admin privileges + */ public abstract class ContentManagementSystem { - public abstract UserService getUserService(); - - public abstract DocumentService getDocumentService(); - - public abstract User getCurrentUser(); - - public abstract DatabaseService getDatabaseService(); - - public abstract TemplateService getTemplateService(); - - public abstract MailService getMailService() ; - - public abstract void runAsSuperadmin(ContentManagementSystemRunnable runnable) throws NoPermissionException; - /** - Get a ContentManagementSystem for the given username and password. - **/ - public static ContentManagementSystem getContentManagementSystem( String userName, String password ) { + * Get a ContentManagementSystem for the given username and password. + * + * @param userName user's login name + * @param password user's password + **/ + public static ContentManagementSystem getContentManagementSystem(String userName, String password) { ImcmsServices imcref = Imcms.getServices(); - UserDomainObject user = imcref.verifyUser( userName, password ); - return DefaultContentManagementSystem.create( imcref, user, Imcms.getApiDataSource()); + UserDomainObject user = imcref.verifyUser(userName, password); + return DefaultContentManagementSystem.create(imcref, user, Imcms.getApiDataSource()); } /** - * Try to login the current user with the given name and password. + * Attempts to login the current user with the given name and password. Returns ContentManagementSystem for that user + * if login is successful. * - * @param request - * @param username - * @param password + * @param request HttpServletRequest request + * @param response HttpServletResponse response + * @param username user's login name + * @param password user's password * @return The new ContentManagementSystem, or null if the login failed. */ - public static ContentManagementSystem login(HttpServletRequest request, String username, String password) { + public static ContentManagementSystem login(HttpServletRequest request, HttpServletResponse response, + String username, String password) { ImcmsServices services = Imcms.getServices(); UserDomainObject user = services.verifyUser(username, password); - if ( null == user || user.isDefaultUser()) { - return null ; + if (null == user || user.isDefaultUser()) { + return null; } - + + Imcms.getServices().getImcmsAuthenticatorAndUserAndRoleMapper().checkUserIpAllowed(user, request); + ContentManagementSystem cms = Utility.initRequestWithApi(request, user); if (services.getConfig().isDenyMultipleUserLogin()) { @@ -56,20 +57,79 @@ public static ContentManagementSystem login(HttpServletRequest request, String u currentUser.setSessionId(request.getSession().getId()); cms.getUserService().updateUserSession(currentUser); } - - Utility.makeUserLoggedIn(request, user); + + String rememberCd = user.getRememberCd(); + if (StringUtils.isEmpty(rememberCd)) { + cms.getUserService().updateUserRememberCd(user); + } + + Utility.makeUserLoggedIn(request, response, user); return cms; } /** + * Returns ContentManagementSystem set in the given request. + * + * @param request ServletRequest to get ContentManagementSystem from * @return The ContentManagementSystem for the request * @since 2.0 */ public static ContentManagementSystem fromRequest(ServletRequest request) { - return Utility.getContentManagementSystemFromRequest(request) ; + return Utility.getContentManagementSystemFromRequest(request); } - abstract ImcmsServices getInternal() ; + /** + * Returns {@link UserService} + * + * @return UserService + */ + public abstract UserService getUserService(); + + /** + * Returns {@link DocumentService} + * + * @return DocumentService + */ + public abstract DocumentService getDocumentService(); + + /** + * Returns current {@link User} + * + * @return current user + */ + public abstract User getCurrentUser(); + + /** + * Returns {@link DatabaseService} + * + * @return DatabaseService + */ + public abstract DatabaseService getDatabaseService(); + + /** + * Returns {@link TemplateService} + * + * @return TemplateService + */ + public abstract TemplateService getTemplateService(); + + /** + * Returns {@link MailService} + * + * @return MailService + */ + public abstract MailService getMailService(); + + /** + * Runs {@link ContentManagementSystemRunnable#runWith(ContentManagementSystem)} with passed ContentManagementSystem's + * user having super admin privileges. + * + * @param runnable class implementing ContentManagementSystemRunnable + * @throws NoPermissionException if ContentManagementSystemRunnable implementer is not signed with the key store + */ + public abstract void runAsSuperadmin(ContentManagementSystemRunnable runnable) throws NoPermissionException; + + abstract ImcmsServices getInternal(); } diff --git a/server/src/com/imcode/imcms/api/ContentManagementSystemRunnable.java b/server/src/com/imcode/imcms/api/ContentManagementSystemRunnable.java index 6b15aaf0fb..6b052fc2cf 100644 --- a/server/src/com/imcode/imcms/api/ContentManagementSystemRunnable.java +++ b/server/src/com/imcode/imcms/api/ContentManagementSystemRunnable.java @@ -1,7 +1,15 @@ package com.imcode.imcms.api; +/** + * Used with {@link ContentManagementSystem#runAsSuperadmin(ContentManagementSystemRunnable)} + */ public interface ContentManagementSystemRunnable { - void runWith(ContentManagementSystem contentManagementSystem) ; + /** + * Runs with passed {@link ContentManagementSystem} + * + * @param contentManagementSystem {@link ContentManagementSystem} + */ + void runWith(ContentManagementSystem contentManagementSystem); } \ No newline at end of file diff --git a/server/src/com/imcode/imcms/api/DatabaseService.java b/server/src/com/imcode/imcms/api/DatabaseService.java index e6f2c5968f..26dc2a521c 100644 --- a/server/src/com/imcode/imcms/api/DatabaseService.java +++ b/server/src/com/imcode/imcms/api/DatabaseService.java @@ -4,17 +4,25 @@ import java.sql.Connection; import java.sql.SQLException; +/** + * Class giving access to the database connection used by {@link ContentManagementSystem} + */ public class DatabaseService { private DataSource dataSource; + /** + * Constructs DatabaseService with the given DataSource + * + * @param dataSource DataSource to get connection from + */ public DatabaseService(DataSource dataSource) { this.dataSource = dataSource; } /** * Get a databaseconnection from the connectionpool. - * + *

* IMPORTANT: Do not forget to make sure that the connection is closed * (inside a "finally" block!), otherwise it won't be returned to the pool. * @@ -22,15 +30,15 @@ public DatabaseService(DataSource dataSource) { * @throws SQLException if there was a problem getting the connection. */ public Connection getConnection() throws SQLException { - return dataSource.getConnection() ; + return dataSource.getConnection(); } - + /** * Get the underlying DataSource. - * + * * @return a {@link DataSource}. */ public DataSource getDataSource() { - return dataSource ; + return dataSource; } } diff --git a/server/src/com/imcode/imcms/api/DefaultContentManagementSystem.java b/server/src/com/imcode/imcms/api/DefaultContentManagementSystem.java index 43127b9348..80e3ba5bd2 100644 --- a/server/src/com/imcode/imcms/api/DefaultContentManagementSystem.java +++ b/server/src/com/imcode/imcms/api/DefaultContentManagementSystem.java @@ -9,79 +9,134 @@ import javax.sql.DataSource; import java.security.KeyStore; +/** + * The default implementation of ContentManagementSystem, supporting services like {@link UserService}, {@link DocumentService}, + * {@link TemplateService}, {@link DatabaseService}, {@link MailService} + */ public class DefaultContentManagementSystem extends ContentManagementSystem implements Cloneable { + protected ImcmsServices service; + UserDomainObject currentUser; private UserService userService; private DocumentService documentService; private TemplateService templateService; private DatabaseService databaseService; private MailService mailService; - UserDomainObject currentUser; - protected ImcmsServices service; - public DefaultContentManagementSystem( ImcmsServices service, UserDomainObject accessor ) { - this.service = service ; + /** + * Constructs DefaultContentManagementSystem for the given user, does not initiallize the services like {@link UserService} etc + * + * @param service ImcmsServices + * @param accessor UserDomainObject becomes current user + */ + public DefaultContentManagementSystem(ImcmsServices service, UserDomainObject accessor) { + this.service = service; currentUser = accessor; } + /** + * Constructs DefaultContentManagementSystem and initializes services + * + * @param service ImcmsServices + * @param accessor UserDomainObject becomes current user + * @param apiDataSource DataSource to be user for {@link DatabaseService} + * @return DefaultContentManagementSystem with initialized services + */ public static DefaultContentManagementSystem create(ImcmsServices service, UserDomainObject accessor, DataSource apiDataSource) { - DefaultContentManagementSystem contentManagementSystem = new DefaultContentManagementSystem( service, accessor ); + DefaultContentManagementSystem contentManagementSystem = new DefaultContentManagementSystem(service, accessor); contentManagementSystem.init(apiDataSource); - return contentManagementSystem ; + return contentManagementSystem; } private void init(DataSource apiDataSource) { - userService = new UserService( this ); - documentService = new DocumentService( this ) ; - templateService = new TemplateService( this ); - databaseService = new DatabaseService( apiDataSource ); - mailService = new MailService(service.getSMTP()) ; + userService = new UserService(this); + documentService = new DocumentService(this); + templateService = new TemplateService(this); + databaseService = new DatabaseService(apiDataSource); + mailService = new MailService(service.getSMTP()); } protected Object clone() throws CloneNotSupportedException { - DefaultContentManagementSystem clone = (DefaultContentManagementSystem)super.clone() ; - clone.currentUser = (UserDomainObject)currentUser.clone() ; - return clone ; + DefaultContentManagementSystem clone = (DefaultContentManagementSystem) super.clone(); + clone.currentUser = (UserDomainObject) currentUser.clone(); + return clone; } - public UserService getUserService(){ + /** + * Returns {@link UserService} + * + * @return UserService + */ + public UserService getUserService() { return userService; } - public DocumentService getDocumentService(){ + /** + * Returns {@link DocumentService} + * + * @return DocumentService + */ + public DocumentService getDocumentService() { return documentService; } + /** + * Returns current {@link User} + * + * @return current user + */ public User getCurrentUser() { - return new User((UserDomainObject)currentUser.clone()) ; + return new User((UserDomainObject) currentUser.clone()); } + /** + * Returns {@link DatabaseService} + * + * @return DatabaseService + */ public DatabaseService getDatabaseService() { return databaseService; } + /** + * Returns {@link TemplateService} + * + * @return TemplateService + */ public TemplateService getTemplateService() { return templateService; } + /** + * Returns {@link MailService} + * + * @return MailService + */ public MailService getMailService() { - return mailService ; + return mailService; } ImcmsServices getInternal() { - return service ; + return service; } - public void runAsSuperadmin( ContentManagementSystemRunnable runnable ) throws NoPermissionException { + /** + * Runs {@link ContentManagementSystemRunnable#runWith(ContentManagementSystem)} with passed ContentManagementSystem's + * user having super admin privileges. + * + * @param runnable class implementing ContentManagementSystemRunnable + * @throws NoPermissionException if ContentManagementSystemRunnable implementer is not signed with the key store + */ + public void runAsSuperadmin(ContentManagementSystemRunnable runnable) throws NoPermissionException { KeyStore keyStore = service.getKeyStore(); Class clazz = runnable.getClass(); - if (!Utility.classIsSignedByCertificatesInKeyStore( clazz, keyStore )) { - throw new NoPermissionException("Class "+clazz.getName()+" is not signed by certificates in keystore.") ; + if (!Utility.classIsSignedByCertificatesInKeyStore(clazz, keyStore)) { + throw new NoPermissionException("Class " + clazz.getName() + " is not signed by certificates in keystore."); } - DefaultContentManagementSystem cms = create( service, (UserDomainObject)currentUser.clone(), Imcms.getApiDataSource()); - cms.currentUser.addRoleId( RoleId.SUPERADMIN ); - runnable.runWith( cms ); + DefaultContentManagementSystem cms = create(service, (UserDomainObject) currentUser.clone(), Imcms.getApiDataSource()); + cms.currentUser.addRoleId(RoleId.SUPERADMIN); + runnable.runWith(cms); cms.currentUser = null; } } diff --git a/server/src/com/imcode/imcms/api/Document.java b/server/src/com/imcode/imcms/api/Document.java index 26565edf35..a1502b1621 100644 --- a/server/src/com/imcode/imcms/api/Document.java +++ b/server/src/com/imcode/imcms/api/Document.java @@ -2,395 +2,703 @@ import com.imcode.util.ChainableReversibleNullComparator; import com.imcode.util.CountingIterator; -import com.imcode.imcms.mapping.CategoryMapper; import imcode.server.document.*; import imcode.server.user.RoleDomainObject; import imcode.server.user.RoleGetter; import imcode.server.user.RoleId; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.Serializable; import java.util.*; +/** + * The base class for all document types, such as {@link TextDocument}, {@link UrlDocument}, {@link FileDocument} etc. + * In charge of document information such as headline, alias, publication status. Publication, archivation and setting as + * unpublished dates. + * Assignment of {@link Category}, {@link Section} and keywords. + * Holds information about document creating and modification, the dates and {@link User}. + */ +@SuppressWarnings("unused") public class Document implements Serializable { + private static final int STATUS_NEW = 0; + private static final int STATUS_PUBLICATION_DISAPPROVED = 1; + private static final int STATUS_PUBLICATION_APPROVED = 2; + + private final static Logger log = LogManager.getLogger(Document.class.getName()); private final DocumentDomainObject internalDocument; ContentManagementSystem contentManagementSystem; - private final static Logger log = Logger.getLogger( Document.class.getName() ); - - /** @deprecated Use {@link Document.PublicationStatus#NEW} instead. */ - public static final int STATUS_NEW = 0; - /** @deprecated Use {@link Document.PublicationStatus#DISAPPROVED} instead. */ - public static final int STATUS_PUBLICATION_DISAPPROVED = 1; - /** @deprecated Use {@link Document.PublicationStatus#APPROVED} instead. */ - public static final int STATUS_PUBLICATION_APPROVED = 2; - - protected Document( DocumentDomainObject document, ContentManagementSystem contentManagementSystem ) { + protected Document(DocumentDomainObject document, ContentManagementSystem contentManagementSystem) { this.internalDocument = document; this.contentManagementSystem = contentManagementSystem; } + public ContentManagementSystem getCMS() { + return contentManagementSystem; + } + + private static Map wrapDomainObjectsInMap(Map rolesMappedToPermissionsIds) { + Map result = new HashMap<>(); + + for (Map.Entry entry : rolesMappedToPermissionsIds.entrySet()) { + result.put(new Role(entry.getKey()), new DocumentPermissionSet(entry.getValue())); + } + + return result; + } + DocumentDomainObject getInternal() { return internalDocument; } + /** + * Returns the unique identifier of this document in imcms + * + * @return int, the id of this document + */ public int getId() { return internalDocument.getId(); } /** - * @return map of roles Role -> DocumentPermissionSet instances. + * Returns a map of roles mapped to their permission set for this document. + * For example Role "Users" has a permission set of type{@link DocumentPermissionSetType#RESTRICTED_1}, and some + * privileges there. + * + * @return map of roles {@link Role} -> {@link DocumentPermissionSet} instances. */ public Map getRolesMappedToPermissions() { RoleIdToDocumentPermissionSetTypeMappings roleIdToDocumentPermissionSetTypeMappings = internalDocument.getRoleIdsMappedToDocumentPermissionSetTypes(); - Map result = new HashMap(); + Map result = new HashMap<>(); RoleIdToDocumentPermissionSetTypeMappings.Mapping[] mappings = roleIdToDocumentPermissionSetTypeMappings.getMappings(); RoleGetter roleGetter = contentManagementSystem.getInternal().getRoleGetter(); - for ( int i = 0; i < mappings.length; i++ ) { - RoleIdToDocumentPermissionSetTypeMappings.Mapping mapping = mappings[i]; + for (RoleIdToDocumentPermissionSetTypeMappings.Mapping mapping : mappings) { RoleId roleId = mapping.getRoleId(); - RoleDomainObject role = roleGetter.getRole(roleId) ; + RoleDomainObject role = roleGetter.getRole(roleId); DocumentPermissionSetTypeDomainObject documentPermissionSetType = mapping.getDocumentPermissionSetType(); - if ( DocumentPermissionSetTypeDomainObject.FULL.equals(documentPermissionSetType) ) { + if (DocumentPermissionSetTypeDomainObject.FULL.equals(documentPermissionSetType)) { result.put(role, DocumentPermissionSetDomainObject.FULL); - } else if ( DocumentPermissionSetTypeDomainObject.RESTRICTED_1.equals(documentPermissionSetType) ) { + } else if (DocumentPermissionSetTypeDomainObject.RESTRICTED_1.equals(documentPermissionSetType)) { result.put(role, internalDocument.getPermissionSets().getRestricted1()); - } else if ( DocumentPermissionSetTypeDomainObject.RESTRICTED_2.equals(documentPermissionSetType) ) { + } else if (DocumentPermissionSetTypeDomainObject.RESTRICTED_2.equals(documentPermissionSetType)) { result.put(role, internalDocument.getPermissionSets().getRestricted2()); - } else if ( DocumentPermissionSetTypeDomainObject.READ.equals(documentPermissionSetType) ) { + } else if (DocumentPermissionSetTypeDomainObject.READ.equals(documentPermissionSetType)) { result.put(role, DocumentPermissionSetDomainObject.READ); - } else if ( !DocumentPermissionSetTypeDomainObject.NONE.equals(documentPermissionSetType) ) { + } else if (!DocumentPermissionSetTypeDomainObject.NONE.equals(documentPermissionSetType)) { log.warn("A missing mapping in DocumentPermissionSetMapper"); } } - return wrapDomainObjectsInMap( result ); + return wrapDomainObjectsInMap(result); } - private static Map wrapDomainObjectsInMap( Map rolesMappedToPermissionsIds ) { - Map result = new HashMap(); - Set keys = rolesMappedToPermissionsIds.keySet(); - Iterator keyIterator = keys.iterator(); - while ( keyIterator.hasNext() ) { - RoleDomainObject role = (RoleDomainObject)keyIterator.next(); - DocumentPermissionSetDomainObject documentPermissionSetDO = (DocumentPermissionSetDomainObject)rolesMappedToPermissionsIds.get( role ); - DocumentPermissionSet documentPermissionSet = new DocumentPermissionSet( documentPermissionSetDO ); - result.put( new Role(role), documentPermissionSet ); - } - return result; - } - - /** Whether the document is archived. **/ + /** + * Tests if the document is archived. + * + * @return true if the document is archived, false otherwise. + */ public boolean isArchived() { return internalDocument.isArchived(); } - /** Whether the document is published and not archived. **/ + /** + * Tests if the document is published and not archived. + * + * @return true if the document is published and not archived, false otherwise. + */ public boolean isActive() { return internalDocument.isActive(); } - /** Whether the document is published. **/ + /** + * Tests if the document is published. + * + * @return true if the document is published, false otherwise. + */ public boolean isPublished() { return internalDocument.isPublished(); } + /** + * Tests if search is disabled for this document. + * Note that {@link DocumentService#getDocument(String)} will still find the document, + * however the {@link DocumentService#getDocuments(SearchQuery)} won't. + * + * @return true if search is disabled for this document, false otherwise. + */ public boolean isSearchDisabled() { return internalDocument.isSearchDisabled(); } + /** + * Sets whether search is disabled for this document. + * + * @param searchDisabled boolean, true to disable search, false to enable + */ public void setSearchDisabled(boolean searchDisabled) { internalDocument.setSearchDisabled(searchDisabled); } + /** + * Returns the most privileged DocumentPermissionSet of this document for current user. + * The lowest DocumentPermissionSet returned here is of type {@link DocumentPermissionSetType#NONE} + * + * @return the most privileged DocumentPermissionSet of this document for current user or {@link DocumentPermissionSetType#NONE} + */ public DocumentPermissionSet getDocumentPermissionSetForUser() { - return new DocumentPermissionSet( contentManagementSystem.getCurrentUser().getInternal().getPermissionSetFor( internalDocument ) ); + return new DocumentPermissionSet(contentManagementSystem.getCurrentUser().getInternal().getPermissionSetFor(internalDocument)); } - public boolean equals( Object o ) { - if ( this == o ) { + /** + * Checks whether this and the given Objects are the same. + * Uses id as a criteria of equality. + * + * @param o Object to compare with + * @return true if the parameter is of class Document or it's subclass and their id attributes are the same. + */ + public boolean equals(Object o) { + if (this == o) { return true; } - if ( !( o instanceof Document ) ) { + if (!(o instanceof Document)) { return false; } - final Document document = (Document)o; + final Document document = (Document) o; return internalDocument.equals(document.internalDocument); } + /** + * Returns the id of this document. + * + * @return id of this document + */ public int hashCode() { return internalDocument.hashCode(); } + /** + * Returns keywords of this document. + * + * @return a Set of keywords assigned to this document + */ public Set getKeywords() { return internalDocument.getKeywords(); } + /** + * Sets keywords for this document. + * + * @param keywords a Set of keywords for this document. + */ public void setKeywords(Set keywords) { internalDocument.setKeywords(keywords); } + /** + * Returns this document's {@link DocumentPermissionSet} of type {@link DocumentPermissionSetType#RESTRICTED_1} + * + * @return can't be null, this document's {@link DocumentPermissionSet} of type {@link DocumentPermissionSetType#RESTRICTED_1} + */ public DocumentPermissionSet getPermissionSetRestrictedOne() { - DocumentPermissionSetDomainObject restrictedOne = internalDocument.getPermissionSets().getRestricted1() ; - return new DocumentPermissionSet( restrictedOne ); + DocumentPermissionSetDomainObject restrictedOne = internalDocument.getPermissionSets().getRestricted1(); + return new DocumentPermissionSet(restrictedOne); } + /** + * Returns this document's {@link DocumentPermissionSet} of type {@link DocumentPermissionSetType#RESTRICTED_2} + * + * @return can't be null, this document's {@link DocumentPermissionSet} of type {@link DocumentPermissionSetType#RESTRICTED_2} + */ public DocumentPermissionSet getPermissionSetRestrictedTwo() { - DocumentPermissionSetDomainObject restrictedTwo = internalDocument.getPermissionSets().getRestricted2() ; - return new DocumentPermissionSet( restrictedTwo ); + DocumentPermissionSetDomainObject restrictedTwo = internalDocument.getPermissionSets().getRestricted2(); + return new DocumentPermissionSet(restrictedTwo); } + /** + * Returns this document's headline. + * + * @return headline or an empty String + */ public String getHeadline() { return internalDocument.getHeadline(); } + /** + * Sets this document's headline. + * + * @param headline new headline + */ + public void setHeadline(String headline) { + internalDocument.setHeadline(headline); + } + + /** + * Returns this document's menu text. + * + * @return menu text or an empty String + */ public String getMenuText() { return internalDocument.getMenuText(); } + /** + * Sets this document's menu text + * + * @param menuText new menu text + */ + public void setMenuText(String menuText) { + internalDocument.setMenuText(menuText); + } + + /** + * Returns this document's alias. + * + * @return this document's alias or null if doesn't exist + */ public String getAlias() { - return internalDocument.getAlias(); + return internalDocument.getAlias(); } + /** + * Sets this document's alias + * + * @param alias new alias or null to remove + */ public void setAlias(String alias) { internalDocument.setAlias(alias); } + /** + * Returns this document's alias if there's one, id otherwise. + * + * @return id or alias, if no alias then id + */ public String getName() { return internalDocument.getName(); } + /** + * Returns this document's menu image url + * + * @return this document's menu image url, or an empty String if doesn't exist + */ public String getMenuImageURL() { return internalDocument.getMenuImage(); } - public void setHeadline( String headline ) { - internalDocument.setHeadline( headline ); + /** + * Sets this document's menu image url + * + * @param imageUrl new menu image url + */ + public void setMenuImageURL(String imageUrl) { + internalDocument.setMenuImage(imageUrl); } - public void setMenuText( String menuText ) { - internalDocument.setMenuText( menuText ); + /** + * Returns the creator of this document + * + * @return User or null if doesn't exist + */ + public User getCreator() { + int creatorId = internalDocument.getCreatorId(); + return contentManagementSystem.getUserService().getUser(creatorId); } - public void setMenuImageURL( String imageUrl ) { - internalDocument.setMenuImage( imageUrl ); + /** + * Sets the creator of this document. + * + * @param creator a User to be the new creator. + */ + public void setCreator(User creator) { + internalDocument.setCreator(creator.getInternal()); } - public User getCreator() { - int creatorId = internalDocument.getCreatorId(); - return contentManagementSystem.getUserService().getUser(creatorId) ; + /** + * Returns the last user who modified this document. + * + * @return a user who modified document or null if there is no such data or user can not be found. + */ + public User getModifier() { + Integer modifierId = internalDocument.getModifierId(); + return modifierId == null ? null : contentManagementSystem.getUserService().getUser(modifierId); } - public void setCreator( User creator ) { - internalDocument.setCreator( creator.getInternal() ); + /** + * Returns the languages set for this document. + * + * @return {@link Language} set for this document + */ + public Language getLanguage() { + return Language.getLanguageByISO639_2(internalDocument.getLanguageIso639_2()); } - public Language getLanguage() { - return Language.getLanguageByISO639_2( internalDocument.getLanguageIso639_2() ); + /** + * Sets the language of this document + * + * @param language language for this document + */ + public void setLanguage(Language language) { + internalDocument.setLanguageIso639_2(language.getIsoCode639_2()); + } + + /** + * Adds a {@link Category} to this document. + * + * @param category a category to add + */ + public void addCategory(Category category) { + addCategory(category.getId()); } - public void addCategory( Category category ) { - internalDocument.addCategoryId( category.getId() ); + public void addCategory(int categoryId) { + internalDocument.addCategoryId(categoryId); + } + + /** + * Removes a {@link Category} from this document. + * + * @param category a category to remove + */ + public void removeCategory(Category category) { + removeCategory(category.getId()); } - public void removeCategory( Category category ) { - internalDocument.removeCategoryId( category.getId() ); + public void removeCategory(int categoryId) { + internalDocument.removeCategoryId(categoryId); } /** - * @return An array of Categories, an empty if no one found. + * Returns categories assigned to this document. + * + * @return An array of Categories, an empty if none assigned. */ public Category[] getCategories() { - Set categories = contentManagementSystem.getInternal().getCategoryMapper().getCategories(internalDocument.getCategoryIds()); - CategoryDomainObject[] categoryDomainObjects = (CategoryDomainObject[]) categories.toArray(new CategoryDomainObject[categories.size()]); - return getCategoryArrayFromCategoryDomainObjectArray( categoryDomainObjects ); + CategoryDomainObject[] categoryDomainObjects = contentManagementSystem.getInternal() + .getCategoryMapper() + .getCategories(internalDocument.getCategoryIds()) + .toArray(new CategoryDomainObject[0]); + + return getCategoryArrayFromCategoryDomainObjectArray(categoryDomainObjects); } - private Category[] getCategoryArrayFromCategoryDomainObjectArray( CategoryDomainObject[] categoryDomainObjects ) { + private Category[] getCategoryArrayFromCategoryDomainObjectArray(CategoryDomainObject[] categoryDomainObjects) { Category[] categories = new Category[categoryDomainObjects.length]; - for ( int i = 0; i < categories.length; i++ ) { + for (int i = 0; i < categories.length; i++) { CategoryDomainObject categoryDomainObject = categoryDomainObjects[i]; - categories[i] = new Category( categoryDomainObject ); + categories[i] = new Category(categoryDomainObject); } return categories; } /** - @param permissionSetId One of the constants in {@link DocumentPermissionSet}. - @deprecated Use {@link #setPermissionSetTypeForRole(Role, DocumentPermissionSetType)} - @since 2.0 + * @param permissionSetId One of the constants in {@link DocumentPermissionSet}. + * @since 2.0 + * @deprecated Use {@link #setPermissionSetTypeForRole(Role, DocumentPermissionSetType)} **/ - public void setPermissionSetIdForRole( Role role, int permissionSetId ) { - if ( null != role ) { + public void setPermissionSetIdForRole(Role role, int permissionSetId) { + if (null != role) { internalDocument.setDocumentPermissionSetTypeForRoleId(role.getInternal().getId(), DocumentPermissionSetTypeDomainObject.fromInt(permissionSetId)); } } /** - @since 3.0 + * Sets a {@link DocumentPermissionSetType} for a {@link Role} for this document + * + * @param role a Role + * @param documentPermissionSetType one of DocumentPermissionSetType constants + * @since 3.0 */ - public void setPermissionSetTypeForRole( Role role, DocumentPermissionSetType documentPermissionSetType ) { + public void setPermissionSetTypeForRole(Role role, DocumentPermissionSetType documentPermissionSetType) { internalDocument.setDocumentPermissionSetTypeForRoleId(role.getInternal().getId(), documentPermissionSetType.getInternal()); } /** - * @deprecated Use {@link #getPermissionSetTypeForRole(Role)} - @since 2.0 + * @since 2.0 + * @deprecated Use {@link #getPermissionSetTypeForRole(Role)} */ - public int getPermissionSetIdForRole( Role role ) { + public int getPermissionSetIdForRole(Role role) { return internalDocument.getDocumentPermissionSetTypeForRoleId(role.getInternal().getId()).getId(); } /** - @since 3.0 - */ - public DocumentPermissionSetType getPermissionSetTypeForRole( Role role ) { - return new DocumentPermissionSetType(internalDocument.getDocumentPermissionSetTypeForRoleId(role.getInternal().getId())) ; + * Returns a {@link DocumentPermissionSetType} for the given {@link Role} + * + * @return {@link DocumentPermissionSetType} for the given {@link Role} or {@link DocumentPermissionSetType#NONE} if none exist + * @since 3.0 + */ + public DocumentPermissionSetType getPermissionSetTypeForRole(Role role) { + return new DocumentPermissionSetType(internalDocument.getDocumentPermissionSetTypeForRoleId(role.getInternal().getId())); } /** - * @param categoryType + * Returns categories of the provided type assigned to this document. + * + * @param categoryType CategoryType to get categories of * @return an array of Categories, empty array if no one found. */ - public Category[] getCategoriesOfType( CategoryType categoryType ) { - CategoryMapper categoryMapper = contentManagementSystem.getInternal().getCategoryMapper(); - Set categoriesOfType = categoryMapper.getCategoriesOfType(categoryType.getInternal(), internalDocument.getCategoryIds()); - CategoryDomainObject[] categories = (CategoryDomainObject[]) categoriesOfType.toArray(new CategoryDomainObject[categoriesOfType.size()]); - return getCategoryArrayFromCategoryDomainObjectArray( categories ); + public Category[] getCategoriesOfType(CategoryType categoryType) { + CategoryDomainObject[] categories = contentManagementSystem.getInternal() + .getCategoryMapper() + .getCategoriesOfType(categoryType.getInternal(), internalDocument.getCategoryIds()) + .toArray(new CategoryDomainObject[0]); + + return getCategoryArrayFromCategoryDomainObjectArray(categories); } + /** + * Returns the publisher of this document + * + * @return publisher User, or null if none + */ public User getPublisher() { Integer publisherId = internalDocument.getPublisherId(); - if ( null != publisherId ) { - return contentManagementSystem.getUserService().getUser(publisherId.intValue()) ; - } else { - return null; - } + return (null == publisherId) ? null : contentManagementSystem.getUserService().getUser(publisherId); + } + + /** + * Sets this document's publisher + * + * @param user a {@link User} to be this document's publisher + */ + public void setPublisher(User user) { + internalDocument.setPublisher(user.getInternal()); } + /** + * Returns a String represending html link target, such as '_blank' etc. + * + * @return String representing html link target attribute + */ public String getTarget() { return internalDocument.getTarget(); } + /** + * Returns the {@link java.util.Date} this document was published or the date it will be. + * + * @return publication Date for/of this document + */ public Date getPublicationStartDatetime() { return internalDocument.getPublicationStartDatetime(); } - public void setPublicationStartDatetime( Date datetime ) { - internalDocument.setPublicationStartDatetime( datetime ); + /** + * Sets publication date for this document + * + * @param datetime new publication {@link java.util.Date} or null to remove + */ + public void setPublicationStartDatetime(Date datetime) { + internalDocument.setPublicationStartDatetime(datetime); } + /** + * Returns the archivation Date for this document. + * + * @return archivation Date or null if not set. + */ public Date getArchivedDatetime() { return internalDocument.getArchivedDatetime(); } - public void setArchivedDatetime( Date datetime ) { - internalDocument.setArchivedDatetime( datetime ); - } - - public void setPublisher( User user ) { - internalDocument.setPublisher( user.getInternal() ); + /** + * Sets archivation Date for this document. + * + * @param datetime new archivation date + */ + public void setArchivedDatetime(Date datetime) { + internalDocument.setArchivedDatetime(datetime); } /** - * @return An array of Sections, an empty array if none found. + * Returns the sections assigned to this document + * + * @return An array of {@link Section}, an empty array if none found. */ public Section[] getSections() { Set sectionIds = internalDocument.getSectionIds(); Section[] sections = new Section[sectionIds.size()]; DocumentService documentService = contentManagementSystem.getDocumentService(); - for ( CountingIterator iterator = new CountingIterator(sectionIds.iterator()); iterator.hasNext(); ) { + for (CountingIterator iterator = new CountingIterator(sectionIds.iterator()); iterator.hasNext(); ) { Integer sectionId = (Integer) iterator.next(); - sections[iterator.getCount() - 1] = documentService.getSection(sectionId.intValue()) ; + sections[iterator.getCount() - 1] = documentService.getSection(sectionId); } return sections; } - public void setSections( Section[] sections ) { + /** + * Sets sections for this document. + * + * @param sections an array of {@link Section} for this document + */ + public void setSections(Section[] sections) { Set sectionIds = new HashSet(); - for ( int i = 0; i < sections.length; i++ ) { - Section section = sections[i]; + for (Section section : sections) { int sectionId = section.getId(); - sectionIds.add(new Integer(sectionId)) ; + sectionIds.add(sectionId); } - internalDocument.setSectionIds( sectionIds ); + internalDocument.setSectionIds(sectionIds); } + /** + * Returns the last {@link java.util.Date} this document was modified. + * + * @return the last date this document was modified + */ public Date getModifiedDatetime() { return internalDocument.getModifiedDatetime(); } - public void setModifiedDatetime( Date date ) { - internalDocument.setModifiedDatetime( date ); + /** + * Sets a modification date for this document. + * + * @param date new modification date for this document + */ + public void setModifiedDatetime(Date date) { + internalDocument.setModifiedDatetime(date); } + /** + * Returns the creation date of this document. + * + * @return creation date + */ public Date getCreatedDatetime() { return internalDocument.getCreatedDatetime(); } - public void addSection( Section section ) { - internalDocument.addSectionId( section.getId() ); - } - - /** @deprecated Use {@link #setPublicationStatus} instead. */ - public void setStatus( int status ) { - internalDocument.setPublicationStatus( new PublicationStatus(status) ); - } - - public void setLanguage( Language language ) { - internalDocument.setLanguageIso639_2( language.getIsoCode639_2() ); - } - - public void setPublicationEndDatetime( Date datetime ) { - internalDocument.setPublicationEndDatetime( datetime ); + /** + * Adds a {@link Section} to this document + * + * @param section to add, can't be null + */ + public void addSection(Section section) { + internalDocument.addSectionId(section.getId()); } + /** + * Returns publication date of this document + * + * @return publication end date or null if not set + */ public Date getPublicationEndDatetime() { return internalDocument.getPublicationEndDatetime(); } - /** @deprecated Use {@link #getPublicationStatus} instead. */ + /** + * Sets publication end date for this document + * + * @param datetime publication end date + */ + public void setPublicationEndDatetime(Date datetime) { + internalDocument.setPublicationEndDatetime(datetime); + } + + /** + * @deprecated Use {@link #getPublicationStatus} instead. + */ public int getStatus() { - return internalDocument.getPublicationStatus().status ; + return internalDocument.getPublicationStatus().status; } - public void setVisibleInMenusForUnauthorizedUsers( boolean visibleInMenusForUnauthorizedUsers ) { - internalDocument.setLinkedForUnauthorizedUsers( visibleInMenusForUnauthorizedUsers ); + /** + * @deprecated Use {@link #setPublicationStatus} instead. + */ + public void setStatus(int status) { + internalDocument.setPublicationStatus(new PublicationStatus(status)); } + /** + * Tests if this document is visible in menus for anauthorized users + * + * @return document visibility in menus for unauthorized users + */ public boolean isVisibleInMenusForUnauthorizedUsers() { return internalDocument.isLinkedForUnauthorizedUsers(); } + /** + * Sets whether this document's link is visible in menus for anauthorized users + * + * @param visibleInMenusForUnauthorizedUsers true to allow unauthorized users see this document's link in menus, false not to + */ + public void setVisibleInMenusForUnauthorizedUsers(boolean visibleInMenusForUnauthorizedUsers) { + internalDocument.setLinkedForUnauthorizedUsers(visibleInMenusForUnauthorizedUsers); + } + + /** + * Tests whether other users can add this document to a menu. + * Note that if a user can edit this document, they can also add it to a menu. + * + * @return whether other users can add this document to a menu. + */ public boolean isLinkableByOtherUsers() { return internalDocument.isLinkableByOtherUsers(); } + /** + * Sets whether other users can add this document to a menu. + * Note that users that can edit this document can link it to a menu too too + * + * @param linkableByOtherUsers true to allow, false not to + */ public void setLinkableByOtherUsers(boolean linkableByOtherUsers) { internalDocument.setLinkableByOtherUsers(linkableByOtherUsers); } + /** + * Returns the {@link PublicationStatus} of this document. + * + * @return publication status of this document, defaults to {@link PublicationStatus#NEW} + */ public PublicationStatus getPublicationStatus() { return internalDocument.getPublicationStatus(); } + /** + * Sets {@link PublicationStatus} of this document. + * + * @param publicationStatus new publication status + */ public void setPublicationStatus(PublicationStatus publicationStatus) { - internalDocument.setPublicationStatus(publicationStatus) ; + internalDocument.setPublicationStatus(publicationStatus); + } + + public Map getProperties() { + return getInternal().getProperties(); + } + + public void setProperties(Map properties) { + getInternal().setProperties(properties); } /** - @since 3.0 + * Represents publication status of a {@link Document} + * + * @since 3.0 */ public static class PublicationStatus implements Serializable { + /** + * New publication status + */ public static final PublicationStatus NEW = new PublicationStatus(STATUS_NEW); + + /** + * Approved publication status + */ public static final PublicationStatus APPROVED = new PublicationStatus(STATUS_PUBLICATION_APPROVED); + + /** + * Disapproved publication status + */ public static final PublicationStatus DISAPPROVED = new PublicationStatus(STATUS_PUBLICATION_DISAPPROVED); private final int status; @@ -399,103 +707,192 @@ private PublicationStatus(int status) { this.status = status; } + public static PublicationStatus fromInt(int status) { + switch (status) { + case STATUS_NEW: + return NEW; + case STATUS_PUBLICATION_APPROVED: + return APPROVED; + case STATUS_PUBLICATION_DISAPPROVED: + return DISAPPROVED; + } + + throw new PublicationStatusNotExistException(status); + } + + /** + * Int values of this status as a string + * + * @return Int values of this status as a string + */ public String toString() { - return ""+status ; + return "" + status; } + /** + * Compares two statuses + * + * @param o Status to compare with + * @return true if this and the argument have the same status + */ public boolean equals(Object o) { - if ( this == o ) { + if (this == o) { return true; } - if ( o == null || getClass() != o.getClass() ) { + if (o == null || getClass() != o.getClass()) { return false; } - return status == ( (PublicationStatus) o ).status; + return status == ((PublicationStatus) o).status; } + /** + * Returns int value of this PublicationStatus + * + * @return status + */ public int hashCode() { return status; } + + private static class PublicationStatusNotExistException extends RuntimeException { + PublicationStatusNotExistException(int status) { + super("Publication status " + status + " not exist."); + } + } } + + /** + * Represents document's life cycle phase + * + * @see Page information + */ public static class LifeCyclePhase implements Serializable { + + /** + * New phase + */ public static final LifeCyclePhase NEW = new LifeCyclePhase(imcode.server.document.LifeCyclePhase.NEW); + + /** + * Disapproved phase + */ public static final LifeCyclePhase DISAPPROVED = new LifeCyclePhase(imcode.server.document.LifeCyclePhase.DISAPPROVED); + + /** + * Published phase + */ public static final LifeCyclePhase PUBLISHED = new LifeCyclePhase(imcode.server.document.LifeCyclePhase.PUBLISHED); + + /** + * Unpublished phase + */ public static final LifeCyclePhase UNPUBLISHED = new LifeCyclePhase(imcode.server.document.LifeCyclePhase.UNPUBLISHED); + + /** + * Archived phase + */ public static final LifeCyclePhase ARCHIVED = new LifeCyclePhase(imcode.server.document.LifeCyclePhase.ARCHIVED); + + /** + * Approved phase + */ public static final LifeCyclePhase APPROVED = new LifeCyclePhase(imcode.server.document.LifeCyclePhase.APPROVED); - private imcode.server.document.LifeCyclePhase phase ; + private imcode.server.document.LifeCyclePhase phase; - private LifeCyclePhase( imcode.server.document.LifeCyclePhase phase ) { + private LifeCyclePhase(imcode.server.document.LifeCyclePhase phase) { this.phase = phase; } + /** + * Returns string representation of this life cycle phase + * + * @return string representation in form of internal life cycle phase name, e.g. "published" + */ public String toString() { - return phase.toString() ; + return phase.toString(); } } + /** + * Abstract class in charge of {@link Document} comparison with a number of static comparators extending it for comparison by + * different document attributes. + */ public abstract static class Comparator extends ChainableReversibleNullComparator { - public int compare( Object o1, Object o2 ) { - final Document d1 = (Document)o1; - final Document d2 = (Document)o2; - try { - return compareDocuments( d1, d2 ); - } catch ( NullPointerException npe ) { - NullPointerException nullPointerException = new NullPointerException("Tried sorting on null fields! You need to call .nullsFirst() or .nullsLast() on your Comparator."); - nullPointerException.initCause(npe); - throw nullPointerException; - } - } - - protected abstract int compareDocuments( Document d1, Document d2 ); - + /** + * Document id comparator + */ public final static Comparator ID = new Comparator() { - protected int compareDocuments( Document d1, Document d2 ) { + protected int compareDocuments(Document d1, Document d2) { return d1.getId() - d2.getId(); } }; - + /** + * Case insensitive document headline comparator + */ public final static Comparator HEADLINE = new Comparator() { - protected int compareDocuments( Document d1, Document d2 ) { - return d1.getHeadline().compareToIgnoreCase( d2.getHeadline() ); + protected int compareDocuments(Document d1, Document d2) { + return d1.getHeadline().compareToIgnoreCase(d2.getHeadline()); } }; - + /** + * Creation date comparator + */ public final static Comparator CREATED_DATETIME = new Comparator() { - protected int compareDocuments( Document d1, Document d2 ) { - return d1.getCreatedDatetime().compareTo( d2.getCreatedDatetime() ); + protected int compareDocuments(Document d1, Document d2) { + return d1.getCreatedDatetime().compareTo(d2.getCreatedDatetime()); } }; - + /** + * Modification date comparator + */ public final static Comparator MODIFIED_DATETIME = new Comparator() { - protected int compareDocuments( Document d1, Document d2 ) { - return d1.getModifiedDatetime().compareTo( d2.getModifiedDatetime() ); + protected int compareDocuments(Document d1, Document d2) { + return d1.getModifiedDatetime().compareTo(d2.getModifiedDatetime()); } }; - + /** + * Publication start date comparator + */ public final static Comparator PUBLICATION_START_DATETIME = new Comparator() { - protected int compareDocuments( Document document1, Document document2 ) { - return document1.getPublicationStartDatetime().compareTo( document2.getPublicationStartDatetime() ); + protected int compareDocuments(Document document1, Document document2) { + return document1.getPublicationStartDatetime().compareTo(document2.getPublicationStartDatetime()); } }; - + /** + * Publication end date comparator + */ public final static Comparator PUBLICATION_END_DATETIME = new Comparator() { - protected int compareDocuments( Document document1, Document document2 ) { - return document1.getPublicationEndDatetime().compareTo( document2.getPublicationEndDatetime() ); + protected int compareDocuments(Document document1, Document document2) { + return document1.getPublicationEndDatetime().compareTo(document2.getPublicationEndDatetime()); } }; - + /** + * Archivation date comparator + */ public final static Comparator ARCHIVED_DATETIME = new Comparator() { - protected int compareDocuments( Document document1, Document document2 ) { - return document1.getArchivedDatetime().compareTo( document2.getArchivedDatetime() ); + protected int compareDocuments(Document document1, Document document2) { + return document1.getArchivedDatetime().compareTo(document2.getArchivedDatetime()); } }; + public int compare(Object o1, Object o2) { + final Document d1 = (Document) o1; + final Document d2 = (Document) o2; + try { + return compareDocuments(d1, d2); + } catch (NullPointerException npe) { + NullPointerException nullPointerException = new NullPointerException("Tried sorting on null fields! You need to call .nullsFirst() or .nullsLast() on your Comparator."); + nullPointerException.initCause(npe); + throw nullPointerException; + } + } + + protected abstract int compareDocuments(Document d1, Document d2); + } } diff --git a/server/src/com/imcode/imcms/api/DocumentAlreadyInMenuException.java b/server/src/com/imcode/imcms/api/DocumentAlreadyInMenuException.java index 5def3dbb3b..e5386fe293 100644 --- a/server/src/com/imcode/imcms/api/DocumentAlreadyInMenuException.java +++ b/server/src/com/imcode/imcms/api/DocumentAlreadyInMenuException.java @@ -1,12 +1,14 @@ package com.imcode.imcms.api; /** + * Not used. + * * @author kreiger */ public class DocumentAlreadyInMenuException extends Exception { - public DocumentAlreadyInMenuException( String message ) { - super(message) ; + public DocumentAlreadyInMenuException(String message) { + super(message); } } diff --git a/server/src/com/imcode/imcms/api/DocumentPermissionSet.java b/server/src/com/imcode/imcms/api/DocumentPermissionSet.java index ff6a9a4edb..2b841e18b6 100644 --- a/server/src/com/imcode/imcms/api/DocumentPermissionSet.java +++ b/server/src/com/imcode/imcms/api/DocumentPermissionSet.java @@ -10,121 +10,223 @@ import java.util.List; import java.util.Set; +/** + * Class describing which actions are allowed to be performed on a document. + */ public class DocumentPermissionSet { - /** @deprecated Use {@link DocumentPermissionSetType#FULL} */ + /** + * @deprecated Use {@link DocumentPermissionSetType#FULL} + */ public final static int FULL = DocumentPermissionSetTypeDomainObject.FULL.getId(); - /** @deprecated Use {@link DocumentPermissionSetType#RESTRICTED_1} */ + /** + * @deprecated Use {@link DocumentPermissionSetType#RESTRICTED_1} + */ public final static int RESTRICTED_1 = DocumentPermissionSetTypeDomainObject.RESTRICTED_1.getId(); - /** @deprecated Use {@link DocumentPermissionSetType#RESTRICTED_2} */ + /** + * @deprecated Use {@link DocumentPermissionSetType#RESTRICTED_2} + */ public final static int RESTRICTED_2 = DocumentPermissionSetTypeDomainObject.RESTRICTED_2.getId(); - /** @deprecated Use {@link DocumentPermissionSetType#READ} */ + /** + * @deprecated Use {@link DocumentPermissionSetType#READ} + */ public final static int READ = DocumentPermissionSetTypeDomainObject.READ.getId(); - /** @deprecated Use {@link DocumentPermissionSetType#NONE} */ + /** + * @deprecated Use {@link DocumentPermissionSetType#NONE} + */ public final static int NONE = DocumentPermissionSetTypeDomainObject.NONE.getId(); private DocumentPermissionSetDomainObject internalDocPermSet; - public DocumentPermissionSet( DocumentPermissionSetDomainObject internalDocPermSet ) { + /** + * Constructs document permission set with the given DocumentPermissionSetDomainObject or it's sub-class backing it. + * Depending on the class of internalDocPermSet backing this set some action permissions are ignored. + * Such as, TextDocumentPermissionSetDomainObject supports editing of texts, images, etc + * while plain DocumentPermissionSetDomainObject (used for url documents for example) doesn't, + * since URLDocuments don't have text, images, etc. + * + * @param internalDocPermSet DocumentPermissionSetDomainObject to be used internally + */ + public DocumentPermissionSet(DocumentPermissionSetDomainObject internalDocPermSet) { this.internalDocPermSet = internalDocPermSet; } /** - * @deprecated No replacement, don't use. Will be removed in 4.0 or later. + * @deprecated No replacement, don't use. Will be removed in 4.0 or later. */ public String getType() { return internalDocPermSet.getTypeName(); } + /** + * Returns a string representation of this permission set, consisting of DocumentPermissionSetType name and if the + * type is either {@link DocumentPermissionSetType#RESTRICTED_1} or {@link DocumentPermissionSetType#RESTRICTED_2} values of + * {@link DocumentPermissionSet#getEditDocumentInformationPermission} and {@link DocumentPermissionSet#getEditRolePermissionsPermission} + * + * @return a String representation of this DocumentPermissionSet + */ public String toString() { return internalDocPermSet.toString(); } + /** + * Returns if the permission set allows editing of document's meta data(info) + * + * @return boolean value if meta data is allowed to be edited + */ public boolean getEditDocumentInformationPermission() { return internalDocPermSet.getEditDocumentInformation(); } + /** + * Sets if the pemission set allows editing of document's meta data. + * + * @param b true to allow meta data editing, false to not to + */ + public void setEditDocumentInformationPermission(boolean b) { + internalDocPermSet.setEditDocumentInformation(b); + } + + /** + * Returns if the permission set allows editing of document's role privileges. + * + * @return boolean value if role privileges are allowed to be edited + */ public boolean getEditRolePermissionsPermission() { return internalDocPermSet.getEditPermissions(); } + /** + * Sets if the pemission set allows editing of document's role permission. + * Same as {@link DocumentPermissionSet#setEditPermissionsPermission(boolean)} + * + * @param b true to allow editing of includes, false to not to + */ + public void setEditRolePermissionsPermission(boolean b) { + internalDocPermSet.setEditPermissions(b); + } + + /** + * Returns if the permission set allows editing of text fields + * + * @return boolean value if text fields are allowed to be edited + */ public boolean getEditTextsPermission() { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - return ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).getEditTexts(); + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + return ((TextDocumentPermissionSetDomainObject) internalDocPermSet).getEditTexts(); } return false; } - public boolean getEditIncludesPermission() { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - return ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).getEditIncludes(); + /** + * Sets if the pemission set allows editing of document's texts. + * + * @param b true to allow editing of texts, false to not to + */ + public void setEditTextsPermission(boolean b) { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + ((TextDocumentPermissionSetDomainObject) internalDocPermSet).setEditTexts(b); } - return false; } - public boolean getEditPicturesPermission() { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - return ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).getEditImages(); + /** + * Returns if the permission set allows editing of includes + * + * @return boolean value if includes are allowed to be edited + */ + public boolean getEditIncludesPermission() { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + return ((TextDocumentPermissionSetDomainObject) internalDocPermSet).getEditIncludes(); } return false; } - public boolean getEditMenusPermission() { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - return ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).getEditMenus(); + /** + * Sets if the pemission set allows editing of document's includes. + * + * @param b true to allow editing of includes, false to not to + */ + public void setEditIncludesPermission(boolean b) { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + ((TextDocumentPermissionSetDomainObject) internalDocPermSet).setEditIncludes(b); } - - return false; } - public String[] getEditableTemplateGroupNames() { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - Set allowedTemplateGroupIds = ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).getAllowedTemplateGroupIds(); - List allowedTemplateGroups = Imcms.getServices().getTemplateMapper().getTemplateGroups(allowedTemplateGroupIds); - String[] templateGroupNames = new String[allowedTemplateGroupIds.size()] ; - for ( CountingIterator iterator = new CountingIterator(allowedTemplateGroups.iterator()); iterator.hasNext(); ) { - TemplateGroupDomainObject templateGroup = (TemplateGroupDomainObject) iterator.next(); - templateGroupNames[iterator.getCount()-1] = templateGroup.getName() ; - } - return templateGroupNames ; + /** + * Returns if the permission set allows editing of images + * + * @return boolean value if images are allowed to be edited + */ + public boolean getEditPicturesPermission() { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + return ((TextDocumentPermissionSetDomainObject) internalDocPermSet).getEditImages(); } - return new String[]{}; - } - - public void setEditDocumentInformationPermission( boolean b ) { - internalDocPermSet.setEditDocumentInformation( b ); + return false; } - public void setEditIncludesPermission( boolean b ) { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).setEditIncludes( b ); + /** + * Sets if the pemission set allows editing of document's includes. + * + * @param b true to allow editing of includes, false to not to + */ + public void setEditPicturesPermission(boolean b) { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + ((TextDocumentPermissionSetDomainObject) internalDocPermSet).setEditImages(b); } } - public void setEditPermissionsPermission( boolean b ) { - internalDocPermSet.setEditPermissions( b ); - } - - public void setEditPicturesPermission( boolean b ) { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).setEditImages( b ); + /** + * Returns if the permission set allows editing of menus + * + * @return boolean value if menus are allowed to be edited + */ + public boolean getEditMenusPermission() { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + return ((TextDocumentPermissionSetDomainObject) internalDocPermSet).getEditMenus(); } + + return false; } - public void setEditMenusPermission( boolean b ) { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).setEditMenus( b ); + /** + * Sets if the pemission set allows editing of document's menus. + * + * @param b true to allow editing of menus, false to not to + */ + public void setEditMenusPermission(boolean b) { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + ((TextDocumentPermissionSetDomainObject) internalDocPermSet).setEditMenus(b); } } - public void setEditTextsPermission( boolean b ) { - if ( internalDocPermSet instanceof TextDocumentPermissionSetDomainObject ) { - ( (TextDocumentPermissionSetDomainObject)internalDocPermSet ).setEditTexts( b ); + /** + * Returns the names of template groups, templates of which are allowed to be assigned to the document + * possessing this permission set. + * + * @return array of template group names. + */ + public String[] getEditableTemplateGroupNames() { + if (internalDocPermSet instanceof TextDocumentPermissionSetDomainObject) { + Set allowedTemplateGroupIds = ((TextDocumentPermissionSetDomainObject) internalDocPermSet).getAllowedTemplateGroupIds(); + List allowedTemplateGroups = Imcms.getServices().getTemplateMapper().getTemplateGroups(allowedTemplateGroupIds); + String[] templateGroupNames = new String[allowedTemplateGroupIds.size()]; + for (CountingIterator iterator = new CountingIterator(allowedTemplateGroups.iterator()); iterator.hasNext(); ) + { + TemplateGroupDomainObject templateGroup = (TemplateGroupDomainObject) iterator.next(); + templateGroupNames[iterator.getCount() - 1] = templateGroup.getName(); + } + return templateGroupNames; } + return new String[]{}; } - public void setEditRolePermissionsPermission( boolean b ) { - internalDocPermSet.setEditPermissions( b ); + /** + * Sets if the pemission set allows editing of document's role permissions. + * + * @param b true to allow editing of role permissions, false to not to + */ + public void setEditPermissionsPermission(boolean b) { + internalDocPermSet.setEditPermissions(b); } } \ No newline at end of file diff --git a/server/src/com/imcode/imcms/api/DocumentPermissionSetType.java b/server/src/com/imcode/imcms/api/DocumentPermissionSetType.java index a687048a7e..7676e33c1f 100644 --- a/server/src/com/imcode/imcms/api/DocumentPermissionSetType.java +++ b/server/src/com/imcode/imcms/api/DocumentPermissionSetType.java @@ -2,15 +2,38 @@ import imcode.server.document.DocumentPermissionSetTypeDomainObject; +/** + * Describes a type of permission set. + * Some types have a defined permisssion set, while other can have a permission set giving or not certain privileges. + */ public class DocumentPermissionSetType { + /** + * Permission set type giving full permission set + */ public final static DocumentPermissionSetType FULL = new DocumentPermissionSetType(DocumentPermissionSetTypeDomainObject.FULL); + + /** + * A permission set type which permission set can be defined. + */ public final static DocumentPermissionSetType RESTRICTED_1 = new DocumentPermissionSetType(DocumentPermissionSetTypeDomainObject.RESTRICTED_1); + + /** + * A permission set type which permission set can be defined. + */ public final static DocumentPermissionSetType RESTRICTED_2 = new DocumentPermissionSetType(DocumentPermissionSetTypeDomainObject.RESTRICTED_2); + + /** + * Permission set type giving read-only permission set + */ public final static DocumentPermissionSetType READ = new DocumentPermissionSetType(DocumentPermissionSetTypeDomainObject.READ); + + /** + * The permission set of this type doesn't allow nor editing for seeing the document. + */ public final static DocumentPermissionSetType NONE = new DocumentPermissionSetType(DocumentPermissionSetTypeDomainObject.NONE); - private final DocumentPermissionSetTypeDomainObject internal ; + private final DocumentPermissionSetTypeDomainObject internal; DocumentPermissionSetType(DocumentPermissionSetTypeDomainObject internal) { this.internal = internal; diff --git a/server/src/com/imcode/imcms/api/DocumentService.java b/server/src/com/imcode/imcms/api/DocumentService.java index 743a86ded0..a2a95be3e9 100644 --- a/server/src/com/imcode/imcms/api/DocumentService.java +++ b/server/src/com/imcode/imcms/api/DocumentService.java @@ -1,24 +1,41 @@ package com.imcode.imcms.api; +import com.imcode.imcms.mapping.AliasAlreadyExistsInternalException; import com.imcode.imcms.mapping.CategoryMapper; import com.imcode.imcms.mapping.DocumentMapper; -import com.imcode.imcms.mapping.AliasAlreadyExistsInternalException; import com.imcode.imcms.mapping.DocumentSaveException; -import imcode.server.document.*; -import imcode.server.document.index.DocumentQuery; +import imcode.server.document.CategoryDomainObject; +import imcode.server.document.CategoryTypeDomainObject; +import imcode.server.document.DocumentDomainObject; +import imcode.server.document.DocumentTypeDomainObject; +import imcode.server.document.DocumentVisitor; +import imcode.server.document.FileDocumentDomainObject; +import imcode.server.document.MaxCategoryDomainObjectsOfTypeExceededException; +import imcode.server.document.SectionDomainObject; +import imcode.server.document.UrlDocumentDomainObject; +import imcode.server.document.XmlDocumentBuilder; +import imcode.server.document.index.DocumentIndex; import imcode.server.document.textdocument.TextDocumentDomainObject; import imcode.server.user.UserDomainObject; -import java.util.List; import java.util.AbstractList; +import java.util.List; +import java.util.function.Predicate; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Sort; - +/** + * In charge of document, category type and category operations such as creation, saving, deletion and look up. + * As well as representation of imcms document in as xml document. + */ +@SuppressWarnings({"unused", "JavaDoc"}) public class DocumentService { private final ContentManagementSystem contentManagementSystem; + /** + * Returns DocumentService with the given cms + * + * @param contentManagementSystem cms used by DocumentService + */ public DocumentService(ContentManagementSystem contentManagementSystem) { this.contentManagementSystem = contentManagementSystem; } @@ -26,7 +43,7 @@ public DocumentService(ContentManagementSystem contentManagementSystem) { static Document wrapDocumentDomainObject(DocumentDomainObject document, ContentManagementSystem contentManagementSystem) { if (null == document) { - return null ; + return null; } ApiWrappingDocumentVisitor apiWrappingDocumentVisitor = new ApiWrappingDocumentVisitor(contentManagementSystem); document.accept(apiWrappingDocumentVisitor); @@ -38,17 +55,14 @@ static Document wrapDocumentDomainObject(DocumentDomainObject document, * instead. * * @param documentIdString The unique id or name of the document requested, can be either the int value also known as "meta_id" - * or the document name also known as "alias". + * or the document name also known as "alias". * @return The document The type is usually a subclass to document, if there exist one. - * @throws NoPermissionException If the current user dosen't have the rights to read this document. + * @throws NoPermissionException If the current user doesn't have the rights to read this document. */ public Document getDocument(String documentIdString) throws NoPermissionException { DocumentDomainObject doc = getDocumentMapper().getDocument(documentIdString); - Document result = null; - if ( null != doc ) { - result = wrapDocumentDomainObject(doc, contentManagementSystem); - } - return result; + + return (null == doc) ? null : wrapDocumentDomainObject(doc, contentManagementSystem); } /** @@ -57,137 +71,221 @@ public Document getDocument(String documentIdString) throws NoPermissionExceptio * * @param documentId The id number of the document requested, also sometimes known as "meta_id" * @return The document The type is usually a subclass to document, if there exist one. - * @throws NoPermissionException If the current user dosen't have the rights to read this document. + * @throws NoPermissionException If the current user doesn't have the rights to read this document. */ public Document getDocument(int documentId) throws NoPermissionException { - return getDocument(""+documentId); + return getDocument("" + documentId); } /** + * Returns TextDocument with given meta_id or alias. + * * @param documentIdString The unique id or name of the document requested, can be either the int value alsp known as "meta_id" - * or the document name also known as "alias". - * @return The document - * @throws NoPermissionException If the current user dosen't have the rights to read this document. + * or the document name also known as "alias". + * @return The document with given id or null if such doesn't exist. + * @throws NoPermissionException If the current user doesn't have the rights to read this document. */ public TextDocument getTextDocument(String documentIdString) throws NoPermissionException { return (TextDocument) getDocument(documentIdString); } /** + * Returns TextDocument with given id. + * * @param documentId The id number of the document requested, also known as "meta_id" - * @return The document - * @throws NoPermissionException If the current user dosen't have the rights to read this document. + * @return The document with given id or null if such doesn't exist. + * @throws NoPermissionException If the current user doesn't have the rights to read this document. */ public TextDocument getTextDocument(int documentId) throws NoPermissionException { - return (TextDocument) getDocument(""+documentId); + return getTextDocument(String.valueOf(documentId)); } /** + * Returns UrlDocument with given meta_id or alias. + * * @param documentIdString The unique id or name of the document requested, can be either the int value also known as "meta_id" - * or the document name also known as "alias". - * @return The document - * @throws NoPermissionException If the current user dosen't have the rights to read this document. + * or the document name also known as "alias". + * @return The document with given id or null if such doesn't exist. + * @throws NoPermissionException If the current user doesn't have the rights to read this document. */ public UrlDocument getUrlDocument(String documentIdString) throws NoPermissionException { return (UrlDocument) getDocument(documentIdString); } /** + * Returns UrlDocument with given meta_id. + * * @param documentId The id number of the document requested, also known as "meta_id" - * @return The document - * @throws NoPermissionException If the current user dosen't have the rights to read this document. + * @return The document with given id or null if such doesn't exist. + * @throws NoPermissionException If the current user doesn't have the rights to read this document. */ public UrlDocument getUrlDocument(int documentId) throws NoPermissionException { - return (UrlDocument) getDocument(documentId); + return getUrlDocument(String.valueOf(documentId)); } + /** + * Creates new TextDocument with given document acting as parent + * + * @param parent document to be used as a parent for the new document + * @return new TextDocument + * @throws NoPermissionException + */ public TextDocument createNewTextDocument(Document parent) throws NoPermissionException { return (TextDocument) createNewDocument(DocumentTypeDomainObject.TEXT_ID, parent); } + /** + * Creates new UrlDocument with given document acting as parent + * + * @param parent document to be used as a parent for the new document + * @return new UrlDocument + * @throws NoPermissionException + */ public UrlDocument createNewUrlDocument(Document parent) throws NoPermissionException { return (UrlDocument) createNewDocument(DocumentTypeDomainObject.URL_ID, parent); } + /** + * Creates new FileDocument with given document acting as parent + * + * @param parent document to be used as a parent for the new document + * @return new FileDocument + * @throws NoPermissionException + */ public FileDocument createNewFileDocument(Document parent) throws NoPermissionException { return (FileDocument) createNewDocument(DocumentTypeDomainObject.FILE_ID, parent); } + /** + * Creates new document with given parent and of specified document type(text, url or file document) + * + * @param doctype document type i.e DocumentTypeDomainObject.TEXT_ID, DocumentTypeDomainObject.URL_ID, DocumentTypeDomainObject.FILE_ID + * @param parent document to serve as new document's parent + * @return new document + * @throws NoPermissionException if current user can't create new documents + */ private Document createNewDocument(int doctype, Document parent) throws NoPermissionException { - return wrapDocumentDomainObject(getDocumentMapper().createDocumentOfTypeFromParent(doctype, parent.getInternal(), contentManagementSystem.getCurrentUser().getInternal()), contentManagementSystem); + + final DocumentDomainObject docFromParent = getDocumentMapper().createDocumentOfTypeFromParent( + doctype, parent.getInternal(), getInternalUser() + ); + + return wrapDocumentDomainObject(docFromParent, contentManagementSystem); } - /** Saves the changes to a modified document. Note that this method is synchronized. */ + /** + * Saves the changes to a modified document. Note that this method is synchronized. + * + * @param document Document to save + * @throws SaveException if the given document's alias already belongs to some other existing document. Or if the + * document was assigned more categories of type that that type's maximum category choice number allows. + * @see imcode.server.document.CategoryTypeDomainObject#getMaxChoices() + */ public synchronized void saveChanges(Document document) throws NoPermissionException, SaveException { try { - if ( 0 == document.getId() ) { - getDocumentMapper().saveNewDocument(document.getInternal(), contentManagementSystem.getCurrentUser().getInternal(), false); + final DocumentDomainObject internalDoc = document.getInternal(); + final UserDomainObject internalUser = getInternalUser(); + final DocumentMapper documentMapper = getDocumentMapper(); + + if (0 == document.getId()) { + documentMapper.saveNewDocument(internalDoc, internalUser, false); } else { - getDocumentMapper().saveDocument(document.getInternal(), contentManagementSystem.getCurrentUser().getInternal()); + documentMapper.saveDocument(internalDoc, internalUser); } - } catch ( MaxCategoryDomainObjectsOfTypeExceededException e ) { + } catch (MaxCategoryDomainObjectsOfTypeExceededException e) { throw new MaxCategoriesOfTypeExceededException(e); } catch (AliasAlreadyExistsInternalException e) { throw new AliasAlreadyExistsException(e); } catch (DocumentSaveException e) { - throw new SaveException(e) ; + throw new SaveException(e); } } + /** + * Returns a category of given category type and name + * + * @param categoryType category type to look for in + * @param categoryName category name to look category for by + * @return category, or null if given category type doesn't have category with given name + */ public Category getCategory(CategoryType categoryType, String categoryName) { - final CategoryDomainObject category = getCategoryMapper().getCategoryByTypeAndName(categoryType.getInternal(), categoryName); - if ( null != category ) { - return new Category(category); - } else { - return null; - } + + final CategoryDomainObject category = getCategoryMapper().getCategoryByTypeAndName( + categoryType.getInternal(), categoryName + ); + + return (null != category) ? new Category(category) : null; } private CategoryMapper getCategoryMapper() { return contentManagementSystem.getInternal().getCategoryMapper(); } + /** + * Returns category with given id + * + * @param categoryId category id + * @return category or null if none exist by given id + */ public Category getCategory(int categoryId) { final CategoryDomainObject category = getCategoryMapper().getCategoryById(categoryId); - if ( null != category ) { - return new Category(category); - } else { - return null; - } + return (null != category) ? new Category(category) : null; } + /** + * Returns category type with given id + * + * @param categoryTypeId category type id + * @return category type or null if none exist by given id + */ public CategoryType getCategoryType(int categoryTypeId) { final CategoryTypeDomainObject categoryType = getCategoryMapper().getCategoryTypeById(categoryTypeId); return returnCategoryTypeAPIObjectOrNull(categoryType); } + /** + * Returns category type with given name + * + * @param categoryTypeName category type name + * @return category type or null if none exist by given name + */ public CategoryType getCategoryType(String categoryTypeName) { final CategoryTypeDomainObject categoryType = getCategoryMapper().getCategoryTypeByName(categoryTypeName); return returnCategoryTypeAPIObjectOrNull(categoryType); } private CategoryType returnCategoryTypeAPIObjectOrNull(final CategoryTypeDomainObject categoryType) { - if ( null != categoryType ) { - return new CategoryType(categoryType); - } - return null; + return (null != categoryType) ? new CategoryType(categoryType) : null; } + /** + * Returns all categories of given category type + * + * @param categoryType category type whose categories to return + * @return an array of categories belonging to given category type + */ public Category[] getAllCategoriesOfType(CategoryType categoryType) { // Allow everyone to get a CategoryType. No security check. CategoryDomainObject[] categoryDomainObjects = getCategoryMapper().getAllCategoriesOfType(categoryType.getInternal()); Category[] categories = new Category[categoryDomainObjects.length]; - for ( int i = 0; i < categoryDomainObjects.length; i++ ) { + + for (int i = 0; i < categoryDomainObjects.length; i++) { CategoryDomainObject categoryDomainObject = categoryDomainObjects[i]; categories[i] = new Category(categoryDomainObject); } return categories; } + /** + * Returns all category types. + * + * @return an array of category types in the cms + */ public CategoryType[] getAllCategoryTypes() { CategoryTypeDomainObject[] categoryTypeDomainObjects = getCategoryMapper().getAllCategoryTypes(); CategoryType[] categoryTypes = new CategoryType[categoryTypeDomainObjects.length]; - for ( int i = 0; i < categoryTypeDomainObjects.length; i++ ) { + + for (int i = 0; i < categoryTypeDomainObjects.length; i++) { CategoryTypeDomainObject categoryTypeDomainObject = categoryTypeDomainObjects[i]; categoryTypes[i] = new CategoryType(categoryTypeDomainObject); } @@ -195,17 +293,18 @@ public CategoryType[] getAllCategoryTypes() { } /** - * @param name - * @param maxChoices - * @return The newly craeated category type. - * @throws NoPermissionException - * @throws CategoryTypeAlreadyExistsException + * Creates new category type with given name and maximum number of categories a document is allowed to have(of this category type) * + * @param name name of the new category type + * @param maxChoices maximum number of category choice of this category type + * @return The newly created category type. + * @throws NoPermissionException + * @throws CategoryTypeAlreadyExistsException if there's already a category type with given name */ public CategoryType createNewCategoryType(String name, int maxChoices) throws NoPermissionException, CategoryTypeAlreadyExistsException { - if ( getCategoryMapper().isUniqueCategoryTypeName(name) ) { - CategoryTypeDomainObject newCategoryTypeDO = new CategoryTypeDomainObject(0, name, maxChoices, false); + if (getCategoryMapper().isUniqueCategoryTypeName(name)) { + CategoryTypeDomainObject newCategoryTypeDO = new CategoryTypeDomainObject(0, name, maxChoices, false, false); newCategoryTypeDO = getCategoryMapper().addCategoryTypeToDb(newCategoryTypeDO); return new CategoryType(newCategoryTypeDO); } else { @@ -213,70 +312,183 @@ public CategoryType createNewCategoryType(String name, } } + /** + * Returns a section with given id + * + * @param sectionId id of a section + * @return a section with give id or null if none found + */ public Section getSection(int sectionId) { - SectionDomainObject section = getDocumentMapper().getSectionById(sectionId); - if ( null == section ) { - return null; - } - return new Section(section); + final SectionDomainObject section = getDocumentMapper().getSectionById(sectionId); + return (null == section) ? null : new Section(section); } - /** @since 2.0 */ + /** + * Returns a section with given name + * + * @param name name of a section + * @return a section with give name or null if none found + * @since 2.0 + */ public Section getSection(String name) { - SectionDomainObject section = getDocumentMapper().getSectionByName(name); - if ( null == section ) { - return null; - } - return new Section(section); + final SectionDomainObject section = getDocumentMapper().getSectionByName(name); + return (null == section) ? null : new Section(section); } - public List getDocuments(final SearchQuery query) throws SearchException { + /** + * Searches for documents using given query, takes into account current cms user + * + * @param query search query to look for documents with + * @return a list of documents found + * @throws SearchException + * @see com.imcode.imcms.api.LuceneParsedQuery + */ + public List getDocuments(final SearchQuery query) throws SearchException { try { - final List documentList = getDocumentMapper().getDocumentIndex().search(new DocumentQuery() { - public Query getQuery() { - return query.getQuery(); - } - - public Sort getSort() { - return query.getSort(); - } - - public boolean isLogged() { - return query.isLogged(); - } - }, contentManagementSystem.getCurrentUser().getInternal()); + final List documentList = getDocumentMapper() + .getDocumentIndex() + .search(query, getInternalUser()); + return new ApiDocumentWrappingList(documentList, contentManagementSystem); - } catch ( RuntimeException e ) { + + } catch (RuntimeException e) { throw new SearchException(e); } } + private UserDomainObject getInternalUser() { + return contentManagementSystem.getCurrentUser().getInternal(); + } + + public SearchResult getDocuments(final SearchQuery query, int startPosition, int maxResults) throws SearchException { + return getDocuments(query, startPosition, maxResults, null); + } + + public SearchResult getDocuments(final SearchQuery query, + int startPosition, + int maxResults, + Predicate filterPredicate) throws SearchException { + try { + final DocumentIndex documentIndex = getDocumentMapper().getDocumentIndex(); + final SearchResult searchResult; + + if (filterPredicate == null) { + searchResult = documentIndex.search(query, getInternalUser(), startPosition, maxResults); + + } else { + searchResult = documentIndex.search( + query, getInternalUser(), startPosition, maxResults, new ApiDocumentWrappingPredicate( + filterPredicate, contentManagementSystem + ) + ); + } + + return searchResult.mapResult(document -> wrapDocumentDomainObject(document, contentManagementSystem)); + + } catch (RuntimeException e) { + throw new SearchException(e); + } + } + + /** + * Searches for documents using given query, takes into account current cms user + * + * @param query search query to look for documents with + * @return an array of documents found + * @throws SearchException + * @see com.imcode.imcms.api.LuceneParsedQuery + */ public Document[] search(SearchQuery query) throws SearchException { - List documents = getDocuments(query) ; - return (Document[]) documents.toArray(new Document[documents.size()]); + return getDocuments(query).toArray(new Document[0]); } private DocumentMapper getDocumentMapper() { return contentManagementSystem.getInternal().getDocumentMapper(); } + /** + * Creates a search query + * + * @param query a string representing document search query + * @return search query + * @throws BadQueryException if something is wrong with the query, like syntax error + */ public SearchQuery parseLuceneSearchQuery(String query) throws BadQueryException { return new LuceneParsedQuery(query); } + /** + * Returns xml representation of the given document + * + * @param document a document to get xml representation of + * @return org.w3c.dom.Document of given document + */ public org.w3c.dom.Document getXmlDomForDocument(Document document) { - XmlDocumentBuilder xmlDocumentBuilder = new XmlDocumentBuilder(contentManagementSystem.getCurrentUser().getInternal()); + XmlDocumentBuilder xmlDocumentBuilder = new XmlDocumentBuilder(getInternalUser()); xmlDocumentBuilder.addDocument(document.getInternal()); return xmlDocumentBuilder.getXmlDocument(); } + /** + * Saves given category + * + * @param category category to save, be it a new one or an existing category + * @throws NoPermissionException + * @throws CategoryAlreadyExistsException if the given category is new and it's category type already contains a category with the same name + */ public void saveCategory(Category category) throws NoPermissionException, CategoryAlreadyExistsException { getCategoryMapper().saveCategory(category.getInternal()); } + /** + * Deletes document from cms + * + * @param document document to delete + * @throws NoPermissionException + */ public void deleteDocument(Document document) throws NoPermissionException { - UserDomainObject internalUser = contentManagementSystem.getCurrentUser().getInternal(); - getDocumentMapper().deleteDocument(document.getInternal(), internalUser); + getDocumentMapper().deleteDocument(document.getInternal(), getInternalUser()); + } + + /** + * Removes all image cache entries. + */ + public void clearImageCache() { + getDocumentMapper().clearImageCache(); + } + + /** + * Removes all image cache entries that have been created for a document that is identified + * with {@code metaId}. + *

+ * If a document contains 3 image fields (1, 2, 3), then the cache entries for these 3 images will be removed. + * + * @param metaId the ID of a text document + */ + public void clearImageCache(int metaId) { + getDocumentMapper().clearImageCache(metaId); + } + + /** + * Removes a specific image cache entry that is identified with a document ID ({@code metaId}) and an image field + * number ({@code no}). + * + * @param metaId the ID of a text document + * @param no the ID of an image field + */ + public void clearImageCache(int metaId, int no) { + getDocumentMapper().clearImageCache(metaId, no); + } + + /** + * Removes a specific image cache entry that is identified with a document ID ({@code metaId}) and a + * {@link FileDocument} file ID ({@code fileNo}). + * + * @param metaId the ID of a text document + * @param fileNo the file ID of a {@link FileDocument} + */ + public void clearImageCache(int metaId, String fileNo) { + getDocumentMapper().clearImageCache(metaId, fileNo); } static class ApiWrappingDocumentVisitor extends DocumentVisitor { @@ -309,18 +521,34 @@ public Document getDocument() { } } - static class ApiDocumentWrappingList extends AbstractList { + private static class ApiDocumentWrappingPredicate implements Predicate { + + private final Predicate predicate; + private final ContentManagementSystem contentManagementSystem; + + ApiDocumentWrappingPredicate(Predicate predicate, ContentManagementSystem contentManagementSystem) { + this.predicate = predicate; + this.contentManagementSystem = contentManagementSystem; + } + + @Override + public boolean test(DocumentDomainObject document) { + return predicate.test(wrapDocumentDomainObject(document, contentManagementSystem)); + } + } + + static class ApiDocumentWrappingList extends AbstractList { - private final List documentList; + private final List documentList; private ContentManagementSystem contentManagementSystem; - ApiDocumentWrappingList(List documentList, ContentManagementSystem contentManagementSystem) { + ApiDocumentWrappingList(List documentList, ContentManagementSystem contentManagementSystem) { this.documentList = documentList; this.contentManagementSystem = contentManagementSystem; } - public Object get(int index) { - DocumentDomainObject document = (DocumentDomainObject) documentList.get(index); + public Document get(int index) { + DocumentDomainObject document = documentList.get(index); return wrapDocumentDomainObject(document, contentManagementSystem); } @@ -328,12 +556,12 @@ public int size() { return documentList.size(); } - public Object remove(int index) { - return wrapDocumentDomainObject((DocumentDomainObject) documentList.remove(index), contentManagementSystem) ; + public Document remove(int index) { + return wrapDocumentDomainObject(documentList.remove(index), contentManagementSystem); } - public Object set(int index, Object element) { - return wrapDocumentDomainObject((DocumentDomainObject) documentList.set(index, ((Document)element).getInternal()), contentManagementSystem) ; + public Document set(int index, Document element) { + return wrapDocumentDomainObject(documentList.set(index, element.getInternal()), contentManagementSystem); } } } \ No newline at end of file diff --git a/server/src/com/imcode/imcms/api/ExternalUserService.java b/server/src/com/imcode/imcms/api/ExternalUserService.java new file mode 100644 index 0000000000..51e53e142f --- /dev/null +++ b/server/src/com/imcode/imcms/api/ExternalUserService.java @@ -0,0 +1,8 @@ +package com.imcode.imcms.api; + +import com.imcode.imcms.model.ExternalUser; + +public interface ExternalUserService { + + ExternalUser saveExternalUser(ExternalUser user) throws SaveException; +} diff --git a/server/src/com/imcode/imcms/api/FileDocument.java b/server/src/com/imcode/imcms/api/FileDocument.java index 9a7074227b..ca4557f029 100644 --- a/server/src/com/imcode/imcms/api/FileDocument.java +++ b/server/src/com/imcode/imcms/api/FileDocument.java @@ -14,94 +14,192 @@ import java.util.List; import java.util.Map; +/** + * Document holding a file or files. + */ public class FileDocument extends Document { - public final static int TYPE_ID = DocumentTypeDomainObject.FILE_ID ; + /** + * FileDocument TYPE_ID + */ + public final static int TYPE_ID = DocumentTypeDomainObject.FILE_ID; - FileDocument( FileDocumentDomainObject document, ContentManagementSystem contentManagementSystem ) { - super( document, contentManagementSystem ); + FileDocument(FileDocumentDomainObject document, ContentManagementSystem contentManagementSystem) { + super(document, contentManagementSystem); } private FileDocumentDomainObject getInternalFileDocument() { - return (FileDocumentDomainObject)getInternal() ; + return (FileDocumentDomainObject) getInternal(); } - public FileDocumentFile getFile( String fileId ) { - return new FileDocumentFile(getInternalFileDocument().getFile( fileId )); + /** + * Returns a {@link FileDocumentFile} with the given id + * + * @param fileId id of a {@link FileDocument} file. + * @return FileDocumentFile with the given id + */ + public FileDocumentFile getFile(String fileId) { + return new FileDocumentFile(getInternalFileDocument().getFile(fileId)); } - public FileDocumentFile removeFile( String fileId ) { - return new FileDocumentFile( getInternalFileDocument().removeFile( fileId ) ); + /** + * Removes a {@link FileDocumentFile} with the given id. + * If the returned filedocument file was the default one, sets the next filedocument file in case insensitive order + * as the default one or null if no filedocument files left. + * + * @param fileId {@link FileDocumentFile} id to remove. + * @return the removed {@link FileDocumentFile} + */ + public FileDocumentFile removeFile(String fileId) { + return new FileDocumentFile(getInternalFileDocument().removeFile(fileId)); } + /** + * Returns all filedocument files in this file filedocument. + * + * @return not null, an array of {@link FileDocumentFile} + */ public FileDocumentFile[] getFiles() { Map filesMap = getInternalFileDocument().getFiles(); List files = TransformedList.decorate(new ArrayList(filesMap.size()), new Transformer() { - public Object transform( Object input ) { - return new FileDocumentFile( (FileDocumentDomainObject.FileDocumentFile)input ) ; + public Object transform(Object input) { + return new FileDocumentFile((FileDocumentDomainObject.FileDocumentFile) input); } - }) ; - files.addAll( filesMap.values() ) ; - return (FileDocumentFile[])files.toArray( new FileDocumentFile[files.size()] ); + }); + files.addAll(filesMap.values()); + return (FileDocumentFile[]) files.toArray(new FileDocumentFile[files.size()]); } - public FileDocumentFile getFileOrDefault( String fileId ) { - return new FileDocumentFile( getInternalFileDocument().getFileOrDefault( fileId ) ); + /** + * Returns FileDocumentFile with given id. The default FileDocumentFile is returned if the id is null or there is + * no FileDocumentFile with such id. + * + * @param fileId id of FileDocumentFile + * @return FileDocumentFile with given id or null if fileId is null or none found with given id. + */ + public FileDocumentFile getFileOrDefault(String fileId) { + return new FileDocumentFile(getInternalFileDocument().getFileOrDefault(fileId)); } + /** + * Returns the default file id + * + * @return default file id or null if there's no default file + */ public String getDefaultFileId() { return getInternalFileDocument().getDefaultFileId(); } + /** + * Returns the default {@link FileDocumentFile} of this {@link FileDocument} + * + * @return the default {@link FileDocumentFile} or null if there's no default file + */ public FileDocumentFile getDefaultFile() { - return new FileDocumentFile( getInternalFileDocument().getDefaultFile() ); + return new FileDocumentFile(getInternalFileDocument().getDefaultFile()); } - public void addFile( String fileId, FileDocumentFile file) { - getInternalFileDocument().addFile( fileId, file.getInternal() ); + /** + * Adds a file to the file document + * The added file becomes the default one if there's no default file. + * + * @param fileId id of the file to be added, not null + * @param file file to add + */ + public void addFile(String fileId, FileDocumentFile file) { + getInternalFileDocument().addFile(fileId, file.getInternal()); } + /** + * Class representing a file contained in a {@link FileDocument} + */ public static class FileDocumentFile implements DataSource { - private FileDocumentDataSource dataSource ; + private FileDocumentDataSource dataSource; - public FileDocumentFile( DataSource dataSource ) { + /** + * Constructs FileDocumentFile from the given {@link javax.activation.DataSource} + * + * @param dataSource data source of a file for this FileDocumentFile + */ + public FileDocumentFile(DataSource dataSource) { FileDocumentDomainObject.FileDocumentFile file = new FileDocumentDomainObject.FileDocumentFile(); - file.setFilename( dataSource.getName() ); - file.setMimeType( dataSource.getContentType() ); - file.setInputStreamSource( new DataSourceInputStreamSource( dataSource )); - this.dataSource = new FileDocumentDataSource( file ) ; - } - - public FileDocumentFile( FileDocumentDomainObject.FileDocumentFile file ) { - dataSource = new FileDocumentDataSource( file ) ; - } - + file.setFilename(dataSource.getName()); + file.setMimeType(dataSource.getContentType()); + file.setInputStreamSource(new DataSourceInputStreamSource(dataSource)); + this.dataSource = new FileDocumentDataSource(file); + } + + /** + * Constructs FileDocumentFile from another FileDocumentFile + * + * @param file FileDocumentFile + */ + public FileDocumentFile(FileDocumentDomainObject.FileDocumentFile file) { + dataSource = new FileDocumentDataSource(file); + } + + /** + * Returns internally used FileDocumentFile + * + * @return internally used FileDocumentFile + */ public FileDocumentDomainObject.FileDocumentFile getInternal() { - return dataSource.getFile() ; + return dataSource.getFile(); } + /** + * Returns the content type of this FileDocumentFile + * + * @return a String representing content type + */ public String getContentType() { return dataSource.getContentType(); } + /** + * Returns {@link java.io.InputStream} of this FileDocumentFile + * + * @return {@link java.io.InputStream} of this FileDocumentFile + * @throws IOException + */ public InputStream getInputStream() throws IOException { return dataSource.getInputStream(); } + /** + * Returns the name of this FileDocumentFile's data source + * + * @return a String with the name of this FileDocumentFile's data source + */ public String getName() { return dataSource.getName(); } - /** @throws UnsupportedOperationException */ + /** + * Not supported. + * + * @throws UnsupportedOperationException to signal that this is not supported + */ public OutputStream getOutputStream() throws IOException { - throw new UnsupportedOperationException() ; + throw new UnsupportedOperationException(); } + /** + * Returns the size of underlying data source's file input stream + * + * @return input stream's size in long + * @throws IOException + */ public long getSize() throws IOException { - return dataSource.getFile().getInputStreamSource().getSize() ; + return dataSource.getFile().getInputStreamSource().getSize(); } + /** + * Returns the id of underlying data source file + * + * @return a String representing underlying data source file's id + */ public String getId() { return dataSource.getFile().getId(); } @@ -112,7 +210,7 @@ private static class FileDocumentDataSource implements DataSource { private FileDocumentDomainObject.FileDocumentFile file; - private FileDocumentDataSource( FileDocumentDomainObject.FileDocumentFile file ) { + private FileDocumentDataSource(FileDocumentDomainObject.FileDocumentFile file) { this.file = file; } @@ -141,7 +239,7 @@ private static class DataSourceInputStreamSource implements InputStreamSource { private final DataSource dataSource; - private DataSourceInputStreamSource( DataSource dataSource ) { + private DataSourceInputStreamSource(DataSource dataSource) { this.dataSource = dataSource; } diff --git a/server/src/com/imcode/imcms/api/Image.java b/server/src/com/imcode/imcms/api/Image.java index 4ba647596d..b76f79342b 100644 --- a/server/src/com/imcode/imcms/api/Image.java +++ b/server/src/com/imcode/imcms/api/Image.java @@ -3,123 +3,284 @@ import imcode.server.document.textdocument.ImageDomainObject; import imcode.server.document.textdocument.ImageSource; import imcode.util.ImcmsImageUtils; +import org.apache.commons.lang.StringEscapeUtils; import javax.servlet.http.HttpServletRequest; import java.util.Properties; +/** + * A representation of an image in imcms. Provides methods of presentation as html tag along with a multitude of + * attributes. + */ public class Image { private ImageDomainObject internalImage; + private Integer metaId; - Image(ImageDomainObject internalImage) { + Image(ImageDomainObject internalImage, Integer metaId) { this.internalImage = internalImage; + this.metaId = metaId; } + /** + * Constructs an empty image. + */ public Image() { - this( new ImageDomainObject() ); + this(new ImageDomainObject(), null); } + /** + * Returns the ID of a document that this image is part of. + * + * @return ID of a document + */ + public Integer getMetaId() { + return metaId; + } + + /** + * Sets the ID of a document that this image is part of. + * + * @param metaId ID of a document + */ + public void setMetaId(Integer metaId) { + this.metaId = metaId; + } + + /** + * Returns the name of this image + * + * @return a String with image's name + */ public String getName() { // html imagetag name return internalImage.getName(); } - public void setName( String name ) { // html imagetag name - internalImage.setName( name ); + /** + * Sets this image's name. + * + * @param name new name + */ + public void setName(String name) { // html imagetag name + internalImage.setName(name); } + /** + * Returns this image's src url relative to context path. + * For a full url 'http://localhost:9090/images/imCMSpower.gif', the returned string would contain '/images/imCMSpower.gif' + * + * @return this image's src url relative to context path. + */ public String getSrcRelativeToContextPath() { // image srcurl, relative imageurl return internalImage.getUrlPathRelativeToContextPath(); } + /** + * Returns the url of the low resolution version of this image if there's one. + * + * @return src url of the low resolution version of this image or an empty string. + */ public String getLowSrc() { return internalImage.getLowResolutionUrl(); } - public void setLowSrc( String low_src ) { - internalImage.setLowResolutionUrl( low_src ); + /** + * Sets the url of the low resolution version of this image. + * + * @param low_src low resolution url. + */ + public void setLowSrc(String low_src) { + internalImage.setLowResolutionUrl(low_src); } + /** + * Returns width attribute of this image. + * + * @return image width + */ public int getWidth() { return internalImage.getDisplayImageSize().getWidth(); } - public void setWidth( int width ) { - internalImage.setWidth( width ); + /** + * Sets this image's width attribute + * The underlying image is not modified, this is just one of attributes. + * + * @param width new image width + */ + public void setWidth(int width) { + internalImage.setWidth(width); } + /** + * Returns height attribute of this image. + * + * @return image height + */ public int getHeight() { return internalImage.getDisplayImageSize().getHeight(); } - public void setHeight( int height ) { - internalImage.setHeight( height ); + /** + * Sets this image's height attribute. + * + * @param height new image height + */ + public void setHeight(int height) { + internalImage.setHeight(height); } + /** + * Returns border width attribute of this image. + * + * @return border width in pixels + */ public int getBorder() { return internalImage.getBorder(); } - public void setBorder( int border ) { - internalImage.setBorder( border ); + /** + * Sets this image's border width attribute. + * + * @param border border width in pixels + */ + public void setBorder(int border) { + internalImage.setBorder(border); } + /** + * Returns this image's 'align' attribute. + * + * @return 'align' attribute + */ public String getAlign() { return internalImage.getAlign(); } - public void setAlign( String align ) { - internalImage.setAlign( align ); + /** + * Sets this image's 'align' attribute. + * + * @param align new value for 'align' attribute + */ + public void setAlign(String align) { + internalImage.setAlign(align); } + /** + * Returns alt text of this image + * + * @return alt text + */ public String getAltText() { return internalImage.getAlternateText(); } - public void setAltText( String alt_text ) { - internalImage.setAlternateText( alt_text ); + /** + * Sets alt text of this image + * + * @param alt_text new alt text string + */ + public void setAltText(String alt_text) { + internalImage.setAlternateText(alt_text); } + /** + * Returns 'vspace' attribute + * + * @return 'vspace' attribute + */ public int getVspace() { return internalImage.getVerticalSpace(); } - public void setVspace( int v_space ) { - internalImage.setVerticalSpace( v_space ); + /** + * Sets 'vspace' attribute + * + * @param v_space new 'vspace' attribute + */ + public void setVspace(int v_space) { + internalImage.setVerticalSpace(v_space); } + /** + * Returns 'hspace' attribute + * + * @return 'hspace' attribute + */ public int getHspace() { return internalImage.getHorizontalSpace(); } - public void setHspace( int h_space ) { - internalImage.setHorizontalSpace( h_space ); + /** + * Sets 'hspace' attribute + * + * @param h_space new 'hspace' attribute + */ + public void setHspace(int h_space) { + internalImage.setHorizontalSpace(h_space); } + /** + * Returns the 'href' attribute of a link surrounding this image's presentation + * + * @return 'href' attribute of a link surrounding this image's presentation or an empty String + */ public String getLinkHref() { return internalImage.getLinkUrl(); } - public void setLinkHref( String link_href ) { - internalImage.setLinkUrl( link_href ); + /** + * Sets the url of the link surrounding(if present) this image. + * + * @param link_href href attribute for a link. + */ + public void setLinkHref(String link_href) { + internalImage.setLinkUrl(link_href); } + /** + * Returns the 'target' attribute of a link surrounding(if present) this image. + * + * @return 'target' attribute + */ public String getLinkTarget() { // use target_name if target = _other return internalImage.getTarget(); } - public void setLinkTarget( String target ) { - internalImage.setTarget( target ); + /** + * Sets the 'target' attribute of a link surrounding(if present) this image. + * + * @param target new 'target' attribute value + */ + public void setLinkTarget(String target) { + internalImage.setTarget(target); } - public void setSrc( String src ) { // image srcurl, relative imageurl - ImageSource imageSource = ImcmsImageUtils.createImageSourceFromString( src ) ; - internalImage.setSource( imageSource ); + /** + * Attempt to replace this image's datasource, with a new one created from the given src url. + * Sets {@link imcode.server.document.textdocument.NullImageSource} if the argument is empty. + * + * @param src relative imageurl + */ + public void setSrc(String src) { // image srcurl, relative imageurl + ImageSource imageSource = ImcmsImageUtils.createImageSourceFromString(src); + internalImage.setSource(imageSource); } + /** + * Tests whether this image's underlying datasource's inputstream size is 0 + * + * @return true if there's an actual image backing this Image object, false otherwise. + */ public boolean isEmpty() { - return internalImage.isEmpty() ; + return internalImage.isEmpty(); } + /** + * Returns this image's size in bytes. + * + * @return image's size in bytes. + */ public long getSize() { return internalImage.getSize(); } @@ -128,14 +289,46 @@ ImageDomainObject getInternal() { return internalImage; } + /** + * Returns image src url with given context path. + * + * @param contextPath context path to append the image url to. + * @return a String representing this image's url with provided context path. + */ public String getSrc(String contextPath) { // image srcurl relative webapp ( /imcms/images/theimage.gif ) - return internalImage.getUrlPath( contextPath ) ; - } - + return internalImage.getUrlPath(contextPath); + } + + /** + * Returns a string representing this image as html tag + * + * @param contextPath context path for tag 'src' attribute's url. + * @return a string with html image tag produced from this image + */ + public String toHtmlUrl(String contextPath) { + return StringEscapeUtils.escapeHtml(ImcmsImageUtils.getImageUrl(metaId, internalImage, contextPath)); + } + + /** + * Returns a string representing the image as html img tag, adds optional attributes like id, class, usemap and style. + * + * @param request a http request + * @param attributes Not null, optional attributes such as id, class, usemap and style. + * @param absolute true if the url in img src attribute should be absolute + * @return a string representing the image as html img tag + */ public String toHtmlTag(HttpServletRequest request, Properties attributes, boolean absolute) { - return ImcmsImageUtils.getImageHtmlTag(internalImage, request, attributes, absolute); + return ImcmsImageUtils.getImageHtmlTag(metaId, internalImage, request, attributes, absolute); } + /** + * Returns a string representing the image as html img tag, adds optional attributes like id, class, usemap and style. + * The src attribute will have relative path + * + * @param request a http request + * @param attributes Not null, optional attributes such as id, class, usemap and style. + * @return a string representing the image as html img tag + */ public String toHtmlTag(HttpServletRequest request, Properties attributes) { return toHtmlTag(request, attributes, false); } diff --git a/server/src/com/imcode/imcms/api/Language.java b/server/src/com/imcode/imcms/api/Language.java index 84089d2e83..8d08107c7d 100644 --- a/server/src/com/imcode/imcms/api/Language.java +++ b/server/src/com/imcode/imcms/api/Language.java @@ -3,45 +3,76 @@ import imcode.server.LanguageMapper; /** + * Represents Language in imcms + * * @author kreiger */ public class Language { - private String isoCode639_2 ; + private String isoCode639_2; - private Language( String isoCode639_2 ) { - this.isoCode639_2 = isoCode639_2 ; + private Language(String isoCode639_2) { + this.isoCode639_2 = isoCode639_2; } - public static Language getLanguageByISO639_2( String isoCode639_2 ) { + /** + * Returns Language by given ISO 639-2 code + * + * @param isoCode639_2 language code + * @return language mapped to the given code or null if the given code is not mapped to any language + * @see List_of_ISO_639-2_codes + */ + public static Language getLanguageByISO639_2(String isoCode639_2) { if (LanguageMapper.existsIsoCode639_2(isoCode639_2)) { - return new Language( isoCode639_2 ); + return new Language(isoCode639_2); } else { - return null ; + return null; } } - public static Language getLanguageByISO639_1( String isoCode639_1 ) { + /** + * Returns Language by given ISO 639-1 code + * + * @param isoCode639_1 language code + * @return language mapped to the given code or null if the given code is not mapped to any language + * @see List_of_ISO_639-2_codes + */ + public static Language getLanguageByISO639_1(String isoCode639_1) { try { - return getLanguageByISO639_2(LanguageMapper.convert639_1to639_2(isoCode639_1)) ; - } catch ( LanguageMapper.LanguageNotSupportedException e ) { - return null ; + return getLanguageByISO639_2(LanguageMapper.convert639_1to639_2(isoCode639_1)); + } catch (LanguageMapper.LanguageNotSupportedException e) { + return null; } } + /** + * Returns a string representation of this object. In the form of "ISO 639-2: " + {@link Language#getIsoCode639_2()} + * + * @return a string representation of this Language + */ public String toString() { - return "ISO 639-2: "+isoCode639_2 ; + return "ISO 639-2: " + isoCode639_2; } + /** + * Returns ISO 639-2 string of this Language + * + * @return ISO 639-2 string of this Language + */ public String getIsoCode639_2() { return isoCode639_2; } + /** + * Returns ISO 639-1 code of this Language. + * + * @return ISO 639-1 code of this Language or null if not found. + */ public String getIsoCode639_1() { try { - return LanguageMapper.convert639_2to639_1(isoCode639_2) ; - } catch ( LanguageMapper.LanguageNotSupportedException e ) { - return null ; + return LanguageMapper.convert639_2to639_1(isoCode639_2); + } catch (LanguageMapper.LanguageNotSupportedException e) { + return null; } } diff --git a/server/src/com/imcode/imcms/api/LuceneParsedQuery.java b/server/src/com/imcode/imcms/api/LuceneParsedQuery.java index 1be00ace28..7de03cccf9 100644 --- a/server/src/com/imcode/imcms/api/LuceneParsedQuery.java +++ b/server/src/com/imcode/imcms/api/LuceneParsedQuery.java @@ -1,26 +1,42 @@ package com.imcode.imcms.api; import imcode.server.document.index.DefaultQueryParser; -import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.search.Query; +/** + * Document search query. Provides means of query creation from String + */ public class LuceneParsedQuery extends SearchQuery { private Query query; - public LuceneParsedQuery( String queryString ) throws BadQueryException { + /** + * Constructs Lucene search query from a String + * + * @param queryString a string representing a search query + * @throws BadQueryException if the given string cannot be parsed into query + */ + public LuceneParsedQuery(String queryString) throws BadQueryException { try { query = parse(queryString); - } catch ( ParseException e ) { - throw new BadQueryException( queryString, e ); + } catch (ParseException e) { + throw new BadQueryException(queryString, e); } } + /** + * Attempts parsing of a String into Lucene search query + * + * @param queryString a string representing a search query + * @return a {@link Query} parsed from the given String + * @throws ParseException if the given string cannot be parsed into query + */ public static Query parse(String queryString) throws ParseException { - return new DefaultQueryParser().parse( queryString ); + return new DefaultQueryParser().parse(queryString); } - Query getQuery() { + public Query getQuery() { return query; } diff --git a/server/src/com/imcode/imcms/api/LuceneQuery.java b/server/src/com/imcode/imcms/api/LuceneQuery.java index dfd09dfb54..999f35589d 100644 --- a/server/src/com/imcode/imcms/api/LuceneQuery.java +++ b/server/src/com/imcode/imcms/api/LuceneQuery.java @@ -2,16 +2,24 @@ import org.apache.lucene.search.Query; +/** + * Wraps lucene search {@link Query} into a query acceptable by {@link DocumentService#getDocuments(SearchQuery)} + */ public class LuceneQuery extends SearchQuery { private Query query; + /** + * Constructs LuceneQuery from already created {@link Query} + * + * @param query {@link Query} + */ public LuceneQuery(Query query) { this.query = query; } - Query getQuery() { + public Query getQuery() { return query; } - + } diff --git a/server/src/com/imcode/imcms/api/Mail.java b/server/src/com/imcode/imcms/api/Mail.java index f4d7c3e516..37e0d877b4 100644 --- a/server/src/com/imcode/imcms/api/Mail.java +++ b/server/src/com/imcode/imcms/api/Mail.java @@ -3,49 +3,138 @@ import imcode.util.net.SMTP; import javax.activation.DataSource; +import java.util.Map; +/** + * Represents an email sent using {@link MailService} + */ public class Mail { - private SMTP.Mail internal ; + private SMTP.Mail internal; + /** + * Constructs email with the given string used as the sender address + * + * @param fromAddress sender address + */ public Mail(String fromAddress) { - this.internal = new SMTP.Mail( fromAddress ); + this.internal = new SMTP.Mail(fromAddress); } - public Mail( String fromAddress, String[] toAddresses, String subject, String body ) { - this.internal = new SMTP.Mail( fromAddress, toAddresses, subject, body ); + /** + * Constructs email with the given from, to addresses, subject and body + * + * @param fromAddress sender email address + * @param toAddresses array of recipient addresses + * @param subject email subject + * @param body email body + */ + public Mail(String fromAddress, String[] toAddresses, String subject, String body) { + this.internal = new SMTP.Mail(fromAddress, toAddresses, subject, body); } SMTP.Mail getInternal() { - return internal ; + return internal; } - public void setAttachments( DataSource[] attachments ) { - internal.setAttachments( attachments ); + /** + * Sets attachments for this email + * + * @param attachments attachments, not null + */ + public void setAttachments(DataSource[] attachments) { + internal.setAttachments(attachments); } - public void setBccAddresses( String[] bccAddresses ) { - internal.setBccAddresses( bccAddresses ); + /** + * Sets bcc addresses + * + * @param bccAddresses an array of Strings with bcc addresses, not null + */ + public void setBccAddresses(String[] bccAddresses) { + internal.setBccAddresses(bccAddresses); } - public void setBody( String body ) { - internal.setBody( body ); + /** + * Sets the text version of body of this email + * + * @param body mail body + */ + public void setBody(String body) { + internal.setBody(body); } - - public void setHtmlBody( String htmlBody ) { - internal.setHtmlBody( htmlBody ); + + /** + * Sets the html version of body of this email + * + * @param htmlBody mail body + */ + public void setHtmlBody(String htmlBody) { + internal.setHtmlBody(htmlBody); + } + + /** + * Sets cc addresses + * + * @param ccAddresses an array of Strings with cc addresses, not null + */ + public void setCcAddresses(String[] ccAddresses) { + internal.setCcAddresses(ccAddresses); + } + + /** + * Sets the subject of this email + * + * @param subject subject of this email + */ + public void setSubject(String subject) { + internal.setSubject(subject); + } + + /** + * Sets the recipient addresses of this email + * + * @param toAddresses an array of String with recipient addresses, not null + */ + public void setToAddresses(String[] toAddresses) { + internal.setToAddresses(toAddresses); } - public void setCcAddresses( String[] ccAddresses ) { - internal.setCcAddresses( ccAddresses ); + /** + * Sets the 'reply to' addresses of this email + * + * @param replyToAddresses an array of String with addresses which will be in 'Reply to:' field. + */ + public void setReplyToAddresses(String[] replyToAddresses) { + internal.setReplyToAddresses(replyToAddresses); } - public void setSubject( String subject ) { - internal.setSubject( subject ); + /** + * Simply adds email header with specified name and value + * + * @param name header name + * @param value header value + */ + public void addHeader(String name, String value) { + internal.addHeader(name, value); } - public void setToAddresses( String[] toAddresses ) { - internal.setToAddresses( toAddresses ); + /** + * Get headers map as header name and header value pairs. + * + * @return header name and header value pairs map + */ + public Map getHeaders() { + return internal.getHeaders(); } + /** + * Set email headers and values as kay-value map. + * Note that this methods will replace all previous headers that was set. + * + * @param headers header name and header value pairs map + */ + public void setHeaders(Map headers) { + internal.setHeaders(headers); + } } diff --git a/server/src/com/imcode/imcms/api/MailException.java b/server/src/com/imcode/imcms/api/MailException.java index a74ae714f5..e37189230e 100644 --- a/server/src/com/imcode/imcms/api/MailException.java +++ b/server/src/com/imcode/imcms/api/MailException.java @@ -1,8 +1,12 @@ package com.imcode.imcms.api; +/** + * Usually thrown when something wrong happens when sending out emails. Like {@link MailService} not being able to contact + * the mail server etc. + */ public class MailException extends Exception { - public MailException( Exception e ) { - super(e) ; + public MailException(Exception e) { + super(e); } } diff --git a/server/src/com/imcode/imcms/api/MailService.java b/server/src/com/imcode/imcms/api/MailService.java index 20265113ca..c3db7bc17e 100644 --- a/server/src/com/imcode/imcms/api/MailService.java +++ b/server/src/com/imcode/imcms/api/MailService.java @@ -2,19 +2,29 @@ import imcode.util.net.SMTP; +/** + * Class used to send out {@link Mail} + */ public class MailService { private SMTP smtp; - MailService( SMTP smtp ) { + MailService(SMTP smtp) { this.smtp = smtp; } + /** + * Sends out the given email + * + * @param mail {@link Mail} to send + * @throws MailException if the email can't be sent due to unavailability of a mail server or invalid + * attributes in the {@link Mail} object, such as sender address, destination addresses, cc, bcc addresses etc. + */ public void sendMail(Mail mail) throws MailException { try { - smtp.sendMail( mail.getInternal() ); - } catch ( Exception e ) { - throw new MailException( e ); + smtp.sendMail(mail.getInternal()); + } catch (Exception e) { + throw new MailException(e); } } } diff --git a/server/src/com/imcode/imcms/api/MaxCategoriesOfTypeExceededException.java b/server/src/com/imcode/imcms/api/MaxCategoriesOfTypeExceededException.java index 3749ad4316..1d84c7436b 100644 --- a/server/src/com/imcode/imcms/api/MaxCategoriesOfTypeExceededException.java +++ b/server/src/com/imcode/imcms/api/MaxCategoriesOfTypeExceededException.java @@ -1,11 +1,14 @@ package com.imcode.imcms.api; /** + * Usually thrown when saving a {@link Document}. Signals that a document was assigned more categories of a + * {@link CategoryType} that that category type's maximum number of choices allows. + * * @author kreiger */ public class MaxCategoriesOfTypeExceededException extends SaveException { MaxCategoriesOfTypeExceededException(Throwable cause) { - super(cause) ; + super(cause); } } diff --git a/server/src/com/imcode/imcms/api/NoPermissionException.java b/server/src/com/imcode/imcms/api/NoPermissionException.java index 2f75ac65b8..d8b10ac069 100644 --- a/server/src/com/imcode/imcms/api/NoPermissionException.java +++ b/server/src/com/imcode/imcms/api/NoPermissionException.java @@ -2,11 +2,11 @@ /** * This exception is thrown from almost all methods in the service classes. It is thrown when the current logged - * in user dosen't have the apropiate rights to do that operation. See the message for futher information. + * in user doesn't have the apropiate rights to do that operation. See the message for further information. */ public class NoPermissionException extends RuntimeException { - public NoPermissionException( String message ) { - super( message ); + public NoPermissionException(String message) { + super(message); } } diff --git a/server/src/com/imcode/imcms/api/P.java b/server/src/com/imcode/imcms/api/P.java new file mode 100644 index 0000000000..b3817f5be9 --- /dev/null +++ b/server/src/com/imcode/imcms/api/P.java @@ -0,0 +1,32 @@ +package com.imcode.imcms.api; + +// Product +public final class P { + + public static P2 of(final A a, final B b) { + return new P2() { + public A _1() { + return a; + } + + public B _2() { + return b; + } + }; + } + + public abstract static class P2 { + public abstract A _1(); + + public abstract B _2(); + + @Override + public String toString() { + return String.format("P.P2{_1=%s, _2=%s}", _1(), _2()); + } + } + + +} + + diff --git a/server/src/com/imcode/imcms/api/Role.java b/server/src/com/imcode/imcms/api/Role.java index efe127f23d..4b6e1beb45 100644 --- a/server/src/com/imcode/imcms/api/Role.java +++ b/server/src/com/imcode/imcms/api/Role.java @@ -4,17 +4,30 @@ import imcode.server.user.RoleId; /** + * Represent a role in imcms. + * * @since 2.0 */ public class Role implements Comparable { - public static final int SUPERADMIN_ID = RoleId.SUPERADMIN_ID ; - public static final int USERADMIN_ID = RoleId.USERADMIN_ID ; - public static final int USERS_ID = RoleId.USERS_ID ; + /** + * Super admin role id + */ + public static final int SUPERADMIN_ID = RoleId.SUPERADMIN_ID; - private final RoleDomainObject internalRole ; + /** + * User admin role id + */ + public static final int USERADMIN_ID = RoleId.USERADMIN_ID; - Role( RoleDomainObject role ) { + /** + * Default user role id. + */ + public static final int USERS_ID = RoleId.USERS_ID; + + private final RoleDomainObject internalRole; + + Role(RoleDomainObject role) { this.internalRole = role; } @@ -22,43 +35,92 @@ RoleDomainObject getInternal() { return internalRole; } + /** + * Returns the id of this role + * + * @return id of this role + */ public int getId() { return internalRole.getId().intValue(); } + /** + * Returns the name of this role + * + * @return name of this role + */ public String getName() { return internalRole.getName(); } - public void setName( String name ) { - internalRole.setName( name ); + /** + * Sets name of this role. + * + * @param name new name of this role + */ + public void setName(String name) { + internalRole.setName(name); } - public boolean equals( Object o ) { - return internalRole.equals( ((Role)o).internalRole ); + /** + * Tests this role for equality with the given one. + * Two roles are the same if their ids are the same. + * + * @param o a {@link Role} to test with + * @return true if equal, false otherwise + */ + public boolean equals(Object o) { + return internalRole.equals(((Role) o).internalRole); } + /** + * Returns hash code of this role + * + * @return hash code + */ public int hashCode() { return internalRole.hashCode(); } + /** + * Calls {@link com.imcode.imcms.api.Role#getName()} + * + * @return the String form of this role + */ public String toString() { - return getName() ; + return getName(); } + /** + * Sets if the role owners are allowed to have their password sent out by email + * + * @param passwordMailPermission whether to allow password be sent out by email + */ public void setPasswordMailPermission(boolean passwordMailPermission) { if (passwordMailPermission) { - internalRole.addPermission( RoleDomainObject.PASSWORD_MAIL_PERMISSION ); + internalRole.addPermission(RoleDomainObject.PASSWORD_MAIL_PERMISSION); } else { - internalRole.removePermission( RoleDomainObject.PASSWORD_MAIL_PERMISSION ); + internalRole.removePermission(RoleDomainObject.PASSWORD_MAIL_PERMISSION); } } + /** + * Tests whether this role owners have permission to get their passwords by email + * + * @return true if are allowed, false otherwise + */ public boolean hasPasswordMailPermission() { - return internalRole.hasPermission( RoleDomainObject.PASSWORD_MAIL_PERMISSION ) ; + return internalRole.hasPermission(RoleDomainObject.PASSWORD_MAIL_PERMISSION); } - public int compareTo( Object o ) { - return internalRole.compareTo( ((Role)o).internalRole ) ; + /** + * Compares two roles by name, the comparison is case insensitive. + * + * @param o another role to compare with + * @return 0 if equal lexicographically, less than 0 if this Role is lesser lexicographically than the argument, + * more than 0 if greater than the argument. + */ + public int compareTo(Object o) { + return internalRole.compareTo(((Role) o).internalRole); } } diff --git a/server/src/com/imcode/imcms/api/RoleAlreadyExistsException.java b/server/src/com/imcode/imcms/api/RoleAlreadyExistsException.java index 769457c421..2e29aeef3d 100644 --- a/server/src/com/imcode/imcms/api/RoleAlreadyExistsException.java +++ b/server/src/com/imcode/imcms/api/RoleAlreadyExistsException.java @@ -1,8 +1,11 @@ package com.imcode.imcms.api; +/** + * Usually thrown when saving a {@link Role}. Signals that there's already a role with the name that the role being save has. + */ public class RoleAlreadyExistsException extends AlreadyExistsException { public RoleAlreadyExistsException(String message, Throwable cause) { - super(message, cause) ; + super(message, cause); } } diff --git a/server/src/com/imcode/imcms/api/SaveException.java b/server/src/com/imcode/imcms/api/SaveException.java index cd03342b6a..1709b07a26 100644 --- a/server/src/com/imcode/imcms/api/SaveException.java +++ b/server/src/com/imcode/imcms/api/SaveException.java @@ -1,15 +1,17 @@ package com.imcode.imcms.api; /** + * Base exception, thrown when saving failed. + * * @since 2.0 */ public class SaveException extends Exception { public SaveException(String message, Throwable cause) { - super(message, cause) ; + super(message, cause); } - public SaveException( Throwable cause ) { - super(cause) ; + public SaveException(Throwable cause) { + super(cause); } } diff --git a/server/src/com/imcode/imcms/api/SearchException.java b/server/src/com/imcode/imcms/api/SearchException.java index 487752e632..56facbce4d 100644 --- a/server/src/com/imcode/imcms/api/SearchException.java +++ b/server/src/com/imcode/imcms/api/SearchException.java @@ -1,9 +1,12 @@ package com.imcode.imcms.api; -public class SearchException extends Exception { +/** + * Base class for search related exceptions. + */ +public class SearchException extends RuntimeException { - public SearchException( Throwable cause ) { - super(cause) ; + public SearchException(Throwable cause) { + super(cause); } } \ No newline at end of file diff --git a/server/src/com/imcode/imcms/api/SearchQuery.java b/server/src/com/imcode/imcms/api/SearchQuery.java index e338142713..80987d885e 100644 --- a/server/src/com/imcode/imcms/api/SearchQuery.java +++ b/server/src/com/imcode/imcms/api/SearchQuery.java @@ -1,29 +1,53 @@ package com.imcode.imcms.api; +import imcode.server.document.index.DocumentQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.Sort; -public abstract class SearchQuery { +/** + * Base class for Lucene based document search queries, used with {@link DocumentService#getDocuments(SearchQuery)} + */ +public abstract class SearchQuery implements DocumentQuery { - private Sort sort ; + private Sort sort; private boolean logged; - abstract Query getQuery() ; - - Sort getSort() { - return sort ; + /** + * Returns the query + * + * @return query + */ + public abstract Query getQuery(); + + public Sort getSort() { + return sort; } + /** + * Sets sorting of for this query + * + * @param sort sorting for this query + */ public void setSort(Sort sort) { this.sort = sort; } - - public void setLogged(boolean logged) { - this.logged = logged; - } - boolean isLogged() { + /** + * Tests whether this query should be logged + * + * @return true if this query is set to be logged, false otherwise + */ + public boolean isLogged() { return logged; } + /** + * Sets whether this query should be logged + * + * @param logged true if the query should be logged, false otherwise + */ + public void setLogged(boolean logged) { + this.logged = logged; + } + } \ No newline at end of file diff --git a/server/src/com/imcode/imcms/api/SearchResult.java b/server/src/com/imcode/imcms/api/SearchResult.java new file mode 100644 index 0000000000..b35da59a16 --- /dev/null +++ b/server/src/com/imcode/imcms/api/SearchResult.java @@ -0,0 +1,48 @@ +package com.imcode.imcms.api; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Getter +@ToString +@EqualsAndHashCode +public class SearchResult { + + private final List result; + private final int totalCount; + private final int nextSkip; + + public SearchResult(List result, int totalCount) { + this(result, totalCount, 0); + } + + public SearchResult(List result, int totalCount, int nextSkip) { + this.result = result; + this.totalCount = totalCount; + this.nextSkip = nextSkip; + } + + public static SearchResult empty() { + return new SearchResult<>(Collections.emptyList(), 0); + } + + public static SearchResult of(List result, int totalCount) { + return new SearchResult<>(result, totalCount); + } + + public SearchResult mapResult(Function transformer) { + + final List newResult = this.result.parallelStream() + .map(transformer) + .collect(Collectors.toList()); + + return new SearchResult<>(newResult, totalCount, nextSkip); + } + +} diff --git a/server/src/com/imcode/imcms/api/Section.java b/server/src/com/imcode/imcms/api/Section.java index b252ba82fa..375b23e7a1 100644 --- a/server/src/com/imcode/imcms/api/Section.java +++ b/server/src/com/imcode/imcms/api/Section.java @@ -1,21 +1,38 @@ package com.imcode.imcms.api; -import imcode.server.document.*; +import imcode.server.document.SectionDomainObject; +/** + * Represents a section in imcms + */ public class Section { SectionDomainObject internalSection; - public Section( SectionDomainObject sectionDomainObject ) { + + /** + * Constructs a Section with the given SectionDomainObject used internally. + * + * @param sectionDomainObject SectionDomainObject to be used internally. + */ + public Section(SectionDomainObject sectionDomainObject) { this.internalSection = sectionDomainObject; } - public String getName(){ - return this.internalSection.getName(); - } + /** + * Returns the name of this serction + * + * @return a string with name of this section + */ + public String getName() { + return this.internalSection.getName(); + } /** - @since 2.0 + * Returns the id of this section. + * + * @return id of this section + * @since 2.0 */ - public int getId() { - return internalSection.getId(); - } + public int getId() { + return internalSection.getId(); + } } diff --git a/server/src/com/imcode/imcms/api/Template.java b/server/src/com/imcode/imcms/api/Template.java index 3e55afe80c..5ff7a8025a 100644 --- a/server/src/com/imcode/imcms/api/Template.java +++ b/server/src/com/imcode/imcms/api/Template.java @@ -2,28 +2,49 @@ import imcode.server.document.TemplateDomainObject; +/** + * Represents a template in imcms + */ public class Template { private final TemplateDomainObject internalTemplate; + /** + * Constructs Template with the given TemplateDomainObject backing it. + * + * @param internalTemplate TemplateDomainObject to be used internally. + */ public Template(TemplateDomainObject internalTemplate) { this.internalTemplate = internalTemplate; } + /** + * Returns the name of this template + * + * @return name of this template + */ public String getName() { return internalTemplate.getName(); } - /** @deprecated Returns 0, use {@link #getName()} instead. **/ + /** + * @deprecated Returns 0, use {@link #getName()} instead. + **/ public int getId() { return 0; } + /** + * Compares two templates, uses {@link com.imcode.imcms.api.Template#getName()} as a criteria of equality. + * + * @param o template to compare with + * @return true if both templates are the same + */ public boolean equals(Object o) { - if ( this == o ) { + if (this == o) { return true; } - if ( !( o instanceof Template ) ) { + if (!(o instanceof Template)) { return false; } @@ -33,14 +54,24 @@ public boolean equals(Object o) { } + /** + * Hash code of this Template, calls hashCode() of Template's name. + * + * @return + */ public int hashCode() { - return internalTemplate.hashCode() ; + return internalTemplate.hashCode(); } TemplateDomainObject getInternal() { return internalTemplate; } + /** + * String representation of this template in the form of a name + * + * @return same as {@link com.imcode.imcms.api.Template#getName()} + */ public String toString() { return getName(); } diff --git a/server/src/com/imcode/imcms/api/TemplateGroup.java b/server/src/com/imcode/imcms/api/TemplateGroup.java index 32032e6eec..f7e81aa099 100644 --- a/server/src/com/imcode/imcms/api/TemplateGroup.java +++ b/server/src/com/imcode/imcms/api/TemplateGroup.java @@ -2,18 +2,36 @@ import imcode.server.document.TemplateGroupDomainObject; +/** + * Class describing a group of templates + */ public class TemplateGroup { private final TemplateGroupDomainObject internalTemplateGroup; + /** + * Constructs TemplateGroup with TemplateGroupDomainObject backing it + * + * @param internal TemplateGroupDomainObject to be used internally + */ public TemplateGroup(TemplateGroupDomainObject internal) { internalTemplateGroup = internal; } + /** + * Returns template group's name + * + * @return template group's name + */ public String getName() { return internalTemplateGroup.getName(); } + /** + * Returns template group's id + * + * @return template group's id + */ public int getId() { return internalTemplateGroup.getId(); } @@ -23,20 +41,20 @@ TemplateGroupDomainObject getInternal() { } public boolean equals(Object o) { - if ( this == o ) { + if (this == o) { return true; } - if ( !( o instanceof TemplateGroup ) ) { + if (!(o instanceof TemplateGroup)) { return false; } final TemplateGroup templateGroup = (TemplateGroup) o; - return internalTemplateGroup.equals(templateGroup.internalTemplateGroup) ; + return internalTemplateGroup.equals(templateGroup.internalTemplateGroup); } public int hashCode() { - return internalTemplateGroup.hashCode() ; + return internalTemplateGroup.hashCode(); } } diff --git a/server/src/com/imcode/imcms/api/TemplateService.java b/server/src/com/imcode/imcms/api/TemplateService.java index bd2e3270dc..3745680e07 100644 --- a/server/src/com/imcode/imcms/api/TemplateService.java +++ b/server/src/com/imcode/imcms/api/TemplateService.java @@ -9,11 +9,14 @@ import java.util.Arrays; import java.util.List; +/** + * In charge of {@link Template} and {@link TemplateGroup} look up. + */ public class TemplateService { private ContentManagementSystem contentManagementSystem; - TemplateService( ContentManagementSystem contentManagementSystem ) { + TemplateService(ContentManagementSystem contentManagementSystem) { this.contentManagementSystem = contentManagementSystem; } @@ -24,29 +27,30 @@ public class TemplateService { * @return Only the templategroups that the current logged in user has the permissions to see * @throws NoPermissionException If the current user isn't superadmin */ - public TemplateGroup[] getTemplatesGroups( TextDocument textDocument ) throws NoPermissionException { + public TemplateGroup[] getTemplatesGroups(TextDocument textDocument) throws NoPermissionException { UserDomainObject user = contentManagementSystem.getCurrentUser().getInternal(); - TemplateGroupDomainObject[] internalTemplates = getTemplateMapper().getAllTemplateGroupsAvailableForUserOnDocument( user, textDocument.getId() ); - return createTemplateGroupArray( internalTemplates ); + TemplateGroupDomainObject[] internalTemplates = getTemplateMapper().getAllTemplateGroupsAvailableForUserOnDocument(user, textDocument.getId()); + return createTemplateGroupArray(internalTemplates); } private TemplateMapper getTemplateMapper() { - return contentManagementSystem.getInternal().getTemplateMapper() ; + return contentManagementSystem.getInternal().getTemplateMapper(); } /** * Get all the template groups found in the system. + * * @return An array of template groups */ public TemplateGroup[] getAllTemplateGroups() { TemplateGroupDomainObject[] templateGroupDomainObject = getTemplateMapper().getAllTemplateGroups(); - return createTemplateGroupArray( templateGroupDomainObject ); + return createTemplateGroupArray(templateGroupDomainObject); } - private TemplateGroup[] createTemplateGroupArray( TemplateGroupDomainObject[] internalTemplates ) { + private TemplateGroup[] createTemplateGroupArray(TemplateGroupDomainObject[] internalTemplates) { TemplateGroup[] result = new TemplateGroup[internalTemplates.length]; for (int i = 0; i < internalTemplates.length; i++) { - result[i] = new TemplateGroup( internalTemplates[i] ); + result[i] = new TemplateGroup(internalTemplates[i]); } return result; } @@ -58,12 +62,12 @@ private TemplateGroup[] createTemplateGroupArray( TemplateGroupDomainObject[] in * @return An array of all the Templates in the given TemplateGroup * @throws NoPermissionException If the current user doesn't have permission to list the templates in the templategroup. */ - public Template[] getTemplates( TemplateGroup templateGroup ) throws NoPermissionException { - List templates = getTemplateMapper().getTemplatesInGroup( templateGroup.getInternal() ); - - List