提交 9522dfbc 编写于 作者: M meyerd

Activiti Cycle: Architectural refactorings in cycle.

上级 7a349fd4
......@@ -39,6 +39,7 @@
<exclude>**/RepositoryConnectorConfigurationManagerImplTest.java</exclude>
<exclude>**/TestSvnRepositoryConnector.java</exclude>
<exclude>**/SubProcessExpansionTest.java</exclude>
<exclude>**/SftpConnectorTest.java</exclude>
</excludes>
</configuration>
</plugin>
......
package org.activiti.cycle;
/**
* Context for session-scoped variables. Wraps a {@link Context}-object and
* stores it as a {@link ThreadLocal}, providing static access to it.
*
* @author daniel.meyer@camunda.com
*/
public class CycleSessionContext {
public static interface Context {
public void set(String key, Object value);
public Object get(String key);
}
private static ThreadLocal<Context> localContext = new ThreadLocal<CycleSessionContext.Context>();
public static void setInCurrentContext(String key, Object value) {
Context context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
context.set(key, value);
}
@SuppressWarnings("unchecked")
public static <T> T getFromCurrentContext(String key, Class<T> clazz) {
Context context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
Object obj = context.get(key);
if (obj != null) {
return (T) obj;
}
return null;
}
public static <T> void setInCurrentContext(Class<T> key, Object value) {
Context context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
context.set(key.getName(), value);
}
@SuppressWarnings("unchecked")
public static <T> T getFromCurrentContext(Class<T> key) {
Context context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
Object obj = context.get(key.getName());
if (obj != null) {
return (T) obj;
}
return null;
}
public static void setCurrentContext(Context context) {
localContext.set(context);
}
public static void clearCurrentContext() {
localContext.remove();
}
}
......@@ -16,7 +16,6 @@ import java.util.List;
import java.util.Map;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.incubator.connector.svn.SvnRepositoryConnector;
/**
*
......
......@@ -3,12 +3,12 @@ package org.activiti.cycle.impl;
import java.util.ArrayList;
import java.util.List;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.CycleTagContent;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity;
import org.activiti.cycle.service.CycleService;
/**
*
......@@ -49,9 +49,9 @@ public class CycleTagContentImpl implements CycleTagContent {
// But this implementation obviously sucks. Improve!
RepositoryNode node = null;
try {
node = service.getRepositoryFolder(tag.getConnectorId(), tag.getNodeId());
node = service.getRepositoryService().getRepositoryFolder(tag.getConnectorId(), tag.getNodeId());
} catch (RepositoryNodeNotFoundException ex) {
node = service.getRepositoryArtifact(tag.getConnectorId(), tag.getNodeId());
node = service.getRepositoryService().getRepositoryArtifact(tag.getConnectorId(), tag.getNodeId());
}
if (tag.hasAlias()) {
......
......@@ -6,7 +6,7 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.service.CycleService;
/**
* Helper-class for handling {@link RepositoryConnectorConfiguration}s in a
......
......@@ -7,7 +7,6 @@ import java.util.Map;
import java.util.Properties;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.plugin.ActivitiCyclePluginDefinition;
......@@ -42,8 +41,6 @@ public abstract class RepositoryConnectorConfiguration {
private static Map<Class< ? extends RepositoryConnectorConfiguration>, List<ArtifactType>> registeredArtifactTypesPerConnector = new HashMap<Class< ? extends RepositoryConnectorConfiguration>, List<ArtifactType>>();
private CycleService cycleService;
/**
* TODO: Decide if we want to keep that here
*
......@@ -159,15 +156,7 @@ public abstract class RepositoryConnectorConfiguration {
this.loginHelp = loginHelp;
}
public CycleService getCycleService() {
return cycleService;
}
public void setCycleService(CycleService cycleService) {
this.cycleService = cycleService;
}
// @Override
// public String toString() {
......
......@@ -8,6 +8,8 @@ import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.impl.ParameterizedHtmlFormTemplateAction;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleRepositoryService;
/**
* This action copies any artifact to another location. Extend it to specify the
......@@ -52,7 +54,8 @@ public abstract class AbstractCopyBaseAction extends ParameterizedHtmlFormTempla
link.setTargetArtifact(targetArtifact);
link.setComment(comment);
link.setLinkType(RepositoryArtifactLinkEntity.TYPE_COPY);
connector.getConfiguration().getCycleService().addArtifactLink(link);
CycleRepositoryService repositoryService = CycleServiceImpl.getInstance().getRepositoryService();
repositoryService.addArtifactLink(link);
}
}
......
......@@ -17,6 +17,8 @@ import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider;
import org.activiti.cycle.impl.connector.util.TransactionalConnectorUtils;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.engine.impl.util.IoUtil;
public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
......@@ -78,7 +80,8 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
link.setTargetArtifact(bpmnArtifact);
link.setComment(comment);
link.setLinkType(getLinkType());
connector.getConfiguration().getCycleService().addArtifactLink(link);
CycleRepositoryService repositoryService = CycleServiceImpl.getInstance().getRepositoryService();
repositoryService.addArtifactLink(link);
}
}
......
......@@ -11,6 +11,8 @@ import org.activiti.cycle.impl.ParameterizedHtmlFormTemplateAction;
import org.activiti.cycle.impl.connector.fs.FileSystemPluginDefinition;
import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleRepositoryService;
/**
* This action creates a technical BPMN 2.0 XML for the process engines. It
......@@ -59,7 +61,8 @@ public class CreateTechnicalBpmnXmlAction extends ParameterizedHtmlFormTemplateA
link.setTargetArtifact(targetArtifact);
link.setComment(comment);
link.setLinkType(getLinkType());
connector.getConfiguration().getCycleService().addArtifactLink(link);
CycleRepositoryService repositoryService = CycleServiceImpl.getInstance().getRepositoryService();
repositoryService.addArtifactLink(link);
}
}
......
......@@ -3,6 +3,7 @@ package org.activiti.cycle.impl.connector.signavio.provider;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.impl.connector.signavio.SignavioConnector;
import org.activiti.cycle.impl.connector.signavio.util.NewSignavioSvgApiBuilder;
import org.activiti.cycle.impl.connector.signavio.util.SignavioSvgApiBuilder;
public class SvgApiProvider extends SignavioContentRepresentationProvider {
......
......@@ -2,7 +2,6 @@ package org.activiti.cycle.impl.connector.signavio.util;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
......@@ -281,7 +280,7 @@ public class SignavioSvgApiBuilder {
if (color == null || color.length() == 0) {
color = "red";
}
// hack for making sure that lanes do not 'overlap' everything else
JSONObject highlightNodesObj = new JSONObject();
List<String> lanes = new ArrayList<String>();
......
......@@ -15,6 +15,8 @@ import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleTagService;
/**
* Connector to represent customized view for a user of cycle to hide all the
......@@ -26,7 +28,9 @@ import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
public class TagConnector implements RepositoryConnector {
private TagConnectorConfiguration configuration;
private CycleTagService tagService = CycleServiceImpl.getInstance().getTagService();
public TagConnector(TagConnectorConfiguration customizedViewConfiguration) {
configuration = customizedViewConfiguration;
}
......@@ -54,8 +58,8 @@ public class TagConnector implements RepositoryConnector {
if ("/".equals(id)) {
return new RepositoryNodeCollectionImpl(createRootFolders());
} else {
String name = id.substring(id.lastIndexOf("/") + 1);
CycleTagContent tagContent = getConfiguration().getCycleService().getTagContent(name);
String name = id.substring(id.lastIndexOf("/") + 1);
CycleTagContent tagContent = tagService.getTagContent(name);
return new RepositoryNodeCollectionImpl(tagContent.getTaggedRepositoryNodes());
}
}
......@@ -63,14 +67,14 @@ public class TagConnector implements RepositoryConnector {
public RepositoryFolder getRepositoryFolder(String id) throws RepositoryNodeNotFoundException {
// we try to access an TAG directly (may be represented as a folder), so
// return an empty folder object
CycleTagContent tag = getConfiguration().getCycleService().getTagContent(id);
CycleTagContent tag = tagService.getTagContent(id);
return createFolderObject(tag);
}
private List<RepositoryNode> createRootFolders() {
List<RepositoryNode> tagFolderList = new ArrayList<RepositoryNode>();
List<CycleTagContent> rootTags = getConfiguration().getCycleService().getRootTags();
List<CycleTagContent> rootTags = tagService.getRootTags();
for (CycleTagContent tag : rootTags) {
tagFolderList.add(createFolderObject(tag));
}
......
package org.activiti.cycle.impl.connector.view;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.service.CycleService;
public class TagConnectorConfiguration extends RepositoryConnectorConfiguration {
......
package org.activiti.cycle.impl.db;
public interface CycleCommentDao {
}
......@@ -2,12 +2,8 @@ package org.activiti.cycle.impl.db;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
/**
* Service to load and store repository connector configurations.
*
* @author Nils Preusker (nils.preusker@camunda.com)
*/
public interface CycleConfigurationService {
public interface CycleConfigurationDao {
/**
* Retrieves the cycle-configuration with the specified name from the
......@@ -24,6 +20,4 @@ public interface CycleConfigurationService {
*/
public void saveConfiguration(ConfigurationContainer container);
// public RepositoryConnectorConfiguration getConfiguration();
}
package org.activiti.cycle.impl.db;
import java.util.List;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
public interface CycleLinkDao {
public List<RepositoryArtifactLinkEntity> getOutgoingArtifactLinks(String sourceConnectorId, String sourceArtifactId);
public List<RepositoryArtifactLinkEntity> getIncomingArtifactLinks(String targetConnectorId, String targetArtifactId);
public void insertArtifactLink(RepositoryArtifactLinkEntity cycleLink);
public void deleteArtifactLink(String id);
}
package org.activiti.cycle.impl.db;
import java.util.List;
import org.activiti.cycle.impl.db.entity.RepositoryNodePeopleLinkEntity;
public interface CyclePeopleLinkDao {
public void insertPeopleLink(RepositoryNodePeopleLinkEntity link);
public void deletePeopleLink(String id);
public List<RepositoryNodePeopleLinkEntity> getPeopleLinks(String connectorId, String artifactId);
}
......@@ -3,39 +3,13 @@ package org.activiti.cycle.impl.db;
import java.util.List;
import org.activiti.cycle.impl.CycleTagContentImpl;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeCommentEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodePeopleLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity;
/**
* Central DAO to do all relevant DB operations for Cycle entities.
*
* @author ruecker
*/
public interface CycleDAO {
/**
* LINKS
*/
public List<RepositoryArtifactLinkEntity> getOutgoingArtifactLinks(String sourceConnectorId, String sourceArtifactId);
public List<RepositoryArtifactLinkEntity> getIncomingArtifactLinks(String targetConnectorId, String targetArtifactId);
public void insertArtifactLink(RepositoryArtifactLinkEntity cycleLink);
public void deleteArtifactLink(String id);
/**
* People-Links
*/
public void insertPeopleLink(RepositoryNodePeopleLinkEntity link);
public void deletePeopleLink(String id);
public List<RepositoryNodePeopleLinkEntity> getPeopleLinks(String connectorId, String artifactId);
public interface CycleTagDao {
/**
/*
* TAGS
*/
public void insertTag(RepositoryNodeTagEntity tag);
......@@ -48,7 +22,7 @@ public interface CycleDAO {
public CycleTagContentImpl getTagContent(String name);
/**
/*
* COMMENTS
*/
public void insertComment(RepositoryNodeCommentEntity comment);
......
......@@ -3,10 +3,10 @@ package org.activiti.cycle.impl.db.entity;
import java.util.HashMap;
import java.util.Map;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.engine.impl.db.PersistentObject;
/**
......@@ -77,7 +77,7 @@ public class RepositoryArtifactLinkEntity implements PersistentObject, Repositor
*/
private boolean linkedBothWays = true;
public void resolveArtifacts(CycleService service) {
public void resolveArtifacts(CycleRepositoryService service) {
this.sourceRepositoryArtifact = service.getRepositoryArtifact(sourceConnectorId, sourceArtifactId);
this.targetRepositoryArtifact = service.getRepositoryArtifact(targetConnectorId, targetArtifactId);
}
......
......@@ -3,10 +3,12 @@ package org.activiti.cycle.impl.db.entity;
import java.util.HashMap;
import java.util.Map;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodePeopleLink;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleService;
import org.activiti.engine.impl.db.PersistentObject;
/**
......@@ -63,7 +65,8 @@ public class RepositoryNodePeopleLinkEntity implements PersistentObject, Reposit
public void resolveArtifacts(CycleService service) {
this.sourceRepositoryArtifact = service.getRepositoryArtifact(sourceConnectorId, sourceArtifactId);
CycleRepositoryService repositoryService = CycleServiceImpl.getInstance().getRepositoryService();
this.sourceRepositoryArtifact = repositoryService.getRepositoryArtifact(sourceConnectorId, sourceArtifactId);
}
public void setSourceArtifact(RepositoryArtifact sourceArtifact) {
......
package org.activiti.cycle.impl.db.impl;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.db.CycleConfigurationService;
import org.activiti.cycle.impl.db.entity.CycleConfigEntity;
import org.apache.ibatis.session.SqlSession;
import com.thoughtworks.xstream.XStream;
public class CycleConfigurationServiceImpl extends AbstractCycleDaoMyBatisImpl implements CycleConfigurationService {
private XStream xStream = new XStream();
public CycleConfigurationServiceImpl(String processEngineName) {
if (processEngineName != null) {
this.processEngineName = processEngineName;
}
}
public void saveConfiguration(ConfigurationContainer container) {
if (null != getConfiguration(container.getName())) {
CycleConfigEntity cycleConfig = new CycleConfigEntity();
cycleConfig.setId(container.getName());
String configXML = this.xStream.toXML(container);
cycleConfig.setConfigXML(configXML);
updateById(cycleConfig);
} else {
createAndInsert(container, container.getName());
}
}
public ConfigurationContainer getConfiguration(String name) {
CycleConfigEntity cycleConfig = selectById(name);
Object configXML = this.xStream.fromXML(cycleConfig.getConfigXML());
return (ConfigurationContainer) configXML;
}
private CycleConfigEntity selectById(String id) {
SqlSession session = openSession();
try {
return (CycleConfigEntity) session.selectOne("selectCycleConfigById", id);
} finally {
session.close();
}
}
private void createAndInsert(Object o, String id) {
CycleConfigEntity cycleConfig = new CycleConfigEntity();
cycleConfig.setId(id);
String configXML = this.xStream.toXML(o);
cycleConfig.setConfigXML(configXML);
SqlSession session = openSession();
try {
session.insert("insertCycleConfig", cycleConfig);
session.commit();
} finally {
session.close();
}
}
private void updateById(CycleConfigEntity cycleConfig) {
SqlSession session = openSession();
try {
session.update("updateCycleConfigById", cycleConfig);
session.commit();
} finally {
session.close();
}
}
private void deleteById(String id) {
SqlSession session = openSession();
try {
session.delete("deleteCycleConfigById", id);
session.commit();
} finally {
session.close();
}
}
}
......@@ -7,14 +7,22 @@ import java.util.TreeSet;
import java.util.UUID;
import org.activiti.cycle.impl.CycleTagContentImpl;
import org.activiti.cycle.impl.db.CycleDAO;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.db.CycleCommentDao;
import org.activiti.cycle.impl.db.CycleConfigurationDao;
import org.activiti.cycle.impl.db.CycleLinkDao;
import org.activiti.cycle.impl.db.CyclePeopleLinkDao;
import org.activiti.cycle.impl.db.CycleTagDao;
import org.activiti.cycle.impl.db.entity.CycleConfigEntity;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeCommentEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodePeopleLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity;
import org.activiti.cycle.impl.util.XmlSerializer;
import org.apache.ibatis.session.SqlSession;
public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements CycleDAO {
public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements CycleCommentDao, CycleConfigurationDao, CycleLinkDao, CyclePeopleLinkDao,
CycleTagDao {
/**
* LINKS
......@@ -241,5 +249,69 @@ public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements
session.close();
}
}
public void saveConfiguration(ConfigurationContainer container) {
if (null != getConfiguration(container.getName())) {
updateConfiguration(container);
} else {
createAndInsertConfiguration(container, container.getName());
}
}
public ConfigurationContainer getConfiguration(String name) {
CycleConfigEntity cycleConfig = selectConfigurationById(name);
Object configXML = XmlSerializer.unSerializeObject(cycleConfig.getConfigXML());
return (ConfigurationContainer) configXML;
}
private CycleConfigEntity selectConfigurationById(String id) {
SqlSession session = openSession();
try {
return (CycleConfigEntity) session.selectOne("selectCycleConfigById", id);
} finally {
session.close();
}
}
private void createAndInsertConfiguration(Object o, String id) {
CycleConfigEntity cycleConfig = new CycleConfigEntity();
cycleConfig.setId(id);
String configXML = XmlSerializer.serializeObject(o);
cycleConfig.setConfigXML(configXML);
SqlSession session = openSession();
try {
session.insert("insertCycleConfig", cycleConfig);
session.commit();
} finally {
session.close();
}
}
private void updateConfiguration(ConfigurationContainer container) {
CycleConfigEntity cycleConfig = new CycleConfigEntity();
cycleConfig.setId(container.getName());
String configXML = XmlSerializer.serializeObject(container);
cycleConfig.setConfigXML(configXML);
SqlSession session = openSession();
try {
session.update("updateCycleConfigById", cycleConfig);
session.commit();
} finally {
session.close();
}
}
private void deleteConfigurationById(String id) {
SqlSession session = openSession();
try {
session.delete("deleteCycleConfigById", id);
session.commit();
} finally {
session.close();
}
}
}
package org.activiti.cycle.impl.service;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.cycle.CycleSessionContext;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.conf.RepositoryConfigurationHandler;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.impl.connector.demo.DemoConnectorConfiguration;
import org.activiti.cycle.impl.connector.fs.FileSystemConnectorConfiguration;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration;
import org.activiti.cycle.impl.db.CycleConfigurationDao;
import org.activiti.cycle.impl.plugin.PluginFinder;
import org.activiti.cycle.service.CycleConfigurationService;
import org.activiti.cycle.service.CycleRepositoryService.RuntimeConnectorList;
/**
* Default implementation of the {@link CycleConfigurationService}.
*
* @author daniel.meyer@camunda.com
*/
public class CycleConfigurationServiceImpl implements CycleConfigurationService {
private CycleConfigurationDao cycleConfigurationDao;
public CycleConfigurationServiceImpl() {
}
/**
* perform initialization after dependencies are set.
*/
public void initialize() {
// perform initialization
}
public void setCycleConfigurationDao(CycleConfigurationDao cycleConfigurationDao) {
this.cycleConfigurationDao = cycleConfigurationDao;
}
protected String getCurrentUserId() {
return CycleSessionContext.getFromCurrentContext("cuid", String.class);
}
public Map<String, String> getRepositoryConnectorConfiguration(String connectorConfigurationId) {
String currentUserId = getCurrentUserId();
// check params
if (currentUserId == null)
throw new IllegalArgumentException("currentUserId must not be null");
if (connectorConfigurationId == null)
throw new IllegalArgumentException("connectorConfigurationId must not be null");
ConfigurationContainer configuration = getConfigurationContainer();
List<RepositoryConnectorConfiguration> configurationList = configuration.getConnectorConfigurations();
RepositoryConnectorConfiguration repoConfiguration = null;
// look for the connector with id 'connectorConfigurationId'
for (RepositoryConnectorConfiguration repositoryConnectorConfiguration : configurationList) {
if (!repositoryConnectorConfiguration.getId().equals(connectorConfigurationId))
continue;
repoConfiguration = repositoryConnectorConfiguration;
}
if (repoConfiguration == null)
throw new RepositoryException("Cannot find Connector with id '" + connectorConfigurationId + "' for user '" + currentUserId + "'");
return RepositoryConfigurationHandler.getValueMap(repoConfiguration);
}
/**
* Loads the configuration for this user. If no configuration exists, a demo
* configuration is created and stored in the database.
*
* @param currentUserId
* the id of the currently logged in user
*/
public ConfigurationContainer getConfigurationContainer() {
String currentUserId = getCurrentUserId();
PluginFinder.checkPluginInitialization();
ConfigurationContainer configuration;
try {
configuration = cycleConfigurationDao.getConfiguration(currentUserId);
} catch (RepositoryException e) {
configuration = createDefaultDemoConfiguration(currentUserId);
cycleConfigurationDao.saveConfiguration(configuration);
}
return configuration;
}
/**
* creates a demo-configuration for the current user
* <p>
* TODO: move to helper-class?
*/
private ConfigurationContainer createDefaultDemoConfiguration(String currentUserId) {
ConfigurationContainer configuration = new ConfigurationContainer(currentUserId);
configuration.addRepositoryConnectorConfiguration(new DemoConnectorConfiguration("demo"));
configuration.addRepositoryConnectorConfiguration(new SignavioConnectorConfiguration("signavio", "http://localhost:8080/activiti-modeler/"));
configuration.addRepositoryConnectorConfiguration(new FileSystemConnectorConfiguration("files", File.listRoots()[0]));
return configuration;
}
public Map<String, List<String>> getConfiguredRepositoryConnectors() {
// retrieve the container for the current user
ConfigurationContainer configuration = getConfigurationContainer();
Map<String, List<String>> result = new HashMap<String, List<String>>();
List<RepositoryConnectorConfiguration> configurationList = configuration.getConnectorConfigurations();
// iterate the list of configured connectors
for (RepositoryConnectorConfiguration repositoryConnectorConfiguration : configurationList) {
String className = repositoryConnectorConfiguration.getClass().getCanonicalName();
List<String> configuredConnectorsForThisClass = result.get(className);
if (configuredConnectorsForThisClass == null) {
configuredConnectorsForThisClass = new ArrayList<String>();
result.put(className, configuredConnectorsForThisClass);
}
configuredConnectorsForThisClass.add(repositoryConnectorConfiguration.getId());
}
return result;
}
public Map<String, String> getConfigurationFields(String configurationClazzName) {
return RepositoryConfigurationHandler.getConfigurationFields(configurationClazzName);
}
public void updateRepositoryConnectorConfiguration(String configurationClass, String configurationId, Map<String, String> values) {
// check params
if (configurationClass == null)
throw new IllegalArgumentException("configurationClass must not be null");
if (configurationId == null)
throw new IllegalArgumentException("configurationId must not be null");
if (values == null)
throw new IllegalArgumentException("values must not be null");
try {
// Retrieve the configuration container for the current user
ConfigurationContainer configurationContainer = getConfigurationContainer();
// look for the configuration with the id 'configurationId'
RepositoryConnectorConfiguration repositoryConnectorConfiguration = null;
for (RepositoryConnectorConfiguration thisConfiguration : configurationContainer.getConnectorConfigurations()) {
if (!configurationId.equals(thisConfiguration.getId()))
continue;
repositoryConnectorConfiguration = thisConfiguration;
break;
}
// if we found a configuration but it is of the wrong type, throw
// exception:
if (repositoryConnectorConfiguration != null && !repositoryConnectorConfiguration.getClass().getCanonicalName().equals(configurationClass)) {
throw new RepositoryException("Cannot store connectorconfiguration of type '" + configurationClass + "' with id '" + configurationId
+ "'. A connector with this id and of type '" + repositoryConnectorConfiguration.getClass().getCanonicalName().equals(configurationClass)
+ "' already exists.");
}
// if no configuration is found, create a new one:
if (repositoryConnectorConfiguration == null) {
@SuppressWarnings("unchecked")
Class< ? extends RepositoryConnectorConfiguration> clazz = (Class< ? extends RepositoryConnectorConfiguration>) Class.forName(configurationClass);
repositoryConnectorConfiguration = clazz.newInstance();
// add configuration to the configuration container
configurationContainer.addRepositoryConnectorConfiguration(repositoryConnectorConfiguration);
}
// update configuration:
RepositoryConfigurationHandler.setConfigurationfields(values, repositoryConnectorConfiguration);
// store configuration container
cycleConfigurationDao.saveConfiguration(configurationContainer);
// update runtime connectors:
RuntimeConnectorList runtimeConnectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
runtimeConnectorList.connectors = null;
} catch (Exception e) {
throw new RepositoryException("Error while storing config for user " + e.getMessage(), e);
}
}
public void deleteRepositoryConnectorConfiguration(String connectorConfigurationId) {
String currentUserId = getCurrentUserId();
// check params
if (connectorConfigurationId == null)
throw new IllegalArgumentException("values must not be null");
if (currentUserId == null)
throw new IllegalArgumentException("currentUserId must not be null");
try {
// Retrieve the configuration container for the current user
ConfigurationContainer configurationContainer = getConfigurationContainer();
// look for the configuration with the id 'configurationId'
RepositoryConnectorConfiguration repositoryConnectorConfiguration = null;
for (RepositoryConnectorConfiguration thisConfiguration : configurationContainer.getConnectorConfigurations()) {
if (!connectorConfigurationId.equals(thisConfiguration.getId()))
continue;
repositoryConnectorConfiguration = thisConfiguration;
break;
}
// if no configuration is found, throw exception
if (repositoryConnectorConfiguration == null) {
throw new RepositoryException("Could not locate connectorConfiguration with id '" + connectorConfigurationId + "' for user '" + currentUserId + "'.");
}
// remove configuration from container:
configurationContainer.removeRepositoryConnectorConfiguration(repositoryConnectorConfiguration);
// store the updated configuration container
cycleConfigurationDao.saveConfiguration(configurationContainer);
// update runtime connectors:
RuntimeConnectorList runtimeConnectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
runtimeConnectorList.connectors = null;
} catch (Exception e) {
throw new RepositoryException("Error while deleting config for user " + e.getMessage(), e);
}
}
public Map<String, String> getAvailableRepositoryConnectorConfiguatationClasses() {
return PluginFinder.getInstance().getAvailableConnectorConfigurations();
}
}
package org.activiti.cycle.impl.service;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.service.CycleConfigurationService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleService;
import org.activiti.cycle.service.CycleTagService;
/**
* Connector to represent customized view for a user of cycle to hide all the
* internal configuration and {@link RepositoryConnector} stuff from the client
* (e.g. the webapp)
*
* @author daniel.meyer@camunda.com
*/
public class CycleServiceImpl implements CycleService {
private static CycleService INSTANCE;
private CycleRepositoryService repositoryService;
private CycleTagService tagService;
private CycleConfigurationService configurationService;
private CycleServiceImpl() {
ServiceImplConfiguration.wireServices(this);
ServiceImplConfiguration.initializeServices(this);
}
void setRepositoryService(CycleRepositoryService repositoryService) {
this.repositoryService = repositoryService;
}
void setConfigurationService(CycleConfigurationService configurationService) {
this.configurationService = configurationService;
}
void setTagService(CycleTagService tagService) {
this.tagService = tagService;
}
public CycleTagService getTagService() {
return tagService;
}
public CycleRepositoryService getRepositoryService() {
return repositoryService;
}
public CycleConfigurationService getConfigurationService() {
return configurationService;
}
public static CycleService getInstance() {
if (INSTANCE == null) {
synchronized (CycleServiceImpl.class) {
if (INSTANCE == null) {
INSTANCE = new CycleServiceImpl();
}
}
}
return INSTANCE;
}
}
\ No newline at end of file
package org.activiti.cycle.impl.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.activiti.cycle.CycleTagContent;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.RepositoryNodeTag;
import org.activiti.cycle.impl.CycleTagContentImpl;
import org.activiti.cycle.impl.connector.view.TagConnectorConfiguration;
import org.activiti.cycle.impl.db.CycleTagDao;
import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity;
import org.activiti.cycle.service.CycleService;
import org.activiti.cycle.service.CycleTagService;
/**
* @author bernd.ruecker@camunda.com
* @author Nils Preusker (nils.preusker@camunda.com)
* */
public class CycleTagServiceImpl implements CycleTagService {
private CycleTagDao tagDao;
private CycleService cycleService;
public CycleTagServiceImpl() {
}
public void setCycleService(CycleService cycleService) {
this.cycleService = cycleService;
}
public void setTagDao(CycleTagDao tagDao) {
this.tagDao = tagDao;
}
/**
* perform initialization after dependencies are set.
*/
public void initialize() {
// perform initialization
}
public void addTag(String connectorId, String artifactId, String tagName, String alias) {
checkValidConnector(connectorId);
RepositoryNodeTagEntity tagEntity = new RepositoryNodeTagEntity(tagName, connectorId, artifactId);
tagEntity.setAlias(alias);
tagDao.insertTag(tagEntity);
}
public void setTags(String connectorId, String nodeId, List<String> tags) {
checkValidConnector(connectorId);
// TODO: Improve method to really just update changes!
List<RepositoryNodeTagEntity> tagsForNode = tagDao.getTagsForNode(connectorId, nodeId);
for (RepositoryNodeTagEntity tagEntity : tagsForNode) {
tagDao.deleteTag(connectorId, nodeId, tagEntity.getName());
}
HashSet<String> alreadyAddedTags = new HashSet<String>();
for (String tag : tags) {
// TODO: Add Alias to setTags method as soon as we have a UI concept for
// it
if (tag != null) {
tag = tag.trim();
}
if (!alreadyAddedTags.contains(tag) && tag.length() > 0) {
addTag(connectorId, nodeId, tag, null);
alreadyAddedTags.add(tag);
}
}
}
public List<RepositoryNodeTag> getRepositoryNodeTags(String connectorId, String nodeId) {
ArrayList<RepositoryNodeTag> list = new ArrayList<RepositoryNodeTag>();
list.addAll(tagDao.getTagsForNode(connectorId, nodeId));
return list;
}
public List<String> getTags(String connectorId, String nodeId) {
ArrayList<String> result = new ArrayList<String>();
List<RepositoryNodeTagEntity> tagsForNode = tagDao.getTagsForNode(connectorId, nodeId);
for (RepositoryNodeTagEntity tagEntity : tagsForNode) {
result.add(tagEntity.getName());
}
return result;
}
public List<String> getSimiliarTagNames(String tagNamePattern) {
return tagDao.getSimiliarTagNames(tagNamePattern);
}
public void deleteTag(String connectorId, String artifactId, String tagName) {
tagDao.deleteTag(connectorId, artifactId, tagName);
}
public List<CycleTagContent> getRootTags() {
ArrayList<CycleTagContent> result = new ArrayList<CycleTagContent>();
result.addAll(tagDao.getTagsGroupedByName());
return result;
}
public CycleTagContent getTagContent(String name) {
CycleTagContentImpl tagContent = tagDao.getTagContent(name);
tagContent.resolveRepositoryArtifacts(cycleService);
return tagContent;
}
private void checkValidConnector(String connectorId) {
if (TagConnectorConfiguration.TAG_CONNECTOR_ID.equals(connectorId)) {
// we do not want to have recursions in tags
throw new RepositoryException("Cannot tag a tag");
}
}
}
package org.activiti.cycle.impl.service;
import org.activiti.cycle.impl.db.impl.CycleDaoMyBatisImpl;
/**
* Performs the configuration and wiring of the CycleServiceImplementations. I
* do not want the service implementations to be aware of the concrete
* implementations of their dependencies.
*
* @author daniel.meyer@camunda.com
*/
public class ServiceImplConfiguration {
public static void wireServices(CycleServiceImpl cycleServiceImpl) {
// instantiate dependencies:
CycleDaoMyBatisImpl dao = new CycleDaoMyBatisImpl();
CycleRepositoryServiceImpl repositoryServiceImpl = new CycleRepositoryServiceImpl();
CycleConfigurationServiceImpl configurationServiceImpl = new CycleConfigurationServiceImpl();
CycleTagServiceImpl tagServiceImpl = new CycleTagServiceImpl();
// wire-up
repositoryServiceImpl.setLinkDao(dao);
configurationServiceImpl.setCycleConfigurationDao(dao);
tagServiceImpl.setTagDao(dao);
repositoryServiceImpl.setCycleService(cycleServiceImpl);
tagServiceImpl.setCycleService(cycleServiceImpl);
cycleServiceImpl.setConfigurationService(configurationServiceImpl);
cycleServiceImpl.setRepositoryService(repositoryServiceImpl);
cycleServiceImpl.setTagService(tagServiceImpl);
}
public static void initializeServices(CycleServiceImpl cycleServiceImpl) {
CycleRepositoryServiceImpl repositoryServiceImpl = (CycleRepositoryServiceImpl) cycleServiceImpl.getRepositoryService();
CycleConfigurationServiceImpl configurationServiceImpl = (CycleConfigurationServiceImpl) cycleServiceImpl.getConfigurationService();
CycleTagServiceImpl tagServiceImpl = (CycleTagServiceImpl) cycleServiceImpl.getTagService();
// initialize
tagServiceImpl.initialize();
repositoryServiceImpl.initialize();
configurationServiceImpl.initialize();
}
}
package org.activiti.cycle.impl.util;
import com.thoughtworks.xstream.XStream;
/**
* Used for serializing / unserializing objects to/from xml.
*/
public class XmlSerializer {
public static String serializeObject(Object o) {
XStream xstream = new XStream();
return xstream.toXML(o);
}
public static Object unSerializeObject(String serializedObject) {
XStream xstream = new XStream();
return xstream.fromXML(serializedObject);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.cycle.service;
import java.util.List;
import java.util.Map;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
/**
* Cycle service used for manipulating the configuration settings. ATM,
* manipulation of RepositoryConnectorConfiguraitons is supported, using a
* String-based interface.
* <p />
* Retreive an instance of this Service by
* {@link CycleService#getConfigurationService()}
*
* @see CycleService
* @author daniel.meyer@camunda.com
*/
public interface CycleConfigurationService {
/**
* Deletes the {@link RepositoryConnectorConfiguration} designated by
* 'connectorConfigurationId'.
*
* @param connectorConfigurationId
* the of the connector we want to delete, as returned by
* {@link RepositoryConnectorConfiguration#getId()}.
*/
public void deleteRepositoryConnectorConfiguration(String connectorConfigurationId);
/**
* Returns all available {@link RepositoryConnectorConfiguration}
* implementations.
*
* @return a map such that each key is a canonical classname of a
* {@link RepositoryConnectorConfiguration} and the corresponding
* value is a human-readable name for this connector-type.
*/
public Map<String, String> getAvailableRepositoryConnectorConfiguatationClasses();
/**
* Returns a map of available configuration fields for the given class.
* <p>
* TODO: at the moment we recognize a field if we find a setter-method which
* takes a single parameter of type String. A better solution would be IMO to
* use annotations and annotate setters with sth. like
* "@ConnectorConfigurationField".
*
* @param configurationClazzName
* . the name of the {@link RepositoryConnectorConfiguration}
* @return a map of field-type mappings.
*
*/
public Map<String, String> getConfigurationFields(String configurationClazzName);
/**
* Returns a map of {@link RepositoryConnectorConfiguration}s for the provided
* user.
*
* @return a map of lists, such that each key represents the canonical
* classname of a {@link RepositoryConnectorConfiguration}
* implementation and the corresponding value is a list of Ids, as
* returned by {@link RepositoryConnectorConfiguration#getId()}.
*/
public Map<String, List<String>> getConfiguredRepositoryConnectors();
/**
* Returns the {@link ConfigurationContainer} for the user with
* 'currentUserId'.
*/
public ConfigurationContainer getConfigurationContainer();
/**
* Returns a field-value map of the current configuration settings represented
* by 'repoConfiguration'.
* <p />
* Note: this method returns values for the fields returned by
* {@link #getConfigurationFields(String)}
*
* @param repoConfiguration
* the {@link RepositoryConnectorConfiguration} instance to extract
* the values from.
* @return a map of field-name / value pairs.
*/
public Map<String, String> getRepositoryConnectorConfiguration(String connectorConfigurationId);
/**
* Creates / Updates the {@link RepositoryConnectorConfiguration} designated
* by the provided 'configurationId' and owned by the provided
* 'currentUserId'. If no such configuration exists, a new configuration is
* created, as an instance of the provided 'configurationClass'.
*
* @param configurationClass
* the canonical classname of the
* {@link RepositoryConnectorConfiguration} implementation we want to
* create / update.
* @param configurationId
* the id as returned by
* {@link RepositoryConnectorConfiguration#getId()}.
* @param values
* the configuration values for this configuration as am map of
* fieldname / value pairs.
*/
public void updateRepositoryConnectorConfiguration(String configurationClass, String configurationId, Map<String, String> values);
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.cycle;
import java.util.List;
import java.util.Map;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
/**
* This is the central entry point for Activiti Cycle. The service provides the
* possibility to store and load user configurations (which then contains
* {@link RepositoryConnector}s) and to do global actions not tied to a single
* repository like Tags, Links and so on...
*/
public interface CycleService {
/**
* Log in to the repository configured for the given connector with the
* provided user name and password.
*
* @param username
* the username to log in
* @param password
* the password to log in
* @param connectorId
* the id of the repository-connector to use
*/
public boolean login(String username, String password, String connectorId);
/**
* Some connectors support commit (like SVN), so all pending changes must be
* committed correctly. If the connector doesn't support committing, this
* method just does nothing. This means, there is no rollback and you
* shouldn't rely on a transaction behavior.
*/
public void commitPendingChanges(String comment);
/**
* load the {@link RepositoryArtifact} including details
*/
public RepositoryArtifact getRepositoryArtifact(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
/**
* returns a preview for the artifact if available, otherwiese null is
* returned. Not every connector must provide a preview for all
* {@link ArtifactType}s.
*/
public Content getRepositoryArtifactPreview(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
public RepositoryFolder getRepositoryFolder(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
/**
* gets all elements
*/
public RepositoryNodeCollection getChildren(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
/**
* return the list of supported {@link ArtifactType}s of this
* {@link RepositoryConnector} for the given folder. Most conenctors doesn't
* make any difference between the folders, but some may do.
*/
public List<ArtifactType> getSupportedArtifactTypes(String connectorId, String folderId);
/**
* create a new file in the given folder with the default
* {@link ContentRepresentation}
*
* @param artifactId
*/
public RepositoryArtifact createArtifact(String connectorId, String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException;
public RepositoryArtifact createArtifactFromContentRepresentation(String connectorId, String parentFolderId, String artifactName, String artifactType,
String contentRepresentationId, Content artifactContent) throws RepositoryNodeNotFoundException;
/**
* create a new subfolder in the given folder
*/
public RepositoryFolder createFolder(String connectorId, String parentFolderId, String name) throws RepositoryNodeNotFoundException;
public Content getContent(String connectorId, String artifactId, String representationName) throws RepositoryNodeNotFoundException;
/**
* update artifact content with default {@link ContentRepresentation}
*/
public void updateContent(String connectorId, String artifactId, Content content) throws RepositoryNodeNotFoundException;
public void updateContent(String connectorId, String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException;
/**
* deletes the given file from the folder
*/
public void deleteArtifact(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
/**
* deletes the given subfolder of the parent folder.
*
* TODO: Think about if we need the parent folder as argument of this API
*/
public void deleteFolder(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
public void executeParameterizedAction(String connectorId, String artifactId, String actionId, Map<String, Object> parameters) throws Exception;
public void addArtifactLink(RepositoryArtifactLink link);
public List<RepositoryArtifactLink> getArtifactLinks(String sourceConnectorId, String sourceArtifactId);
public List<RepositoryArtifactLink> getIncomingArtifactLinks(String targetConnectorId, String targetArtifactId);
public void deleteLink(String linkId);
/**
* add tag for the given node id and specify an alias which can be used in the
* GUI later on when showing the tag to the user
*/
public void addTag(String connectorId, String nodeId, String tagName, String alias);
public List<String> getTags(String connectorId, String nodeId);
public List<RepositoryNodeTag> getRepositoryNodeTags(String connectorId, String nodeId);
/**
* sets provided tags to the given artifact, this means it should reset the
* previous tags for that artifact!
*
* Additionally it does some magic for you:
* <ul>
* <li>checks for every tag whether it is empty (doesn't create it if that is
* the case)</li>
* <li>checks whether the tag already exists, CycleService should worry about
* duplicate exceptions etc.</li>
* </ul>
*/
public void setTags(String connectorId, String nodeId, List<String> tags);
/**
* delete the tag
*/
public void deleteTag(String connectorId, String nodeId, String tagName);
/**
* get all tag names matching the given pattern. This can be used to find
* already used tags to resuse them
*/
public List<String> getSimiliarTagNames(String tagNamePattern);
/**
* get all available tags for the system in order to show them in the GUI (as
* folder, tag cloud, ...)
*/
public CycleTagContent getTagContent(String name);
public List<CycleTagContent> getRootTags();
/**
* Returns all available {@link RepositoryConnectorConfiguration}
* implementations.
*
* @return a map such that each key is a canonical classname of a
* {@link RepositoryConnectorConfiguration} and the corresponding
* value is a human-readable name for this connector-type.
*/
public Map<String, String> getAvailableRepositoryConnectorConfiguatationClasses();
/**
* Creates / Updates the {@link RepositoryConnectorConfiguration} designated
* by the provided 'configurationId' and owned by the provided
* 'currentUserId'. If no such configuration exists, a new configuration is
* created, as an instance of the provided 'configurationClass'.
*
* @param configurationClass
* the canonical classname of the
* {@link RepositoryConnectorConfiguration} implementation we want to
* create / update.
* @param configurationId
* the id as returned by
* {@link RepositoryConnectorConfiguration#getId()}.
* @param values
* the configuration values for this configuration as am map of
* fieldname / value pairs.
* @param currentUserId
* the user we want to update the configuration for.
*/
public void updateRepositoryConnectorConfiguration(String configurationClass, String configurationId, Map<String, String> values, String currentUserId);
/**
* Returns a map of available configuration fields for the given class.
* <p>
* TODO: at the moment we recognize a field if we find a setter-method which
* takes a single parameter of type String. A better solution would be IMO to
* use annotations and annotate setters with sth. like
* "@ConnectorConfigurationField".
*
* @param configurationClazzName
* . the name of the {@link RepositoryConnectorConfiguration}
* @return a map of field-type mappings.
*
*/
public Map<String, String> getConfigurationFields(String configurationClazzName);
/**
* Returns a map of {@link RepositoryConnectorConfiguration}s for the provided
* user.
*
* @param currentUserId
* the user to retrieve the connectors for.
* @return a map of lists, such that each key represents the canonical
* classname of a {@link RepositoryConnectorConfiguration}
* implementation and the corresponding value is a list of Ids, as
* returned by {@link RepositoryConnectorConfiguration#getId()}.
*/
public Map<String, List<String>> getConfiguredRepositoryConnectors(String currentUserId);
/**
* Returns a field-value map of the current configuration settings represented
* by 'repoConfiguration'.
* <p />
* Note: this method returns values for the fields returned by
* {@link #getConfigurationFields(String)}
*
* @param repoConfiguration
* the {@link RepositoryConnectorConfiguration} instance to extract
* the values from.
* @param currentUserId
* the user to retrieve the {@link RepositoryConnectorConfiguration}
* for.
* @return a map of field-name / value pairs.
*/
public Map<String, String> getRepositoryConnectorConfiguration(String connectorConfigurationId, String currentUserId);
/**
* Deletes the {@link RepositoryConnectorConfiguration} designated by
* 'connectorConfigurationId'.
*
* @param connectorConfigurationId
* the of the connector we want to delete, as returned by
* {@link RepositoryConnectorConfiguration#getId()}.
* @param currentUserId
* the user we want to delete the configuration for.
*/
public void deleteRepositoryConnectorConfiguration(String connectorConfigurationId, String currentUserId);
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.cycle.service;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.Content;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
/**
* Cycle service used for accessing repositories.
* <p />
* Get an instance of this service by
* {@link CycleService#getRepositoryService()}
*
* @see CycleService
*/
public interface CycleRepositoryService {
public static class RuntimeConnectorList implements Serializable {
private static final long serialVersionUID = 1L;
// the transient field keeps the servlet container from serializing the
// connectors in the session
// TODO: needs testing: When do servlet containers serialize/deserialize?
// Tomcat seems to do it
// between shutdowns / startups. At the moment I would qualify this as a
// 'hack' - Daniel Meyer
public transient List<RepositoryConnector> connectors;
}
public void addArtifactLink(RepositoryArtifactLink link);
/**
* create a new file in the given folder with the default
* {@link ContentRepresentation}
*
* @param artifactId
*/
public RepositoryArtifact createArtifact(String connectorId, String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException;
public RepositoryArtifact createArtifactFromContentRepresentation(String connectorId, String parentFolderId, String artifactName, String artifactType,
String contentRepresentationId, Content artifactContent) throws RepositoryNodeNotFoundException;
/**
* create a new subfolder in the given folder
*/
public RepositoryFolder createFolder(String connectorId, String parentFolderId, String name) throws RepositoryNodeNotFoundException;
/**
* deletes the given file from the folder
*/
public void deleteArtifact(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
/**
* deletes the given subfolder of the parent folder.
*
* TODO: Think about if we need the parent folder as argument of this API
*/
public void deleteFolder(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
public void deleteLink(String linkId);
public List<RepositoryArtifactLink> getArtifactLinks(String sourceConnectorId, String sourceArtifactId);
/**
* gets all elements
*/
public RepositoryNodeCollection getChildren(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
public Content getContent(String connectorId, String artifactId, String representationName) throws RepositoryNodeNotFoundException;
public List<RepositoryArtifactLink> getIncomingArtifactLinks(String targetConnectorId, String targetArtifactId);
/**
* load the {@link RepositoryArtifact} including details
*/
public RepositoryArtifact getRepositoryArtifact(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
/**
* returns a preview for the artifact if available, otherwiese null is
* returned. Not every connector must provide a preview for all
* {@link ArtifactType}s.
*/
public Content getRepositoryArtifactPreview(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
public RepositoryFolder getRepositoryFolder(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
/**
* return the list of supported {@link ArtifactType}s of this
* {@link RepositoryConnector} for the given folder. Most conenctors doesn't
* make any difference between the folders, but some may do.
*/
public List<ArtifactType> getSupportedArtifactTypes(String connectorId, String folderId);
/**
* update artifact content with default {@link ContentRepresentation}
*/
public void updateContent(String connectorId, String artifactId, Content content) throws RepositoryNodeNotFoundException;
public void updateContent(String connectorId, String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException;
/**
* Some connectors support commit (like SVN), so all pending changes must be
* committed correctly. If the connector doesn't support committing, this
* method just does nothing. This means, there is no rollback and you
* shouldn't rely on a transaction behavior.
*/
public void commitPendingChanges(String comment);
public void executeParameterizedAction(String connectorId, String artifactId, String actionId, Map<String, Object> parameters) throws Exception;
/**
* Log in to the repository configured for the given connector with the
* provided user name and password.
*
* @param username
* the username to log in
* @param password
* the password to log in
* @param connectorId
* the id of the repository-connector to use
*/
public boolean login(String username, String password, String connectorId);
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.cycle.service;
/**
* This is the central entry point for Activiti Cycle and provides access to the
* {@link CycleRepositoryService}, the {@link CycleTagService} and the
* {@link CycleConfigurationService}.
*
*/
public interface CycleService {
public CycleRepositoryService getRepositoryService();
public CycleTagService getTagService();
public CycleConfigurationService getConfigurationService();
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.cycle.service;
import java.util.List;
import org.activiti.cycle.CycleTagContent;
import org.activiti.cycle.RepositoryNodeTag;
/**
* Cycle service used for managing tags.
* <p />
* Get an instance of this service by {@link CycleService#getCycleTagService()}
*
* @see CycleService
*/
public interface CycleTagService {
/**
* add tag for the given node id and specify an alias which can be used in the
* GUI later on when showing the tag to the user
*/
public void addTag(String connectorId, String nodeId, String tagName, String alias);
/**
* delete the tag
*/
public void deleteTag(String connectorId, String nodeId, String tagName);
public List<RepositoryNodeTag> getRepositoryNodeTags(String connectorId, String nodeId);
public List<CycleTagContent> getRootTags();
/**
* get all tag names matching the given pattern. This can be used to find
* already used tags to resuse them
*/
public List<String> getSimiliarTagNames(String tagNamePattern);
/**
* get all available tags for the system in order to show them in the GUI (as
* folder, tag cloud, ...)
*/
public CycleTagContent getTagContent(String name);
public List<String> getTags(String connectorId, String nodeId);
/**
* sets provided tags to the given artifact, this means it should reset the
* previous tags for that artifact!
*
* Additionally it does some magic for you:
* <ul>
* <li>checks for every tag whether it is empty (doesn't create it if that is
* the case)</li>
* <li>checks whether the tag already exists, CycleService should worry about
* duplicate exceptions etc.</li>
* </ul>
*/
public void setTags(String connectorId, String nodeId, List<String> tags);
}
package org.activiti.cycle.impl.conf;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.activiti.cycle.impl.connector.fs.FileSystemConnectorConfiguration;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration;
import org.activiti.cycle.incubator.connector.svn.SvnConnectorConfiguration;
import org.activiti.cycle.incubator.connector.vfs.VfsConnectorConfiguration;
import org.junit.Test;
public class RepositoryConfigurationHandlerTest {
@Test
public void testGetConfigurationFields() {
RepositoryConfigurationHandler handler = new RepositoryConfigurationHandler();
System.out.println(handler.getConfigurationFields(SvnConnectorConfiguration.class.getCanonicalName()));
System.out.println(handler.getConfigurationFields(SignavioConnectorConfiguration.class.getCanonicalName()));
System.out.println(handler.getConfigurationFields(FileSystemConnectorConfiguration.class.getCanonicalName()));
System.out.println(handler.getConfigurationFields(VfsConnectorConfiguration.class.getCanonicalName()));
}
@Test
public void setConfigurationFields() {
RepositoryConfigurationHandler handler = new RepositoryConfigurationHandler();
Map<String, String> keyValueMap = new HashMap<String, String>();
for (String fieldname : handler.getConfigurationFields(SvnConnectorConfiguration.class.getCanonicalName()).keySet()) {
keyValueMap.put(fieldname, UUID.randomUUID().toString());
}
SvnConnectorConfiguration config = new SvnConnectorConfiguration();
handler.setConfigurationfields(keyValueMap, config);
System.out.println(config);
}
}
package org.activiti.cycle.impl.conf;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.service.CycleService;
import org.activiti.engine.ProcessEngines;
import org.junit.AfterClass;
import org.junit.BeforeClass;
......
......@@ -11,15 +11,15 @@ import java.util.Map;
import org.activiti.cycle.Content;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.impl.CycleServiceImpl;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.impl.connector.demo.action.CopyArtifactAction;
import org.activiti.cycle.impl.plugin.PluginFinder;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleService;
import org.junit.Before;
import org.junit.Test;
......@@ -33,90 +33,91 @@ public class DemoConnectorTest {
@Test
public void testFirstPlay() throws Exception {
// create demo connector but accessed via the customized view connector
ConfigurationContainer configurationContainer = new ConfigurationContainer("bernd");
RepositoryConnectorConfiguration configuration = new DemoConnectorConfiguration("demo");
configurationContainer.addRepositoryConnectorConfiguration(configuration);
CycleService cycleService = new CycleServiceImpl(configurationContainer.getConnectorList());
cycleService.login("bernd", "bernd", "demo");
List<RepositoryNode> childNodes = cycleService.getChildren("demo", "/").asList();
// // create demo connector but accessed via the customized view connector
// ConfigurationContainer configurationContainer = new ConfigurationContainer("bernd");
// RepositoryConnectorConfiguration configuration = new DemoConnectorConfiguration("demo");
// configurationContainer.addRepositoryConnectorConfiguration(configuration);
//
// CycleService cycleService = CycleServiceImpl.getInstance();
//
//
// cycleService.login("bernd", "bernd", "demo");
//
// List<RepositoryNode> childNodes = cycleService.getChildren("demo", "/").asList();
//// assertEquals(1, childNodes.size());
//// assertEquals("demo", childNodes.get(0).getCurrentPath());
//
//// childNodes = cycleService.getChildren("demo", "/").asList();
// assertEquals(2, childNodes.size());
//
// assertTrue(childNodes.get(0) instanceof RepositoryFolder);
// RepositoryFolder folder1 = (RepositoryFolder) childNodes.get(0);
// assertEquals("/minutes", folder1.getNodeId());
// // assertEquals("http://localhost:8080/activiti-cycle/demo/minutes",
// // folder1.getClientUrl());
//
// assertTrue(childNodes.get(1) instanceof RepositoryFolder);
// RepositoryFolder folder2 = (RepositoryFolder) childNodes.get(1);
// assertEquals("/BPMN", folder2.getNodeId());
//
// // check sub elements of folder 1
// childNodes = cycleService.getChildren("demo", folder1.getNodeId()).asList();
// assertEquals(2, childNodes.size());
//
// RepositoryArtifact file1 = (RepositoryArtifact) childNodes.get(0);
// assertEquals("/minutes/20100701-KickOffMeeting.txt", file1.getNodeId());
//
// RepositoryArtifact file2 = (RepositoryArtifact) childNodes.get(1);
// assertEquals("/minutes/InitialMindmap.mm", file2.getNodeId());
//
// // check sub elements of folder 2
// childNodes = cycleService.getChildren("demo", folder2.getNodeId()).asList();
// assertEquals(1, childNodes.size());
// assertEquals("demo", childNodes.get(0).getCurrentPath());
// childNodes = cycleService.getChildren("demo", "/").asList();
assertEquals(2, childNodes.size());
assertTrue(childNodes.get(0) instanceof RepositoryFolder);
RepositoryFolder folder1 = (RepositoryFolder) childNodes.get(0);
assertEquals("/minutes", folder1.getNodeId());
// assertEquals("http://localhost:8080/activiti-cycle/demo/minutes",
// folder1.getClientUrl());
assertTrue(childNodes.get(1) instanceof RepositoryFolder);
RepositoryFolder folder2 = (RepositoryFolder) childNodes.get(1);
assertEquals("/BPMN", folder2.getNodeId());
// check sub elements of folder 1
childNodes = cycleService.getChildren("demo", folder1.getNodeId()).asList();
assertEquals(2, childNodes.size());
RepositoryArtifact file1 = (RepositoryArtifact) childNodes.get(0);
assertEquals("/minutes/20100701-KickOffMeeting.txt", file1.getNodeId());
RepositoryArtifact file2 = (RepositoryArtifact) childNodes.get(1);
assertEquals("/minutes/InitialMindmap.mm", file2.getNodeId());
// check sub elements of folder 2
childNodes = cycleService.getChildren("demo", folder2.getNodeId()).asList();
assertEquals(1, childNodes.size());
RepositoryFolder folder3 = (RepositoryFolder) childNodes.get(0);
assertEquals("/BPMN/Level3", folder3.getNodeId());
childNodes = cycleService.getChildren("demo", folder3.getNodeId()).asList();
assertEquals(1, childNodes.size());
RepositoryArtifact file3 = (RepositoryArtifact) childNodes.get(0);
assertEquals("/BPMN/Level3/InitialBpmnModel", file3.getNodeId());
assertEquals("InitialBpmnModel", file3.getMetadata().getName());
assertEquals("/BPMN/Level3", file3.getMetadata().setParentFolderId());
//
// System.out.println(folder2.getId() + " -> " + folder2.getClientUrl());
// System.out.println(folder3.getId() + " -> " + folder3.getClientUrl());
// System.out.println(file3.getId() + " -> " + file3.getClientUrl());
//
Collection<ContentRepresentation> contentRepresentations = file3.getArtifactType().getContentRepresentations();
for (ContentRepresentation contentRepresentation : contentRepresentations) {
Content content = cycleService.getContent("demo", file3.getNodeId(), contentRepresentation.getId());
assertNotNull(content);
assertNotNull(content.asByteArray());
}
assertEquals(6, DemoConnector.nodes.size());
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("targetName", "xxx.txt");
parameters.put("copyCount", 2);
parameters.put("targetConnectorId", "demo");
parameters.put("targetFolderId", "/minutes");
cycleService.executeParameterizedAction("demo", file1.getNodeId(), new CopyArtifactAction().getId(), parameters);
List<RepositoryNode> nodes = DemoConnector.nodes;
assertEquals(8, DemoConnector.nodes.size());
childNodes = cycleService.getChildren("demo", folder1.getNodeId()).asList();
assertEquals(4, childNodes.size());
assertEquals("/minutes/20100701-KickOffMeeting.txt", childNodes.get(0).getNodeId());
assertEquals("/minutes/InitialMindmap.mm", childNodes.get(1).getNodeId());
assertEquals("/minutes/xxx.txt0", childNodes.get(2).getNodeId());
assertEquals("xxx.txt0", childNodes.get(2).getMetadata().getName());
assertEquals("/minutes/xxx.txt1", childNodes.get(3).getNodeId());
assertEquals("xxx.txt1", childNodes.get(3).getMetadata().getName());
//
// RepositoryFolder folder3 = (RepositoryFolder) childNodes.get(0);
// assertEquals("/BPMN/Level3", folder3.getNodeId());
//
// childNodes = cycleService.getChildren("demo", folder3.getNodeId()).asList();
// assertEquals(1, childNodes.size());
//
// RepositoryArtifact file3 = (RepositoryArtifact) childNodes.get(0);
// assertEquals("/BPMN/Level3/InitialBpmnModel", file3.getNodeId());
// assertEquals("InitialBpmnModel", file3.getMetadata().getName());
// assertEquals("/BPMN/Level3", file3.getMetadata().setParentFolderId());
// //
// // System.out.println(folder2.getId() + " -> " + folder2.getClientUrl());
// // System.out.println(folder3.getId() + " -> " + folder3.getClientUrl());
// // System.out.println(file3.getId() + " -> " + file3.getClientUrl());
// //
// Collection<ContentRepresentation> contentRepresentations = file3.getArtifactType().getContentRepresentations();
// for (ContentRepresentation contentRepresentation : contentRepresentations) {
// Content content = cycleService.getContent("demo", file3.getNodeId(), contentRepresentation.getId());
// assertNotNull(content);
// assertNotNull(content.asByteArray());
// }
//
// assertEquals(6, DemoConnector.nodes.size());
//
// Map<String, Object> parameters = new HashMap<String, Object>();
// parameters.put("targetName", "xxx.txt");
// parameters.put("copyCount", 2);
// parameters.put("targetConnectorId", "demo");
// parameters.put("targetFolderId", "/minutes");
//
// cycleService.executeParameterizedAction("demo", file1.getNodeId(), new CopyArtifactAction().getId(), parameters);
//
// List<RepositoryNode> nodes = DemoConnector.nodes;
// assertEquals(8, DemoConnector.nodes.size());
//
// childNodes = cycleService.getChildren("demo", folder1.getNodeId()).asList();
// assertEquals(4, childNodes.size());
//
// assertEquals("/minutes/20100701-KickOffMeeting.txt", childNodes.get(0).getNodeId());
// assertEquals("/minutes/InitialMindmap.mm", childNodes.get(1).getNodeId());
// assertEquals("/minutes/xxx.txt0", childNodes.get(2).getNodeId());
// assertEquals("xxx.txt0", childNodes.get(2).getMetadata().getName());
// assertEquals("/minutes/xxx.txt1", childNodes.get(3).getNodeId());
// assertEquals("xxx.txt1", childNodes.get(3).getMetadata().getName());
}
// @Test
......
package org.activiti.cycle.impl.connector.vfs;
import java.util.UUID;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.plugin.PluginFinder;
import org.activiti.cycle.incubator.connector.vfs.VfsConnector;
import org.activiti.cycle.incubator.connector.vfs.VfsConnectorConfiguration;
import org.activiti.cycle.incubator.connector.vfs.VfsConnectorPluginDefinition;
import org.junit.BeforeClass;
import org.junit.Test;
public class SftpConnectorTest {
private static ConfigurationContainer userConfiguration;
private static VfsConnector connector;
@BeforeClass
public static void createConnector() {
userConfiguration = new ConfigurationContainer("daniel");
userConfiguration.addRepositoryConnectorConfiguration(new VfsConnectorConfiguration("sftp", "localhost", "/home/guest/", "sftp"));
connector = (VfsConnector) userConfiguration.getConnector("sftp");
// TODO: Should be done in Bootstrapping
PluginFinder.checkPluginInitialization();
connector.login("guest", "guestlogin");
}
@Test
public void testGetChildren() {
RepositoryNodeCollection nodeCollection = connector.getChildren("");
for (RepositoryNode node : nodeCollection.asList()) {
System.out.println(node);
}
}
@Test
public void testCreateArtifact() {
RepositoryArtifact artifact = connector.getRepositoryArtifact("build.xml");
Content content = connector.getContent(artifact.getNodeId(), VfsConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_XML);
RepositoryArtifact newArtifact = connector.createArtifact("tmp/", UUID.randomUUID() + ".xml", "Text", content);
}
@Test
public void testCreateFolder() {
RepositoryFolder newFolder = connector.createFolder("tmp/", UUID.randomUUID().toString());
}
@Test
public void testDeleteArtifact() {
RepositoryArtifact artifact = connector.getRepositoryArtifact("build.xml");
Content content = connector.getContent(artifact.getNodeId(), VfsConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_XML);
RepositoryArtifact newArtifact = connector.createArtifact("tmp/", UUID.randomUUID() + ".xml", "Text", content);
connector.deleteArtifact(newArtifact.getNodeId());
}
@Test
public void testDeleteFolder() {
connector.deleteFolder("/tmp/test");
}
}
......@@ -3,7 +3,6 @@ package org.activiti.cycle.impl.db.impl;
import java.util.List;
import org.activiti.cycle.impl.CycleTagContentImpl;
import org.activiti.cycle.impl.db.CycleDAO;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodePeopleLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity;
......@@ -12,7 +11,7 @@ import org.activiti.engine.impl.test.PluggableActivitiTestCase;
public class CycleDaoMyBatisImplTest extends PluggableActivitiTestCase {
private CycleDAO dao;
private CycleDaoMyBatisImpl dao;
@Override
protected void setUp() throws Exception {
......
......@@ -32,7 +32,7 @@ public class ActionExecutionPut extends ActivitiCycleWebScript {
Map<String, Object> parameters = req.getFormVariables();
try {
this.cycleService.executeParameterizedAction(connectorId, artifactId, actionId, parameters);
repositoryService.executeParameterizedAction(connectorId, artifactId, actionId, parameters);
model.put("result", true);
} catch (Exception e) {
// TODO: see whether this makes sense, probably either exception or negative result.
......
......@@ -13,19 +13,15 @@
package org.activiti.rest.api.cycle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryAuthenticationException;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.impl.CycleServiceImpl;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleConfigurationService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleService;
import org.activiti.cycle.service.CycleTagService;
import org.activiti.rest.api.cycle.session.CycleHttpSession;
import org.activiti.rest.util.ActivitiRequest;
import org.activiti.rest.util.ActivitiWebScript;
import org.springframework.extensions.webscripts.Cache;
......@@ -38,67 +34,31 @@ public abstract class ActivitiCycleWebScript extends ActivitiWebScript {
protected CycleService cycleService;
private void init(ActivitiRequest req) {
String cuid = req.getCurrentUserId();
HttpSession session = req.getHttpServletRequest().getSession(true);
protected CycleRepositoryService repositoryService;
// Retrieve the list of configured connectors for the current user (either
// from the session or, if not present, from the database
List<RepositoryConnector> connectors = CycleServiceImpl.getConfiguredRepositoryConnectors(cuid, session);
protected CycleTagService tagService;
// Make sure we know username and password for all connectors that require
// login. If it is not stored in the users configuration it should be
// provided as a parameter in the request.
Map<String, String> connectorsWithoutLoginMap = new HashMap<String, String>();
for (RepositoryConnector connector : getPasswordEnabledConnectors(connectors)) {
PasswordEnabledRepositoryConnectorConfiguration conf = (PasswordEnabledRepositoryConnectorConfiguration) connector.getConfiguration();
String username = req.getString(conf.getId() + "_username");
String password = req.getString(conf.getId() + "_password");
protected CycleConfigurationService configurationService;
if (username != null && password != null) {
// Remove the connector from the configuration for this session since
// the user pressed cancel in the authentication dialog.
if (username.equals("\"\"") && password.equals("\"\"")) {
connectors.remove(connector);
} else {
conf.setUser(username);
conf.setPassword(password);
}
} else if (conf.getUser() == null || conf.getPassword() == null) {
connectorsWithoutLoginMap.put(conf.getId(), conf.getName());
}
// If one or more logins are missing (not provided in either the
// configuration or as HTTP parameter) we'll throw an authentication
// exception with the list of connectors that are missing login
// information
}
if (connectorsWithoutLoginMap.size() > 0) {
// TODO: i18n
throw new RepositoryAuthenticationException("Please provide your username and password for the following repositories:", connectorsWithoutLoginMap);
}
// Initialize the cycleService
this.cycleService = CycleServiceImpl.getCycleService(cuid, session, connectors);
}
private List<RepositoryConnector> getPasswordEnabledConnectors(List<RepositoryConnector> connectors) {
List<RepositoryConnector> LoginEnabledconnectors = new ArrayList<RepositoryConnector>();
for (RepositoryConnector connector : connectors) {
RepositoryConnectorConfiguration conf = connector.getConfiguration();
if (PasswordEnabledRepositoryConnectorConfiguration.class.isInstance(conf)) {
LoginEnabledconnectors.add(connector);
}
}
return LoginEnabledconnectors;
public ActivitiCycleWebScript() {
cycleService = CycleServiceImpl.getInstance();
configurationService = cycleService.getConfigurationService();
repositoryService = cycleService.getRepositoryService();
tagService = cycleService.getTagService();
}
@Override
protected void executeWebScript(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
try {
init(req);
// open cycle ui-session
CycleHttpSession.openSession(req);
// execute the request in the context of a CycleHttpSession
execute(req, status, cache, model);
} catch (RepositoryAuthenticationException e) {
model.put("authenticationException", e);
} finally {
// close the CycleHttpSession
CycleHttpSession.closeSession();
}
}
......
......@@ -44,7 +44,7 @@ public class ArtifactActionFormGet extends ActivitiCycleWebScript {
String actionId = req.getMandatoryString("actionName");
// Retrieve the artifact from the repository
RepositoryArtifact artifact = this.cycleService.getRepositoryArtifact(connectorId, artifactId);
RepositoryArtifact artifact = repositoryService.getRepositoryArtifact(connectorId, artifactId);
if (artifact == null) {
throw new WebScriptException(Status.STATUS_NOT_FOUND, "There is no artifact with id '" + artifactId + "' for connector with id '" + connectorId + "'.");
......
......@@ -30,7 +30,7 @@ import org.springframework.extensions.webscripts.Status;
/**
*
* @author Nils Preusker (nils.preusker@camunda.com)
* @author Bernd Rcker
* @author Bernd Rcker
*/
public class ArtifactGet extends ActivitiCycleWebScript {
......@@ -45,7 +45,7 @@ public class ArtifactGet extends ActivitiCycleWebScript {
String restProxyUri = req.getString("restProxyUri");
// Retrieve the artifact from the repository
RepositoryArtifact artifact = this.cycleService.getRepositoryArtifact(connectorId, artifactId);
RepositoryArtifact artifact = repositoryService.getRepositoryArtifact(connectorId, artifactId);
List<String> contentRepresentations = new ArrayList<String>();
for (ContentRepresentation representation : artifact.getArtifactType().getContentRepresentations()) {
......
......@@ -50,7 +50,7 @@ public class ArtifactLinkPost extends ActivitiCycleWebScript {
link.setTargetArtifactId(targetArtifactId);
try {
cycleService.addArtifactLink(link);
repositoryService.addArtifactLink(link);
model.put("result", true);
} catch (Exception e) {
// TODO: see whether this makes sense, probably either exception or
......
......@@ -30,7 +30,7 @@ public class ArtifactLinksGet extends ActivitiCycleWebScript {
protected void execute(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
String connectorId = req.getMandatoryString("connectorId");
String artifactId = req.getString("artifactId");
List<RepositoryArtifactLink> links = this.cycleService.getArtifactLinks(connectorId, artifactId);
List<RepositoryArtifactLink> links = repositoryService.getArtifactLinks(connectorId, artifactId);
model.put("links", links);
}
......
......@@ -16,8 +16,8 @@ package org.activiti.rest.api.cycle;
import java.util.Map;
import org.activiti.cycle.Content;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.service.CycleService;
import org.activiti.rest.util.ActivitiRequest;
import org.activiti.rest.util.ActivitiRequestObject;
import org.springframework.extensions.webscripts.Cache;
......@@ -48,7 +48,7 @@ public class ArtifactPost extends ActivitiCycleWebScript {
Content artifactContent = new Content();
artifactContent.setValue(file.getInputStream());
try {
this.cycleService.createArtifact(connectorId, parentFolderId, artifactName, artifactType, artifactContent);
repositoryService.createArtifact(connectorId, parentFolderId, artifactName, artifactType, artifactContent);
model.put("result", true);
} catch (Exception e) {
model.put("result", false);
......
......@@ -27,7 +27,7 @@ public class AvailableConnectorConfigsGet extends ActivitiCycleWebScript {
@Override
void execute(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
model.put("configs", this.cycleService.getAvailableRepositoryConnectorConfiguatationClasses());
model.put("configs", configurationService.getAvailableRepositoryConnectorConfiguatationClasses());
}
}
......@@ -39,7 +39,7 @@ public class ChildNodesGet extends ActivitiCycleWebScript {
String artifactId = req.getMandatoryString("artifactId");
String connectorId = req.getMandatoryString("connectorId");
try {
RepositoryNodeCollection children = this.cycleService.getChildren(connectorId, artifactId);
RepositoryNodeCollection children = repositoryService.getChildren(connectorId, artifactId);
model.put("files", children.getArtifactList());
model.put("folders", children.getFolderList());
......
......@@ -19,19 +19,20 @@ import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.CycleDefaultMimeType;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.impl.CycleServiceImpl;
import org.activiti.cycle.impl.connector.signavio.transform.TransformationException;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleConfigurationService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleService;
import org.activiti.cycle.service.CycleTagService;
import org.activiti.engine.impl.util.IoUtil;
import org.activiti.rest.api.cycle.session.CycleHttpSession;
import org.activiti.rest.util.ActivitiRequest;
import org.activiti.rest.util.ActivitiStreamingWebScript;
import org.springframework.extensions.webscripts.WebScriptException;
......@@ -43,23 +44,34 @@ import org.springframework.extensions.webscripts.WebScriptResponse;
*/
public class ContentGet extends ActivitiStreamingWebScript {
private CycleService cycleService;
protected CycleService cycleService;
private void init(ActivitiRequest req) {
String cuid = req.getCurrentUserId();
protected CycleRepositoryService repositoryService;
HttpSession session = req.getHttpServletRequest().getSession(true);
protected CycleTagService cycleTagService;
// Retrieve the list of configured connectors for the current user
List<RepositoryConnector> connectors = CycleServiceImpl.getConfiguredRepositoryConnectors(cuid, session);
protected CycleConfigurationService configurationService;
// Initialize the cycleService
this.cycleService = CycleServiceImpl.getCycleService(cuid, session, connectors);
public ContentGet() {
cycleService = CycleServiceImpl.getInstance();
configurationService = cycleService.getConfigurationService();
repositoryService = cycleService.getRepositoryService();
cycleTagService = cycleService.getTagService();
}
@Override
protected void executeStreamingWebScript(ActivitiRequest req, WebScriptResponse res) throws IOException {
init(req);
try {
CycleHttpSession.openSession(req);
getContent(req, res);
} finally {
CycleHttpSession.closeSession();
}
}
private void getContent(ActivitiRequest req, WebScriptResponse res) throws IOException {
// Retrieve the artifactId from the request
String cnonectorId = req.getMandatoryString("connectorId");
......@@ -67,7 +79,7 @@ public class ContentGet extends ActivitiStreamingWebScript {
String contentRepresentationId = req.getMandatoryString("contentRepresentationId");
// Retrieve the artifact from the repository
RepositoryArtifact artifact = cycleService.getRepositoryArtifact(cnonectorId, artifactId);
RepositoryArtifact artifact = repositoryService.getRepositoryArtifact(cnonectorId, artifactId);
ContentRepresentation contentRepresentation = artifact.getArtifactType().getContentRepresentation(contentRepresentationId);
......@@ -100,11 +112,11 @@ public class ContentGet extends ActivitiStreamingWebScript {
InputStream contentInputStream = null;
try {
contentInputStream = this.cycleService.getContent(artifact.getConnectorId(), artifact.getNodeId(), contentRepresentation.getId()).asInputStream();
contentInputStream = repositoryService.getContent(artifact.getConnectorId(), artifact.getNodeId(), contentRepresentation.getId()).asInputStream();
// Calculate an etag for the content using the MD5 algorithm
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(this.cycleService.getContent(artifact.getConnectorId(), artifact.getNodeId(), contentRepresentation.getId())
byte[] messageDigest = md.digest(repositoryService.getContent(artifact.getConnectorId(), artifact.getNodeId(), contentRepresentation.getId())
.asByteArray());
BigInteger number = new BigInteger(1, messageDigest);
String etag = number.toString(16);
......@@ -138,7 +150,6 @@ public class ContentGet extends ActivitiStreamingWebScript {
} finally {
IoUtil.closeSilently(contentInputStream);
}
}
}
......@@ -36,7 +36,7 @@ public class ContentRepresentationGet extends ActivitiCycleWebScript {
String artifactId = req.getString("artifactId");
String representationId = req.getString("representationId");
RepositoryArtifact artifact = this.cycleService.getRepositoryArtifact(connectorId, artifactId);
RepositoryArtifact artifact = repositoryService.getRepositoryArtifact(connectorId, artifactId);
// Get representation by id to determine whether it is an image...
try {
......@@ -55,7 +55,7 @@ public class ContentRepresentationGet extends ActivitiCycleWebScript {
case BINARY:
case CODE:
case TEXT_PLAIN:
String content = this.cycleService.getContent(connectorId, artifactId, contentRepresentation.getId()).asString();
String content = repositoryService.getContent(connectorId, artifactId, contentRepresentation.getId()).asString();
model.put("content", content);
}
model.put("renderInfo", contentRepresentation.getRenderInfo().name());
......
......@@ -15,8 +15,8 @@ package org.activiti.rest.api.cycle;
import java.util.Map;
import org.activiti.cycle.CycleService;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.service.CycleService;
import org.activiti.rest.util.ActivitiRequest;
import org.activiti.rest.util.ActivitiRequestObject;
import org.springframework.extensions.webscripts.Cache;
......@@ -39,7 +39,7 @@ public class FolderPost extends ActivitiCycleWebScript {
String name = req.getMandatoryString(obj, "name");
try {
this.cycleService.createFolder(connectorId, parentFolderId, name);
repositoryService.createFolder(connectorId, parentFolderId, name);
model.put("result", true);
} catch (Exception e) {
model.put("result", false);
......
......@@ -30,7 +30,7 @@ public class IncomingArtifactLinksGet extends ActivitiCycleWebScript {
protected void execute(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
String connectorId = req.getMandatoryString("connectorId");
String artifactId = req.getString("artifactId");
List<RepositoryArtifactLink> links = this.cycleService.getIncomingArtifactLinks(connectorId, artifactId);
List<RepositoryArtifactLink> links = repositoryService.getIncomingArtifactLinks(connectorId, artifactId);
model.put("links", links);
}
......
......@@ -30,7 +30,7 @@ public class TagDelete extends ActivitiCycleWebScript {
String connectorId = req.getMandatoryString("connectorId");
String repositoryNodeId = req.getMandatoryString("repositoryNodeId");
String tagName = req.getMandatoryString("tagName");
this.cycleService.deleteTag(connectorId, repositoryNodeId, tagName);
tagService.deleteTag(connectorId, repositoryNodeId, tagName);
}
}
......@@ -46,7 +46,7 @@ public class TagPost extends ActivitiCycleWebScript {
String tagName = req.getMandatoryString(obj, "tagName");
String alias = req.getMandatoryString(obj, "alias");
this.cycleService.addTag(connectorId, repositoryNodeId, tagName, alias);
tagService.addTag(connectorId, repositoryNodeId, tagName, alias);
model.put("connectorId", connectorId);
model.put("repositoryNodeId", repositoryNodeId);
model.put("tagName", tagName);
......
......@@ -34,9 +34,9 @@ public class TagsGet extends ActivitiCycleWebScript {
List<String> tags;
if (connectorId != null && repositoryNodeId != null) {
tags = this.cycleService.getTags(connectorId, repositoryNodeId);
tags = tagService.getTags(connectorId, repositoryNodeId);
} else {
tags = this.cycleService.getSimiliarTagNames(tag != null ? tag : "");
tags = tagService.getSimiliarTagNames(tag != null ? tag : "");
}
model.put("tags", tags);
}
......
......@@ -32,7 +32,7 @@ public class TagsPost extends ActivitiCycleWebScript {
String connectorId = req.getMandatoryString(obj, "connectorId");
String repositoryNodeId = req.getMandatoryString(obj, "repositoryNodeId");
List<String> tags = req.getMandatoryList(obj, "tags", ActivitiRequestObject.STRING);
this.cycleService.setTags(connectorId, repositoryNodeId, tags);
tagService.setTags(connectorId, repositoryNodeId, tags);
}
}
......@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List;
import org.activiti.rest.api.cycle.dto.ArtifactLinkDto;
import org.activiti.rest.api.cycle.dto.ContentView;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
......
......@@ -22,7 +22,6 @@ import org.activiti.rest.util.ActivitiRequest;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
/**
* @author Nils Preusker (nils.preusker@camunda.com)
*/
......@@ -30,19 +29,18 @@ public class UserConfigGet extends ActivitiCycleWebScript {
@Override
void execute(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
Map<String, List<String>> connectors = this.cycleService.getConfiguredRepositoryConnectors(req.getCurrentUserId());
Map<String, List<Map<String,String>>> connectorsForJson = new HashMap<String, List<Map<String, String>>>();
for(String key : connectors.keySet()) {
List <Map<String, String>> configs = new ArrayList<Map<String, String>>();
for(String configId : connectors.get(key)) {
configs.add(this.cycleService.getRepositoryConnectorConfiguration(configId, req.getCurrentUserId()));
Map<String, List<String>> connectors = configurationService.getConfiguredRepositoryConnectors();
Map<String, List<Map<String, String>>> connectorsForJson = new HashMap<String, List<Map<String, String>>>();
for (String key : connectors.keySet()) {
List<Map<String, String>> configs = new ArrayList<Map<String, String>>();
for (String configId : connectors.get(key)) {
configs.add(configurationService.getRepositoryConnectorConfiguration(configId));
}
connectorsForJson.put(key, configs);
}
model.put("userConfig", connectorsForJson);
}
}
......@@ -34,7 +34,7 @@ public class UserConfigPost extends ActivitiCycleWebScript {
String configurationId = json.getString("configurationId");
Map<String, String> values = json.getMap("values");
this.cycleService.updateRepositoryConnectorConfiguration(configurationClass, configurationId, values, req.getCurrentUserId());
configurationService.updateRepositoryConnectorConfiguration(configurationClass, configurationId, values);
}
......
package org.activiti.rest.api.cycle.session;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.CycleSessionContext;
import org.activiti.cycle.RepositoryAuthenticationException;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
import org.activiti.cycle.impl.connector.view.TagConnectorConfiguration;
import org.activiti.cycle.impl.plugin.PluginFinder;
import org.activiti.cycle.impl.service.CycleServiceImpl;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleRepositoryService.RuntimeConnectorList;
import org.activiti.rest.util.ActivitiRequest;
public class CycleHttpSession {
public static void openSession(ActivitiRequest req) {
HttpSession httpSession = req.getHttpServletRequest().getSession(true);
String cuid = req.getCurrentUserId();
// TODO: find a better place for this ?
PluginFinder.registerServletContext(httpSession.getServletContext());
// Makes the HttpSession available as CycleSessionContext
CycleSessionContext.setCurrentContext(new HttpSessionContext(httpSession));
CycleSessionContext.setInCurrentContext("cuid", cuid);
boolean couldRestoreConnectors = loadRuntimeRepositoryConnectors();
checkPasswordEnabledConnectors(req);
if (!couldRestoreConnectors) {
performLogin();
}
}
private static boolean loadRuntimeRepositoryConnectors() {
boolean couldRestore = false;
// try to retrieve list of connectors form the session
RuntimeConnectorList connectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
if (connectorList == null) {
// store new connector-list in session
connectorList = new RuntimeConnectorList();
CycleSessionContext.setInCurrentContext(RuntimeConnectorList.class, connectorList);
}
if (connectorList.connectors == null) {
// populate list of connectors if empty
ConfigurationContainer container = CycleServiceImpl.getInstance().getConfigurationService().getConfigurationContainer();
List<RepositoryConnector> connectors = container.getConnectorList();
connectorList.connectors = connectors;
} else {
// connectors could be restored
couldRestore = true;
}
return couldRestore;
}
private static void checkPasswordEnabledConnectors(ActivitiRequest req) {
// this is guaranteed to be initialized now
RuntimeConnectorList connectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
// Make sure we know username and password for all connectors that require
// login. If it is not stored in the users configuration it should be
// provided as a parameter in the request.
Map<String, String> connectorsWithoutLoginMap = new HashMap<String, String>();
for (RepositoryConnector connector : getPasswordEnabledConnectors(connectorList.connectors)) {
PasswordEnabledRepositoryConnectorConfiguration conf = (PasswordEnabledRepositoryConnectorConfiguration) connector.getConfiguration();
String username = req.getString(conf.getId() + "_username");
String password = req.getString(conf.getId() + "_password");
if (username != null && password != null) {
// Remove the connector from the configuration for this session since
// the user pressed cancel in the authentication dialog.
if (username.equals("\"\"") && password.equals("\"\"")) {
connectorList.connectors.remove(connector);
} else {
conf.setUser(username);
conf.setPassword(password);
}
} else if (conf.getUser() == null || conf.getPassword() == null) {
connectorsWithoutLoginMap.put(conf.getId(), conf.getName());
}
// If one or more logins are missing (not provided in either the
// configuration or as HTTP parameter) we'll throw an authentication
// exception with the list of connectors that are missing login
// information
}
if (connectorsWithoutLoginMap.size() > 0) {
// TODO: i18n
throw new RepositoryAuthenticationException("Please provide your username and password for the following repositories:", connectorsWithoutLoginMap);
}
}
private static void performLogin() {
// this is guaranteed to be initialized now
RuntimeConnectorList connectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
CycleRepositoryService repositoryService = CycleServiceImpl.getInstance().getRepositoryService();
// If we get here we can assume that all the required logins are
// available
// and we can now perform the login for those connectors that require it
for (RepositoryConnector connector : connectorList.connectors) {
if (PasswordEnabledRepositoryConnectorConfiguration.class.isInstance(connector.getConfiguration())) {
PasswordEnabledRepositoryConnectorConfiguration conf = (PasswordEnabledRepositoryConnectorConfiguration) connector.getConfiguration();
String username = conf.getUser();
String password = conf.getPassword();
try {
repositoryService.login(username, password, conf.getId());
} catch (RepositoryException e) {
Map<String, String> connectorMap = new HashMap<String, String>();
connectorMap.put(conf.getId(), conf.getName());
throw new RepositoryAuthenticationException("Repository authentication error: couldn't login to " + conf.getName(), connectorMap, e);
}
}
}
// add tag connector hard coded for the moment (at the first node in the
// tree)
// TODO: move to better place !!!
connectorList.connectors.add(0, new TagConnectorConfiguration(CycleServiceImpl.getInstance()).createConnector());
}
private static List<RepositoryConnector> getPasswordEnabledConnectors(List<RepositoryConnector> connectors) {
List<RepositoryConnector> loginEnabledconnectors = new ArrayList<RepositoryConnector>();
for (RepositoryConnector connector : connectors) {
if (connector.getConfiguration() instanceof PasswordEnabledRepositoryConnectorConfiguration) {
loginEnabledconnectors.add(connector);
}
}
return loginEnabledconnectors;
}
public static void closeSession() {
CycleSessionContext.clearCurrentContext();
}
}
package org.activiti.rest.api.cycle.session;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.CycleSessionContext.Context;
public class HttpSessionContext implements Context {
private final HttpSession session;
public HttpSessionContext(HttpSession session) {
this.session = session;
}
public void set(String key, Object value) {
session.setAttribute(key, value);
}
public Object get(String key) {
return session.getAttribute(key);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册