Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r06ae1e4daee7838ea5ceba04ab67633ebfc78997 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 06ae1e4daee7838ea5ceba04ab67633ebfc78997) +++ lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -660,5 +660,7 @@ config.enable.collapsing.subcourses =Enable collapsing of subcourses label.manage.tool.consumers.delete =Are you sure you want to delete this LTI consumer? sysadmin.server.delete =Are you sure you want to to delete this integrated server? - +config.header.etherpad =Etherpad +config.etherpad.server.url =Server URL +config.etherpad.api.key =API key #======= End labels: Exported 652 labels for en AU ===== Index: lams_build/3rdParty.userlibraries =================================================================== diff -u -r3b8c76397a6db09a9bd14ad2afaacf6a38639341 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_build/3rdParty.userlibraries (.../3rdParty.userlibraries) (revision 3b8c76397a6db09a9bd14ad2afaacf6a38639341) +++ lams_build/3rdParty.userlibraries (.../3rdParty.userlibraries) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -36,6 +36,6 @@ - + Index: lams_build/build.xml =================================================================== diff -u -r3b8c76397a6db09a9bd14ad2afaacf6a38639341 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_build/build.xml (.../build.xml) (revision 3b8c76397a6db09a9bd14ad2afaacf6a38639341) +++ lams_build/build.xml (.../build.xml) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -451,12 +451,12 @@ file="lib/basiclti-util/signpost.module.xml" overwrite="true" verbose="true" /> - + - Index: lams_build/conf/j2ee/jboss-deployment-structure.xml =================================================================== diff -u -r3cdcc421a982fe488cd3c991e2a9d4f3af0ae778 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_build/conf/j2ee/jboss-deployment-structure.xml (.../jboss-deployment-structure.xml) (revision 3cdcc421a982fe488cd3c991e2a9d4f3af0ae778) +++ lams_build/conf/j2ee/jboss-deployment-structure.xml (.../jboss-deployment-structure.xml) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -52,6 +52,7 @@ + - - - - - - - - - true - - - - - - - - PROPAGATION_REQUIRED - - - - + + + + + + + + + + true + + + + + + + + PROPAGATION_REQUIRED + + + + + + + + + + + + true + + + + + + + + PROPAGATION_REQUIRED + + + + @@ -639,11 +659,11 @@ - - - - - + + + + + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20200326.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20200326.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20200326.sql (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -0,0 +1,14 @@ +SET AUTOCOMMIT = 0; +set FOREIGN_KEY_CHECKS = 0; + +-- LDEV-4997 Etherpad as service + +INSERT INTO lams_configuration (config_key, config_value, description_key, header_name, format, required) +VALUES ('EtherpadServerUrl', 'http://localhost:9001', 'config.etherpad.server.url', 'config.header.etherpad', 'STRING', 0), + ('EtherpadApiKey', '', 'config.etherpad.api.key', 'config.header.etherpad', 'STRING', 0); + + +COMMIT; +SET AUTOCOMMIT = 1; +set FOREIGN_KEY_CHECKS = 1; + Index: lams_common/src/java/org/lamsfoundation/lams/etherpad/EtherpadException.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/etherpad/EtherpadException.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/etherpad/EtherpadException.java (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -0,0 +1,11 @@ +package org.lamsfoundation.lams.etherpad; + +public class EtherpadException extends Exception { + public EtherpadException(String message, Throwable cause) { + super(message, cause); + } + + public EtherpadException(String message) { + super(message); + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/etherpad/service/EtherpadService.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/etherpad/service/EtherpadService.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/etherpad/service/EtherpadService.java (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -0,0 +1,158 @@ +package org.lamsfoundation.lams.etherpad.service; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.Cookie; + +import org.apache.commons.lang.StringUtils; +import org.lamsfoundation.lams.etherpad.EtherpadException; +import org.lamsfoundation.lams.etherpad.util.EtherpadUtil; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.ConfigurationKeys; + +import net.gjerull.etherpad.client.EPLiteClient; +import net.gjerull.etherpad.client.EPLiteException; + +public class EtherpadService implements IEtherpadService { + + private EPLiteClient client = null; + + @SuppressWarnings("unchecked") + @Override + public Map createPad(String groupIdentifier) throws EtherpadException { + EPLiteClient client = getClient(); + + Map result = new HashMap<>(); + result.put("client", client); + + // create Etherpad Group assossiated with this session + Map map = client.createGroupIfNotExistsFor(groupIdentifier); + String groupId = (String) map.get("groupID"); + result.put("groupId", groupId); + String padId = EtherpadUtil.getPadId(groupId); + result.put("padId", padId); + + boolean isPadAlreadyCreated = false; + try { + client.createGroupPad(groupId, DEFAULT_PAD_NAME); + } catch (EPLiteException e) { + // allow recreating existing pads + if ("padName does already exist".equals(e.getMessage())) { + isPadAlreadyCreated = true; + // throw exception in all other cases + } else { + throw new EtherpadException("Exception while creating a group etherpad", e); + } + } + + result.put("isPadAlreadyCreated", isPadAlreadyCreated); + + // gets read-only id + String etherpadReadOnlyId = (String) client.getReadOnlyID(padId).get("readOnlyID"); + result.put("readOnlyId", etherpadReadOnlyId); + return result; + } + + @Override + public EPLiteClient getClient() throws EtherpadException { + if (client == null) { + // get the API key from the configuration and create EPLiteClient using it + String etherpadServerUrl = Configuration.get(ConfigurationKeys.ETHERPAD_SERVER_URL); + String etherpadApiKey = Configuration.get(ConfigurationKeys.ETHERPAD_API_KEY); + if (StringUtils.isBlank(etherpadServerUrl) || StringUtils.isBlank(etherpadApiKey)) { + throw new EtherpadException("Etherpad is not configured in sysadmin console"); + } + + // create EPLiteClient + client = new EPLiteClient(etherpadServerUrl, etherpadApiKey); + } + return client; + } + + /** + * Constructs cookie to be stored at a clientside browser. + */ + @Override + public Cookie createCookie(String etherpadSessionIds) throws EtherpadException { + String etherpadServerUrl = Configuration.get(ConfigurationKeys.ETHERPAD_SERVER_URL); + URI uri; + try { + uri = new URI(etherpadServerUrl); + } catch (URISyntaxException e) { + throw new EtherpadException("Etherpad is not correctly configured in sysadmin console", e); + } + //regex to get the top level part of a domain + Pattern p = Pattern.compile( + "^(?:\\w+://)?[^:?#/\\s]*?([^.\\s]+\\.(?:[a-z]{2,}|co\\.uk|org\\.uk|ac\\.uk|edu\\.au|org\\.au|com\\.au|edu\\.sg|com\\.sg|net\\.sg|org\\.sg|gov\\.sg|per\\.sg))(?:[:?#/]|$)"); + // eg: uri.getHost() will return "www.foo.com" + Matcher m = p.matcher(uri.getHost()); + String topLevelDomain = m.matches() ? "." + m.group(1) : uri.getHost(); + + Cookie etherpadSessionCookie = new Cookie("sessionID", etherpadSessionIds); + etherpadSessionCookie.setDomain(topLevelDomain); + // A negative value means that the cookie is not stored persistently and will be deleted when the Web browser + // exits. A zero value causes the cookie to be deleted. + etherpadSessionCookie.setMaxAge(-1); + etherpadSessionCookie.setPath("/"); + + return etherpadSessionCookie; + } + + /** + * Returns valid Etherpad session. Returns existing one if finds such one and creates the new one otherwise + */ + @Override + @SuppressWarnings("unchecked") + public String getExistingSessionID(String authorId, String etherpadGroupId, Map etherpadSessions) + throws EtherpadException { + String etherpadSessionId = null; + + // search for already existing user's session + boolean isValidForMoreThan1Hour = false; + for (String etherpadSessionIdIter : etherpadSessions.keySet()) { + Map sessessionAttributes = (Map) etherpadSessions + .get(etherpadSessionIdIter); + String groupIdIter = (String) sessessionAttributes.get("groupID"); + if (groupIdIter.equals(etherpadGroupId)) { + + // check session expiration date + long validUntil = (Long) sessessionAttributes.get("validUntil") * 1000; + long now = System.currentTimeMillis(); + isValidForMoreThan1Hour = ((validUntil - now) > 0) && ((validUntil - now) >= 60 * 60 * 1000); + + //use existing session if it's valid for more than 1 hour + if (isValidForMoreThan1Hour) { + etherpadSessionId = etherpadSessionIdIter; + break; + + } else { + // can't delete expired sessions as Etherpad throws an exception. Nonetheless it returns expired + // ones when client.listSessionsOfAuthor(authorId) is requested + } + } + + } + + // if session with validity of more than 1 hour doesn't exist yet - create it + if (etherpadSessionId == null) { + EPLiteClient client = getClient(); + Map map2 = client.createSession(etherpadGroupId, authorId, 24); + etherpadSessionId = (String) map2.get("sessionID"); + } + + return etherpadSessionId; + } + + @SuppressWarnings("unchecked") + public String createAuthor(Integer userId, String userName) throws EtherpadException { + EPLiteClient client = getClient(); + + Map map = client.createAuthorIfNotExistsFor(userId.toString(), userName); + return map.get("authorID"); + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/etherpad/service/IEtherpadService.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/etherpad/service/IEtherpadService.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/etherpad/service/IEtherpadService.java (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -0,0 +1,39 @@ +package org.lamsfoundation.lams.etherpad.service; + +import java.util.Map; + +import javax.servlet.http.Cookie; + +import org.lamsfoundation.lams.etherpad.EtherpadException; + +import net.gjerull.etherpad.client.EPLiteClient; + +public interface IEtherpadService { + + String DEFAULT_PAD_NAME = "LAMS-pad"; + + String PREFIX_REGULAR_GROUP = "LAMS-group-"; + + /** + * Creates EPLiteClient that will make calls to Etherpad server. Throws DokumaranConfigurationException + * + * @throws DokumaranConfigurationException + * if the etherpad is not configured appropriately (either server URL or API key). + */ + EPLiteClient getClient() throws EtherpadException; + + Map createPad(String groupIdentifier) throws EtherpadException; + + /** + * Constructs cookie to be stored at a clientside browser. + */ + Cookie createCookie(String etherpadSessionIds) throws EtherpadException; + + /** + * Returns valid Etherpad session. Returns existing one if finds such one and creates the new one otherwise + */ + String getExistingSessionID(String authorId, String etherpadGroupId, Map etherpadSessions) + throws EtherpadException; + + String createAuthor(Integer userId, String userName) throws EtherpadException; +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/etherpad/util/EtherpadUtil.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/etherpad/util/EtherpadUtil.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/etherpad/util/EtherpadUtil.java (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -0,0 +1,10 @@ +package org.lamsfoundation.lams.etherpad.util; + +import org.lamsfoundation.lams.etherpad.service.IEtherpadService; + +public class EtherpadUtil { + + public static String getPadId(String groupId) { + return groupId + "$" + IEtherpadService.DEFAULT_PAD_NAME; + } +} Index: lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java =================================================================== diff -u -rebb598b9d631fa479aef19110dc7b8c2cce0575b -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java (.../ConfigurationKeys.java) (revision ebb598b9d631fa479aef19110dc7b8c2cce0575b) +++ lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java (.../ConfigurationKeys.java) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -290,4 +290,7 @@ // LDEV-4594 / LDEV-4583 Allow/Block access to index.do for integration learners. Default to false - do not allow direct access. public static String ALLOW_DIRECT_ACCESS_FOR_INTEGRATION_LEARNERS = "AllowDirectAccessIntgrtnLrnr"; + // LDEV-4997 Etherpad as service + public static String ETHERPAD_SERVER_URL = "EtherpadServerUrl"; + public static String ETHERPAD_API_KEY = "EtherpadApiKey"; } Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/net/gjerull/etherpad/client/EPLiteClient.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/net/gjerull/etherpad/client/EPLiteConnection.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/net/gjerull/etherpad/client/EPLiteException.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/net/gjerull/etherpad/client/GETRequest.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/net/gjerull/etherpad/client/POSTRequest.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/net/gjerull/etherpad/client/Request.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dao/DokumaranConfigItemDAO.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dao/hibernate/DokumaranConfigItemDAOHibernate.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dokumaranApplicationContext.xml =================================================================== diff -u -r713a4d2055ba7766354709db2ae65dacfb5d2b1a -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dokumaranApplicationContext.xml (.../dokumaranApplicationContext.xml) (revision 713a4d2055ba7766354709db2ae65dacfb5d2b1a) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/dokumaranApplicationContext.xml (.../dokumaranApplicationContext.xml) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -29,11 +29,6 @@ - - - - - @@ -56,21 +51,18 @@ - - - - - - + + + Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/DokumaranConfigItem.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/DokumaranSession.java =================================================================== diff -u -r20aa6cbca9fc96d341080e6ad39f82593443f792 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/DokumaranSession.java (.../DokumaranSession.java) (revision 20aa6cbca9fc96d341080e6ad39f82593443f792) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/model/DokumaranSession.java (.../DokumaranSession.java) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -35,7 +35,7 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; -import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; +import org.lamsfoundation.lams.etherpad.util.EtherpadUtil; /** * Dokumaran session @@ -189,8 +189,6 @@ } public String getPadId() { - // HashUtil.sha1(DokumaranConstants.DEFAULT_PAD_NAME + sessionId); - return etherpadGroupId + "$" + DokumaranConstants.DEFAULT_PAD_NAME; + return EtherpadUtil.getPadId(etherpadGroupId); } - -} +} \ No newline at end of file Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranConfigurationException.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java =================================================================== diff -u -rb8cffb90895b237f8974633720e6c491699117f4 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java (.../DokumaranService.java) (revision b8cffb90895b237f8974633720e6c491699117f4) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/DokumaranService.java (.../DokumaranService.java) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -24,28 +24,25 @@ package org.lamsfoundation.lams.tool.dokumaran.service; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.servlet.http.Cookie; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; +import org.lamsfoundation.lams.etherpad.EtherpadException; +import org.lamsfoundation.lams.etherpad.service.IEtherpadService; import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; -import org.lamsfoundation.lams.logevent.service.ILogEventService; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; @@ -59,14 +56,12 @@ import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; import org.lamsfoundation.lams.tool.ToolSessionManager; import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; -import org.lamsfoundation.lams.tool.dokumaran.dao.DokumaranConfigItemDAO; import org.lamsfoundation.lams.tool.dokumaran.dao.DokumaranDAO; import org.lamsfoundation.lams.tool.dokumaran.dao.DokumaranSessionDAO; import org.lamsfoundation.lams.tool.dokumaran.dao.DokumaranUserDAO; import org.lamsfoundation.lams.tool.dokumaran.dto.ReflectDTO; import org.lamsfoundation.lams.tool.dokumaran.dto.SessionDTO; import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; -import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; import org.lamsfoundation.lams.tool.exception.DataMissingException; @@ -81,7 +76,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import net.gjerull.etherpad.client.EPLiteClient; -import net.gjerull.etherpad.client.EPLiteException; /** * @author Dapeng.Ni @@ -95,8 +89,6 @@ private DokumaranSessionDAO dokumaranSessionDao; - private DokumaranConfigItemDAO dokumaranConfigItemDAO; - // tool service private IToolContentHandler dokumaranToolContentHandler; @@ -106,18 +98,16 @@ private ILamsToolService toolService; - private ILogEventService logEventService; - private IUserManagementService userManagementService; private IExportToolContentService exportContentService; private ICoreNotebookService coreNotebookService; + private IEtherpadService etherpadService; + private DokumaranOutputFactory dokumaranOutputFactory; - private EPLiteClient client = null; - // ******************************************************************************* // Service method // ******************************************************************************* @@ -356,16 +346,6 @@ } @Override - public DokumaranConfigItem getConfigItem(String key) { - return dokumaranConfigItemDAO.getConfigItemByKey(key); - } - - @Override - public void saveOrUpdateDokumaranConfigItem(DokumaranConfigItem item) { - dokumaranConfigItemDAO.saveOrUpdate(item); - } - - @Override public void saveOrUpdateDokumaran(Dokumaran dokumaran) { dokumaranDao.saveObject(dokumaran); } @@ -401,7 +381,7 @@ //finish Etherpad session. Encapsulate it in try-catch block as we don't want it to affect regular LAMS workflow. try { - EPLiteClient client = initializeEPLiteClient(); + EPLiteClient client = etherpadService.getClient(); DokumaranSession session = dokumaranSessionDao.getSessionBySessionId(toolSessionId); String groupId = session.getEtherpadGroupId(); @@ -758,7 +738,7 @@ } @Override - public void createPad(Dokumaran dokumaran, DokumaranSession session) throws DokumaranConfigurationException { + public void createPad(Dokumaran dokumaran, DokumaranSession session) throws DokumaranApplicationException { Long toolSessionId = session.getSessionId(); Long toolContentId = dokumaran.getContentId(); String groupIdentifier = DokumaranConstants.PREFIX_REGULAR_GROUP + toolSessionId; @@ -789,27 +769,19 @@ } } - EPLiteClient client = initializeEPLiteClient(); - - // create Etherpad Group assossiated with this session - Map map = client.createGroupIfNotExistsFor(groupIdentifier); - String groupId = (String) map.get("groupID"); - session.setEtherpadGroupId(groupId); - String padId = session.getPadId(); - - boolean isPadAlreadyCreated = false; + Map result; try { - client.createGroupPad(groupId, DokumaranConstants.DEFAULT_PAD_NAME); - } catch (EPLiteException e) { - // allow recreating existing pads - if ("padName does already exist".equals(e.getMessage())) { - isPadAlreadyCreated = true; - // throw exception in all other cases - } else { - throw e; - } + result = etherpadService.createPad(groupIdentifier); + } catch (EtherpadException e) { + throw new DokumaranApplicationException("Exception while creating an etherpad pad", e); } + EPLiteClient client = (EPLiteClient) result.get("client"); + String groupId = (String) result.get("groupId"); + String padId = (String) result.get("padId"); + boolean isPadAlreadyCreated = (boolean) result.get("isPadAlreadyCreated"); + + session.setEtherpadGroupId(groupId); // set initial content if (!dokumaran.isSharedPadEnabled() || !isPadAlreadyCreated) { String etherpadHtml = "" @@ -819,8 +791,8 @@ } // gets read-only id - String etherpadReadOnlyId = (String) client.getReadOnlyID(padId).get("readOnlyID"); - session.setEtherpadReadOnlyId(etherpadReadOnlyId); + String readOnlyId = (String) result.get("readOnlyId"); + session.setEtherpadReadOnlyId(readOnlyId); dokumaranSessionDao.saveObject(session); } @@ -836,9 +808,10 @@ : ToolCompletionStatus.ACTIVITY_ATTEMPTED, null, null); } + @SuppressWarnings("unchecked") @Override public Cookie createEtherpadCookieForLearner(DokumaranUser user, DokumaranSession session) - throws DokumaranConfigurationException, URISyntaxException, DokumaranApplicationException { + throws DokumaranApplicationException, EtherpadException { String groupId = session.getEtherpadGroupId(); //don't allow sessions that has had problems with pad initializations. they could be fixed in monitoring by a teacher @@ -847,29 +820,25 @@ "This session has had problems with initialization. Please seek help from your teacher."); } - EPLiteClient client = initializeEPLiteClient(); + EPLiteClient client = etherpadService.getClient(); String userName = user.getFirstName() + " " + user.getLastName(); - Map map = client.createAuthorIfNotExistsFor(user.getUserId().toString(), userName); - String authorId = map.get("authorID"); + Map map = client.createAuthorIfNotExistsFor(user.getUserId().toString(), userName); + String authorId = (String) map.get("authorID"); // search for already existing user's session at Etherpad server Map etherpadSessions = client.listSessionsOfAuthor(authorId); - String etherpadSessionId = getEtherpadSession(authorId, groupId, etherpadSessions); - - return createEtherpadCookie(etherpadSessionId); + String etherpadSessionId = etherpadService.getExistingSessionID(authorId, groupId, etherpadSessions); + return etherpadService.createCookie(etherpadSessionId); } + @SuppressWarnings("unchecked") @Override - public Cookie createEtherpadCookieForMonitor(UserDTO user, Long contentId) - throws DokumaranConfigurationException, URISyntaxException { + public Cookie createEtherpadCookieForMonitor(UserDTO user, Long contentId) throws EtherpadException { - EPLiteClient client = initializeEPLiteClient(); + String authorId = etherpadService.createAuthor(user.getUserID(), + user.getFirstName() + " " + user.getLastName()); - String userName = user.getFirstName() + " " + user.getLastName(); - Map map = client.createAuthorIfNotExistsFor(user.getUserID().toString(), userName); - String authorId = map.get("authorID"); - List sessionList = dokumaranSessionDao.getByContentId(contentId); if (sessionList.isEmpty()) { return null; @@ -883,7 +852,8 @@ // find according session String etherpadSessionIds = ""; - Map etherpadSessions = client.listSessionsOfAuthor(authorId); + EPLiteClient client = etherpadService.getClient(); + Map etherpadSessions = client.listSessionsOfAuthor(authorId); for (DokumaranSession session : sessionList) { String groupId = session.getEtherpadGroupId(); @@ -892,104 +862,14 @@ continue; } - String etherpadSessionId = getEtherpadSession(authorId, groupId, etherpadSessions); + String etherpadSessionId = etherpadService.getExistingSessionID(authorId, groupId, etherpadSessions); etherpadSessionIds += StringUtils.isEmpty(etherpadSessionIds) ? etherpadSessionId : "," + etherpadSessionId; } - return createEtherpadCookie(etherpadSessionIds); + return etherpadService.createCookie(etherpadSessionIds); } - /** - * Returns valid Etherpad session. Returns existing one if finds such one and creates the new one otherwise - */ - private String getEtherpadSession(String authorId, String etherpadGroupId, Map etherpadSessions) { - String etherpadSessionId = null; - - // search for already existing user's session - boolean isValidForMoreThan1Hour = false; - for (String etherpadSessionIdIter : (Set) etherpadSessions.keySet()) { - Map sessessionAttributes = (Map) etherpadSessions - .get(etherpadSessionIdIter); - String groupIdIter = (String) sessessionAttributes.get("groupID"); - if (groupIdIter.equals(etherpadGroupId)) { - - // check session expiration date - long validUntil = (Long) sessessionAttributes.get("validUntil") * 1000; - long now = System.currentTimeMillis(); - isValidForMoreThan1Hour = ((validUntil - now) > 0) && ((validUntil - now) >= 60 * 60 * 1000); - - //use existing session if it's valid for more than 1 hour - if (isValidForMoreThan1Hour) { - etherpadSessionId = etherpadSessionIdIter; - break; - - } else { - // can't delete expired sessions as Etherpad throws an exception. Nonetheless it returns expired - // ones when client.listSessionsOfAuthor(authorId) is requested - } - } - - } - - // if session with validity of more than 1 hour doesn't exist yet - create it - if (etherpadSessionId == null) { - Map map2 = client.createSession(etherpadGroupId, authorId, 24); - etherpadSessionId = (String) map2.get("sessionID"); - } - - return etherpadSessionId; - } - - /** - * Constructs cookie to be stored at a clientside browser. - * - * @param etherpadSessionIds - * @return - * @throws URISyntaxException - */ - private Cookie createEtherpadCookie(String etherpadSessionIds) throws URISyntaxException { - DokumaranConfigItem etherpadServerUrlConfig = getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); - String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); - URI uri = new URI(etherpadServerUrl); - //regex to get the top level part of a domain - Pattern p = Pattern.compile( - "^(?:\\w+://)?[^:?#/\\s]*?([^.\\s]+\\.(?:[a-z]{2,}|co\\.uk|org\\.uk|ac\\.uk|edu\\.au|org\\.au|com\\.au|edu\\.sg|com\\.sg|net\\.sg|org\\.sg|gov\\.sg|per\\.sg))(?:[:?#/]|$)"); - // eg: uri.getHost() will return "www.foo.com" - Matcher m = p.matcher(uri.getHost()); - String topLevelDomain = m.matches() ? "." + m.group(1) : uri.getHost(); - - Cookie etherpadSessionCookie = new Cookie("sessionID", etherpadSessionIds); - etherpadSessionCookie.setDomain(topLevelDomain); - // A negative value means that the cookie is not stored persistently and will be deleted when the Web browser - // exits. A zero value causes the cookie to be deleted. - etherpadSessionCookie.setMaxAge(-1); - etherpadSessionCookie.setPath("/"); - - return etherpadSessionCookie; - } - @Override - public EPLiteClient initializeEPLiteClient() throws DokumaranConfigurationException { - if (client == null) { - // get the API key from the config table and create EPLiteClient using it - DokumaranConfigItem etherpadServerUrlConfig = getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); - DokumaranConfigItem etherpadApiKeyConfig = getConfigItem(DokumaranConfigItem.KEY_API_KEY); - if (etherpadApiKeyConfig == null || etherpadApiKeyConfig.getConfigValue() == null - || etherpadServerUrlConfig == null || etherpadServerUrlConfig.getConfigValue() == null) { - throw new DokumaranConfigurationException("Dokumaran settings are not configured. apiKeyConfig=" - + etherpadApiKeyConfig + " etherpadServerUrlConfig=" + etherpadServerUrlConfig - + " Please seek help from your administrator"); - } - - // create EPLiteClient - String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); - String etherpadApiKey = etherpadApiKeyConfig.getConfigValue(); - client = new EPLiteClient(etherpadServerUrl, etherpadApiKey); - } - return client; - } - - @Override public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { if (toolSessionId == null) { DokumaranService.log.error("Fail to leave tool Session based on null tool session id."); @@ -1071,10 +951,6 @@ // ***************************************************************************** // set methods for Spring Bean // ***************************************************************************** - public void setLogEventService(ILogEventService logEventService) { - this.logEventService = logEventService; - } - public void setMessageService(MessageService messageService) { this.messageService = messageService; } @@ -1087,10 +963,6 @@ this.dokumaranSessionDao = dokumaranSessionDao; } - public void setDokumaranConfigItemDAO(DokumaranConfigItemDAO dokumaranConfigItemDAO) { - this.dokumaranConfigItemDAO = dokumaranConfigItemDAO; - } - public void setDokumaranToolContentHandler(IToolContentHandler dokumaranToolContentHandler) { this.dokumaranToolContentHandler = dokumaranToolContentHandler; } @@ -1115,6 +987,10 @@ this.coreNotebookService = coreNotebookService; } + public void setEtherpadService(IEtherpadService etherpadService) { + this.etherpadService = etherpadService; + } + public DokumaranOutputFactory getDokumaranOutputFactory() { return dokumaranOutputFactory; } Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java =================================================================== diff -u -rb8cffb90895b237f8974633720e6c491699117f4 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java (.../IDokumaranService.java) (revision b8cffb90895b237f8974633720e6c491699117f4) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/service/IDokumaranService.java (.../IDokumaranService.java) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -24,23 +24,20 @@ package org.lamsfoundation.lams.tool.dokumaran.service; import java.io.IOException; -import java.net.URISyntaxException; import java.util.List; import javax.servlet.http.Cookie; +import org.lamsfoundation.lams.etherpad.EtherpadException; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.tool.dokumaran.dto.ReflectDTO; import org.lamsfoundation.lams.tool.dokumaran.dto.SessionDTO; import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; -import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; import org.lamsfoundation.lams.tool.service.ICommonToolService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; -import net.gjerull.etherpad.client.EPLiteClient; - /** * @author Dapeng.Ni * @@ -133,28 +130,14 @@ boolean checkTimeLimitExceeded(Dokumaran dokumaran); Cookie createEtherpadCookieForLearner(DokumaranUser user, DokumaranSession session) - throws DokumaranConfigurationException, URISyntaxException, DokumaranApplicationException; + throws DokumaranApplicationException, EtherpadException; - Cookie createEtherpadCookieForMonitor(UserDTO user, Long contentId) - throws DokumaranConfigurationException, URISyntaxException; + Cookie createEtherpadCookieForMonitor(UserDTO user, Long contentId) throws EtherpadException; /** - * Creates EPLiteClient that will make calls to Etherpad server. Throws DokumaranConfigurationException tf the tool - * is not configured appropriately (either etherpadServerUrl or etherpadApiKey is missing). - * - * @return - * @throws DokumaranConfigurationException - */ - EPLiteClient initializeEPLiteClient() throws DokumaranConfigurationException; - - /** * Creates pad on Etherpad server side. - * - * @param dokumaran - * @param session - * @throws DokumaranConfigurationException */ - void createPad(Dokumaran dokumaran, DokumaranSession session) throws DokumaranConfigurationException; + void createPad(Dokumaran dokumaran, DokumaranSession session) throws DokumaranApplicationException; // ********** for user methods ************* /** @@ -189,10 +172,6 @@ */ List getUsersBySession(Long toolSessionId); - DokumaranConfigItem getConfigItem(String key); - - void saveOrUpdateDokumaranConfigItem(DokumaranConfigItem item); - /** * Save or update dokumaran into database. * Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/AdminController.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningController.java =================================================================== diff -u -r3ee06bc1b00b1673399c1871a73cfa1d8ec2c0db -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningController.java (.../LearningController.java) (revision 3ee06bc1b00b1673399c1871a73cfa1d8ec2c0db) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/LearningController.java (.../LearningController.java) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -34,21 +34,23 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.lamsfoundation.lams.etherpad.EtherpadException; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; import org.lamsfoundation.lams.tool.ToolAccessMode; import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; -import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranUser; import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranApplicationException; -import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranConfigurationException; import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; import org.lamsfoundation.lams.tool.dokumaran.web.form.ReflectionForm; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; @@ -78,14 +80,16 @@ * method run successfully. * * This method will avoid read database again and lost un-saved resouce item lost when user "refresh page", + * + * @throws EtherpadException * * @throws DokumaranConfigurationException * @throws URISyntaxException * */ @RequestMapping("/start") private String start(HttpServletRequest request, HttpServletResponse response) - throws DokumaranConfigurationException, DokumaranApplicationException, URISyntaxException { + throws DokumaranApplicationException, EtherpadException { // initial Session Map SessionMap sessionMap = new SessionMap<>(); @@ -189,14 +193,11 @@ sessionMap.put(DokumaranConstants.ATTR_DOKUMARAN, dokumaran); // get the API key from the config table and add it to the session - DokumaranConfigItem etherpadServerUrlConfig = dokumaranService - .getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); - DokumaranConfigItem apiKeyConfig = dokumaranService.getConfigItem(DokumaranConfigItem.KEY_API_KEY); - if (apiKeyConfig == null || apiKeyConfig.getConfigValue() == null || etherpadServerUrlConfig == null - || etherpadServerUrlConfig.getConfigValue() == null) { + String etherpadServerUrl = Configuration.get(ConfigurationKeys.ETHERPAD_SERVER_URL); + String etherpadApiKey = Configuration.get(ConfigurationKeys.ETHERPAD_API_KEY); + if (StringUtils.isBlank(etherpadServerUrl) || StringUtils.isBlank(etherpadApiKey)) { return "pages/learning/notconfigured"; } - String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); request.setAttribute(DokumaranConstants.KEY_ETHERPAD_SERVER_URL, etherpadServerUrl); //time limit Index: lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/MonitoringController.java =================================================================== diff -u -rf2ad75cef0c507a64877942631fee13efbc6ed50 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/MonitoringController.java (.../MonitoringController.java) (revision f2ad75cef0c507a64877942631fee13efbc6ed50) +++ lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/controller/MonitoringController.java (.../MonitoringController.java) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.PrintWriter; -import java.net.URISyntaxException; import java.util.List; import javax.servlet.ServletException; @@ -34,16 +33,18 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.lamsfoundation.lams.etherpad.EtherpadException; import org.lamsfoundation.lams.tool.dokumaran.DokumaranConstants; import org.lamsfoundation.lams.tool.dokumaran.dto.ReflectDTO; import org.lamsfoundation.lams.tool.dokumaran.dto.SessionDTO; import org.lamsfoundation.lams.tool.dokumaran.model.Dokumaran; -import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranConfigItem; import org.lamsfoundation.lams.tool.dokumaran.model.DokumaranSession; -import org.lamsfoundation.lams.tool.dokumaran.service.DokumaranConfigurationException; import org.lamsfoundation.lams.tool.dokumaran.service.IDokumaranService; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.WebUtil; import org.lamsfoundation.lams.web.session.SessionManager; import org.lamsfoundation.lams.web.util.AttributeNames; @@ -62,8 +63,7 @@ private IDokumaranService dokumaranService; @RequestMapping("/summary") - private String summary(HttpServletRequest request, HttpServletResponse response) - throws DokumaranConfigurationException, URISyntaxException { + private String summary(HttpServletRequest request, HttpServletResponse response) throws EtherpadException { // initial Session Map SessionMap sessionMap = new SessionMap<>(); request.getSession().setAttribute(sessionMap.getSessionID(), sessionMap); @@ -101,12 +101,11 @@ sessionMap.put(DokumaranConstants.ATTR_IS_GROUPED_ACTIVITY, dokumaranService.isGroupedActivity(contentId)); // get the API key from the config table and add it to the session - DokumaranConfigItem etherpadServerUrlConfig = dokumaranService - .getConfigItem(DokumaranConfigItem.KEY_ETHERPAD_URL); - if (etherpadServerUrlConfig == null || etherpadServerUrlConfig.getConfigValue() == null) { + String etherpadServerUrl = Configuration.get(ConfigurationKeys.ETHERPAD_SERVER_URL); + String etherpadApiKey = Configuration.get(ConfigurationKeys.ETHERPAD_API_KEY); + if (StringUtils.isBlank(etherpadServerUrl) || StringUtils.isBlank(etherpadApiKey)) { return "pages/learning/notconfigured"; } - String etherpadServerUrl = etherpadServerUrlConfig.getConfigValue(); request.setAttribute(DokumaranConstants.KEY_ETHERPAD_SERVER_URL, etherpadServerUrl); HttpSession ss = SessionManager.getSession(); @@ -125,7 +124,7 @@ @RequestMapping("/fixFaultySession") private void fixFaultySession(HttpServletRequest request, HttpServletResponse response) - throws DokumaranConfigurationException, ServletException, IOException { + throws ServletException, IOException { Long toolSessionId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_SESSION_ID); DokumaranSession session = dokumaranService.getDokumaranSessionBySessionId(toolSessionId); @@ -148,7 +147,7 @@ /** * Stores date when user has started activity with time limit - * + * * @throws IOException * @throws JSONException */ @@ -161,7 +160,7 @@ /** * Stores date when user has started activity with time limit - * + * * @throws IOException * @throws JSONException */ Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/src/java/org/lamsfoundation/lams/tool/dokumaran/web/form/AdminForm.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_doku/web/WEB-INF/tags/ImgButtonWrapper.tag =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -r5ce80833bb0828de219fc5b59e9e73c365da8559 --- lams_tool_doku/web/WEB-INF/tags/ImgButtonWrapper.tag (.../ImgButtonWrapper.tag) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_doku/web/WEB-INF/tags/ImgButtonWrapper.tag (.../ImgButtonWrapper.tag) (revision 5ce80833bb0828de219fc5b59e9e73c365da8559) @@ -1,37 +1,37 @@ -<% -/**************************************************************** - * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) - * ============================================================= - * License Information: http://lamsfoundation.org/licensing/lams/2.0/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2.0 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - * - * http://www.gnu.org/licenses/gpl.txt - * **************************************************************** - */ - - /** - * ImgButtonWrapper.tag - * Author: Mitchell Seaton - * Description: Simple wrapper that will display buttons correctly when RTL page rendering is used. - */ - - %> -<%@ tag body-content="scriptless" %> -
-
- -
-
+<% +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + /** + * ImgButtonWrapper.tag + * Author: Mitchell Seaton + * Description: Simple wrapper that will display buttons correctly when RTL page rendering is used. + */ + + %> +<%@ tag body-content="scriptless" %> +
+
+ +
+
Fisheye: Tag 5ce80833bb0828de219fc5b59e9e73c365da8559 refers to a dead (removed) revision in file `lams_tool_doku/web/pages/admin/config.jsp'. Fisheye: No comparison available. Pass `N' to diff?