提交 eeee0968 编写于 作者: M meyerd

Activiti Cycle: Added support for cycle component-declaration via annotations,...

Activiti Cycle: Added support for cycle component-declaration via annotations, adjusted lazy-connector login to new architecture.

上级 cb55856d
package org.activiti.cycle;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.Interceptors;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.CycleComponentInvocationHandler;
import org.activiti.cycle.impl.Interceptor;
import org.scannotation.AnnotationDB;
import org.scannotation.ClasspathUrlFinder;
import org.scannotation.WarUrlFinder;
/**
* Factory for cycle components. Components are classes annotated by
* {@link CycleComponent}.
*/
public abstract class CycleComponentFactory {
public static final class CycleComponentDescriptor {
public final String name;
public final CycleContextType contextType;
public final Class< ? > clazz;
private CycleComponentDescriptor(String name, CycleContextType type, Class< ? > clazz) {
this.name = name;
this.contextType = type;
this.clazz = clazz;
}
}
private Logger logger = Logger.getLogger(CycleComponentFactory.class.getName());
/**
* @Singleton instance
*/
private static CycleComponentFactory INSTANCE;
private ServletContext servletContext;
/**
* all available components by name
*/
private Map<String, CycleComponentDescriptor> descriptorRegistry = new HashMap<String, CycleComponentFactory.CycleComponentDescriptor>();
/**
* List of {@link RepositoryConnector}s
*/
private Set<String> repositoryConnectors = new HashSet<String>();
/**
* List of Actions
*/
private Set<String> actions = new HashSet<String>();
private boolean initialized = false;
private void guaranteeInitialization() {
if (!initialized)
synchronized (this) {
if (!initialized) {
init();
}
}
}
@SuppressWarnings("unchecked")
private Object getComponentInstance(Class< ? > clazz) {
Object obj = getComponentInstance(clazz.getCanonicalName());
return obj;
}
private Object getComponentInstance(String name) {
guaranteeInitialization();
CycleComponentDescriptor descriptor = descriptorRegistry.get(name);
if (descriptor == null) {
throw new RuntimeException("No component with name '" + name + "' found.");
}
return getComponentInstance(descriptor);
}
private Object getComponentInstance(CycleComponentDescriptor descriptor) {
guaranteeInitialization();
if (descriptor == null)
throw new IllegalArgumentException("Descriptor must not be null");
// try to restore from context:
Object instance = restoreFormContext(descriptor);
if (instance != null)
return instance;
// create new instance
instance = createInstance(descriptor.name, descriptor.clazz);
// decorate instance
instance = decorateInstance(instance, descriptor.clazz);
// store in context
storeInContext(instance, descriptor);
return instance;
}
private CycleComponentDescriptor getComponentDescriptor(String name) {
guaranteeInitialization();
return descriptorRegistry.get(name);
}
private CycleComponentDescriptor getComponentDescriptor(Class< ? > clazz) {
return getComponentDescriptor(clazz.getCanonicalName());
}
private Object restoreFormContext(CycleComponentDescriptor descriptor) {
switch (descriptor.contextType) {
case SESSION:
CycleContext sessionContext = CycleSessionContext.getLocalContext();
if (sessionContext != null) {
sessionContext.get(descriptor.name);
}
break;
case APPLICATION:
return CycleApplicationContext.get(descriptor.name);
}
return null;
}
private void storeInContext(Object instance, CycleComponentDescriptor descriptor) {
switch (descriptor.contextType) {
case SESSION:
CycleSessionContext.set(descriptor.name, instance);
break;
case APPLICATION:
CycleApplicationContext.set(descriptor.name, instance);
break;
}
}
private <T> T createInstance(String name, Class<T> type) {
try {
return type.newInstance();
} catch (Exception e) {
throw new RuntimeException("Cannot create instance of component '" + name + "' of type '" + type + "': " + e.getMessage(), e);
}
}
private Object decorateInstance(Object instanceToDecorate, Class< ? > type) {
Interceptors interceptors = type.getAnnotation(Interceptors.class);
if (interceptors == null)
return instanceToDecorate;
Class< ? extends Interceptor>[] interceptorClasses = interceptors.value();
if (interceptorClasses.length == 0) {
return instanceToDecorate;
}
try {
return decorateInstance(instanceToDecorate, interceptorClasses);
} catch (Exception e) {
throw new RuntimeException("Cannot decorate instance '" + instanceToDecorate + "' with decorators: '" + e.getMessage() + "'.", e);
}
}
private Object decorateInstance(Object instanceToDecorate, Class< ? extends Interceptor>[] interceptorClasses) throws Exception {
Set<Class< ? >> interfaces = new HashSet<Class< ? >>();
Class< ? > superClass = instanceToDecorate.getClass();
// collect implemented interfaces of this instance
while (superClass != null && !superClass.equals(Object.class)) {
interfaces.addAll(Arrays.asList(superClass.getInterfaces()));
superClass = superClass.getSuperclass();
}
if (interfaces.size() == 0) {
throw new RuntimeException("Cannot decorate instance '" + instanceToDecorate + "'. Implements no interfaces.");
}
Interceptor[] interceptorInstances = new Interceptor[interceptorClasses.length];
for (int i = 0; i < interceptorClasses.length; i++) {
Class< ? extends Interceptor> interceptorClass = interceptorClasses[i];
Interceptor interceptorInstance = interceptorClass.newInstance();
interceptorInstances[i] = interceptorInstance;
}
InvocationHandler invocationHandler = new CycleComponentInvocationHandler(instanceToDecorate, interceptorInstances);
// TODO: which classloader do we use?
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
return Proxy.newProxyInstance(classLoader, interfaces.toArray(new Class< ? >[0]), invocationHandler);
}
private void init() {
scanForComponents();
initialized = true;
}
private void scanForComponents() {
AnnotationDB db = new AnnotationDB();
URL[] urls = null;
if (servletContext == null) {
urls = ClasspathUrlFinder.findClassPaths();
logger.log(Level.INFO, "Activiti Cycle Plugin finder uses normal classpath");
} else {
urls = WarUrlFinder.findWebInfLibClasspaths(servletContext);
}
try {
db.scanArchives(urls);
} catch (IOException e) {
logger.log(Level.SEVERE, "Cannot scan for components: " + e.getMessage(), e);
return;
}
// look for cycle components
Set<String> componentClassNames = db.getAnnotationIndex().get(CycleComponent.class.getName());
for (String componentClassName : componentClassNames) {
Class< ? > cycleComponentClass;
try {
cycleComponentClass = this.getClass().getClassLoader().loadClass(componentClassName);
registerComponent(cycleComponentClass);
} catch (ClassNotFoundException e) {
logger.log(Level.WARNING, "Cannot find class for '" + componentClassName + "': " + e.getMessage(), e);
}
}
}
private String registerComponent(Class< ? > cycleComponentClass) {
CycleComponent componentAnnotation = cycleComponentClass.getAnnotation(CycleComponent.class);
String name = componentAnnotation.value();
if (name == null)
name = componentAnnotation.name();
if (name == null || name.length() == 0) {
name = cycleComponentClass.getCanonicalName();
}
if (descriptorRegistry.containsKey(name)) {
logger.log(Level.SEVERE,
"Cannot register component of type '" + cycleComponentClass + "', name '" + name + "', copmonent of type '" + descriptorRegistry.get(name)
+ "', has same name.");
}
// init component descriptor:
CycleComponentDescriptor componentDescriptor = new CycleComponentDescriptor(name, componentAnnotation.context(), cycleComponentClass);
descriptorRegistry.put(name, componentDescriptor);
return name;
}
private static CycleComponentFactory getInstance() {
if (INSTANCE == null) {
synchronized (CycleComponentFactory.class) {
if (INSTANCE == null) {
INSTANCE = new CycleComponentFactory() {
};
}
}
}
return INSTANCE;
}
public static void registerServletContext(ServletContext servletContext) {
getInstance().servletContext = servletContext;
}
public static <T> T getCycleComponentInstance(Class< ? > clazz, Class<T> castTo) {
Object instance = getInstance().getComponentInstance(clazz);
return castSafely(instance, castTo);
}
@SuppressWarnings("unchecked")
private static <T> T castSafely(Object instance, Class<T> to) {
if (instance == null)
return null;
return (T) instance;
}
public static <T> T getCycleComponentInstance(String name, Class<T> castTo) {
Object instance = getInstance().getComponentInstance(name);
return castSafely(instance, castTo);
}
public static Object getCycleComponentInstance(Class< ? > clazz) {
return getInstance().getComponentInstance(clazz);
}
public static Object getCycleComponentInstance(String name) {
return getInstance().getComponentInstance(name);
}
public static CycleComponentDescriptor getCycleComponentDescriptor(String name) {
return getInstance().getComponentDescriptor(name);
}
public static CycleComponentDescriptor getCycleComponentDescriptor(Class< ? > clazz) {
return getInstance().getComponentDescriptor(clazz);
}
}
......@@ -23,91 +23,97 @@ import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
*/
public interface RepositoryConnector {
public RepositoryConnectorConfiguration getConfiguration();
/**
* log in given user and return true, if login was successful and false, if
* the user couldn't be logged in
*/
public boolean login(String username, String password);
// /**
// * get all child nodes of a node with the given url, independent if the
// * children are folders or artifacts.
// */
// public List<RepositoryNode> getChildNodes(String parentId) throws
// RepositoryNodeNotFoundException;
/**
* load the {@link RepositoryArtifact} including details
*/
public RepositoryArtifact getRepositoryArtifact(String id) 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 artifactId) throws RepositoryNodeNotFoundException;
public RepositoryFolder getRepositoryFolder(String id) throws RepositoryNodeNotFoundException;
/**
* gets all elements
*/
public RepositoryNodeCollection getChildren(String id) 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 folderId);
/**
* create a new file in the given folder with the default
* {@link ContentRepresentation}
*
* @param artifactId
*/
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException;
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException;
/**
* create a new subfolder in the given folder
*/
public RepositoryFolder createFolder(String parentFolderId, String name) throws RepositoryNodeNotFoundException;
public Content getContent(String artifactId, String representationName) throws RepositoryNodeNotFoundException;
/**
* update artifact content with default {@link ContentRepresentation}
*/
public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException;
public void updateContent(String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException;
/**
* deletes the given file from the folder
*/
public void deleteArtifact(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 folderId) throws RepositoryNodeNotFoundException;
/**
* TODO double check the signature
*/
public void executeParameterizedAction(String artifactId, String actionId, Map<String, Object> parameters) throws Exception;
// public String getGlobalId(RepositoryNode node);
public RepositoryConnectorConfiguration getConfiguration();
/**
* log in given user and return true, if login was successful and false, if
* the user couldn't be logged in
*/
public boolean login(String username, String password);
// /**
// * get all child nodes of a node with the given url, independent if the
// * children are folders or artifacts.
// */
// public List<RepositoryNode> getChildNodes(String parentId) throws
// RepositoryNodeNotFoundException;
/**
* load the {@link RepositoryArtifact} including details
*/
public RepositoryArtifact getRepositoryArtifact(String id) 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 artifactId) throws RepositoryNodeNotFoundException;
public RepositoryFolder getRepositoryFolder(String id) throws RepositoryNodeNotFoundException;
/**
* gets all elements
*/
public RepositoryNodeCollection getChildren(String id) 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 folderId);
/**
* create a new file in the given folder with the default
* {@link ContentRepresentation}
*
* @param artifactId
*/
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException;
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException;
/**
* create a new subfolder in the given folder
*/
public RepositoryFolder createFolder(String parentFolderId, String name) throws RepositoryNodeNotFoundException;
public Content getContent(String artifactId, String representationName) throws RepositoryNodeNotFoundException;
/**
* update artifact content with default {@link ContentRepresentation}
*/
public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException;
public void updateContent(String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException;
/**
* deletes the given file from the folder
*/
public void deleteArtifact(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 folderId) throws RepositoryNodeNotFoundException;
/**
* TODO double check the signature
*/
public void executeParameterizedAction(String artifactId, String actionId, Map<String, Object> parameters) throws Exception;
/**
* return true if the connector is currently logged in, returns false,
* otherwise.
*/
public boolean isLoggedIn();
public void setConfiguration(RepositoryConnectorConfiguration configuration);
// public String getGlobalId(RepositoryNode node);
}
package org.activiti.cycle.context;
import java.util.HashMap;
/**
* The cycle application context, holds objects of scope
* {@link CycleContextType#APPLICATION}.
*
* @author daniel.meyer@camunda.com
*/
public class CycleApplicationContext {
private static CycleContext wrappedContext = new CycleContext() {
private HashMap<String, Object> map = new HashMap<String, Object>();
public void set(String key, Object value) {
map.put(key, value);
}
public Object get(String key) {
return map.get(key);
}
};
public static void set(String key, Object value) {
wrappedContext.set(key, value);
}
public static Object get(String key) {
return wrappedContext.get(key);
}
public static void setWrappedContext(CycleContext context) {
wrappedContext = context;
}
}
package org.activiti.cycle.context;
/**
* Context interface for Cycle Contexts. Used to acces Key/Value stores. We use
* this interface to abstract form concrete contexts such as the http-session
* context.
*
* @author daniel.meyer@camunda.com
*/
public interface CycleContext {
public void set(String key, Object value);
public Object get(String key);
}
package org.activiti.cycle.context;
/**
* Cycle supports different 'types' of contexts. The {@link #SESSION}-Context
* corresponds to a user-session and is initialized once per user-Session. The
* {@link #APPLICATION}-Context is a singleton-scope. When an instance of a
* {@link #NONE}-scoped component is retrieved, a fresh instance is created for
* each retrieval.
*
* @author daniel.meyer@camunda.com
*/
public enum CycleContextType {
SESSION,
APPLICATION,
NONE;
}
package org.activiti.cycle;
package org.activiti.cycle.context;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.CycleComponentFactory.CycleComponentDescriptor;
/**
* Context for session-scoped variables. Wraps a {@link Context}-object and
......@@ -8,59 +11,58 @@ package org.activiti.cycle;
*/
public class CycleSessionContext {
public static interface Context {
public void set(String key, Object value);
public Object get(String key);
}
private static ThreadLocal<CycleContext> localContext = new ThreadLocal<CycleContext>();
private static ThreadLocal<Context> localContext = new ThreadLocal<CycleSessionContext.Context>();
public static void setInCurrentContext(String key, Object value) {
Context context = localContext.get();
public static void set(String key, Object value) {
CycleContext 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();
public static <T> T get(String key, Class<T> clazz) {
Object obj = get(key);
if (obj == null) {
return null;
}
return (T) obj;
}
public static Object get(String key) {
CycleContext context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
Object obj = context.get(key);
if (obj != null) {
return (T) obj;
if (obj == null) {
// try to restore component instance using the
CycleComponentDescriptor descriptor = CycleComponentFactory.getCycleComponentDescriptor(key);
if (descriptor != null)
if (descriptor.contextType.equals(CycleContextType.SESSION)) {
// note: adds obj to SessionContext
obj = CycleComponentFactory.getCycleComponentInstance(key);
}
}
return null;
return obj;
}
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);
public static <T> void set(Class<T> key, Object value) {
set(key.getCanonicalName(), 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 <T> T get(Class<T> key) {
return get(key.getCanonicalName(), key);
}
public static CycleContext getLocalContext() {
return localContext.get();
}
public static void setCurrentContext(Context context) {
public static void setContext(CycleContext context) {
localContext.set(context);
}
public static void clearCurrentContext() {
public static void clearContext() {
localContext.remove();
}
......
......@@ -22,7 +22,7 @@ public class ConfigurationContainer {
* Signavio, department wide SVN, team shared folders and special user
* specific stuff for e.g. local file system
*
* We allowed multiple parent {@link ConfigurationContainer}s too be flexible.
* We allowed multiple parent {@link ConfigurationContainer}s to be flexible.
* Maybe that is not the best idea for complexity?
*/
private List<ConfigurationContainer> parentContainers = new ArrayList<ConfigurationContainer>();
......
......@@ -23,11 +23,19 @@ public abstract class AbstractRepositoryConnector<T extends RepositoryConnectorC
public AbstractRepositoryConnector(T configuration) {
this.configuration = configuration;
}
public AbstractRepositoryConnector() {
}
public T getConfiguration() {
return configuration;
}
public void setConfiguration(RepositoryConnectorConfiguration configuration) {
this.configuration = (T) configuration;
}
/**
* Typical basic implementation to query {@link Content} from
* {@link ContentProvider} obtained by the {@link ArtifactType} of the
......
......@@ -32,7 +32,7 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
rootNodes = new ArrayList<RepositoryNode>();
content = new HashMap<String, Map<String, byte[]>>();
createDemoData();
createDemoData();
}
private String loggedInUser;
......@@ -54,8 +54,7 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
RepositoryArtifact file2 = createArtifact("/minutes", "InitialMindmap.mm", DemoConnectorPluginDefinition.ARTIFACT_TYPE_MINDMAP,
createContent("/org/activiti/cycle/impl/connector/demo/mindmap.html"));
addContentToInternalMap(file2.getNodeId(), DemoConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_PNG,
createContent(
"/org/activiti/cycle/impl/connector/demo/mindmap.jpg").asByteArray());
createContent("/org/activiti/cycle/impl/connector/demo/mindmap.jpg").asByteArray());
rootNodes.add(folder1);
......@@ -65,10 +64,9 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
RepositoryFolder folder3 = createFolder("/BPMN", "Level3");
RepositoryArtifact file3 = createArtifactFromContentRepresentation("/BPMN/Level3", "InitialBpmnModel", DemoConnectorPluginDefinition.ARTIFACT_TYPE_BPMN_20,
DemoConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_XML,
createContent("/org/activiti/cycle/impl/connector/demo/engine-pool.xml"));
addContentToInternalMap(file3.getNodeId(), DemoConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_PNG, createContent(
"/org/activiti/cycle/impl/connector/demo/bpmn.png").asByteArray());
DemoConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_XML, createContent("/org/activiti/cycle/impl/connector/demo/engine-pool.xml"));
addContentToInternalMap(file3.getNodeId(), DemoConnectorPluginDefinition.CONTENT_REPRESENTATION_ID_PNG,
createContent("/org/activiti/cycle/impl/connector/demo/bpmn.png").asByteArray());
rootNodes.add(folder2);
// nodes.add(folder2);
......@@ -86,9 +84,9 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
public void copyArtifact(RepositoryArtifact artifact, String targetName) {
RepositoryArtifact copy = new RepositoryArtifactImpl(getConfiguration().getId(), targetName, artifact.getArtifactType(), this);
nodes.add(copy);
Collection<ContentRepresentation> contentRepresentationDefinitions = artifact.getArtifactType().getContentRepresentations();
for (ContentRepresentation def : contentRepresentationDefinitions) {
def.getId();
......@@ -108,7 +106,7 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
public static RepositoryFolderImpl clone(RepositoryFolder folder) {
// TODO: Maybe make deep copy?
RepositoryFolderImpl newFolder = new RepositoryFolderImpl(folder.getConnectorId(), folder.getNodeId());
newFolder.getMetadata().setName(folder.getMetadata().getName());
newFolder.getMetadata().setParentFolderId(folder.getMetadata().setParentFolderId());
return newFolder;
......@@ -123,10 +121,9 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
newArtifact.getMetadata().setName(artifact.getMetadata().getName());
newArtifact.getMetadata().setParentFolderId(artifact.getMetadata().setParentFolderId());
return newArtifact;
}
private void addContentToInternalMap(String artifactId, String name, byte[] byteArray) {
Map<String, byte[]> map = content.get(artifactId);
......@@ -137,15 +134,15 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
map.put(name, byteArray);
}
public Content getContent(String artifactId, String representationName) throws RepositoryNodeNotFoundException {
Map<String, byte[]> map = content.get(artifactId);
byte[] bs = map.get(representationName);
Content c = new Content();
c.setValue(bs);
return c;
}
}
private Content createContent(String contentSourceUrl) {
Content result = new Content();
InputStream in = null;
......@@ -172,11 +169,11 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
} catch (Exception ex) {
throw new RepositoryException("couldn't create content from URL " + contentSourceUrl, ex);
} finally {
IoUtil.closeSilently(in);
IoUtil.closeSilently(in);
}
return result;
}
return result;
}
public RepositoryNodeCollection getChildren(String parentUrl) throws RepositoryNodeNotFoundException {
ArrayList<RepositoryNode> list = new ArrayList<RepositoryNode>();
if ("/".equals(parentUrl)) {
......@@ -189,7 +186,7 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
// remove / at the end
String remainingUrl = node.getNodeId().substring(parentUrl.length() + 1);
remainingUrl = remainingUrl.substring(0, remainingUrl.length() - 1);
if (!remainingUrl.contains("/")) {
list.add(clone(node));
}
......@@ -211,7 +208,7 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
}
throw new RepositoryNodeNotFoundException(getConfiguration().getName(), RepositoryArtifact.class, id);
}
public RepositoryFolder getRepositoryFolder(String id) {
for (RepositoryNode node : nodes) {
if (node.getNodeId().equals(id) && node instanceof RepositoryFolder) {
......@@ -219,22 +216,21 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
}
}
throw new RepositoryNodeNotFoundException(getConfiguration().getName(), RepositoryFolder.class, id);
}
}
public boolean login(String username, String password) {
log.fine("login called with user " + username + " and password " + password);
loggedInUser = username;
return true;
}
public void commitPendingChanges(String comment) {
}
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException {
return createArtifactFromContentRepresentation(parentFolderId, artifactName, artifactType, getArtifactType(artifactType)
.getDefaultContentRepresentation().getId(),
artifactContent);
return createArtifactFromContentRepresentation(parentFolderId, artifactName, artifactType, getArtifactType(artifactType).getDefaultContentRepresentation()
.getId(), artifactContent);
}
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
......@@ -243,12 +239,12 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
if (!id.startsWith("/")) {
id = "/" + id;
}
if (id.length()>1) {
if (id.length() > 1) {
// all but root folder
id = id + "/";
}
id = id + artifactName;
RepositoryArtifact newArtifact = new RepositoryArtifactImpl(getConfiguration().getId(), id, getArtifactType(artifactType), this);
newArtifact.getMetadata().setName(artifactName);
newArtifact.getMetadata().setParentFolderId(parentFolderId);
......@@ -264,8 +260,8 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
public void updateContent(String artifactId, String contentRepresentationId, Content artifactContent) {
addContentToInternalMap(artifactId, contentRepresentationId, artifactContent.asByteArray());
}
}
public RepositoryFolder createFolder(String parentFolderId, String name) throws RepositoryNodeNotFoundException {
String id = parentFolderId;
if (!id.startsWith("/")) {
......@@ -295,4 +291,8 @@ public class DemoConnector extends AbstractRepositoryConnector<DemoConnectorConf
public void exceuteAction(String artifactId, String actionId, Map<String, Object> parameters) {
}
public boolean isLoggedIn() {
return loggedInUser != null;
}
}
......@@ -16,6 +16,7 @@ import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.impl.RepositoryArtifactImpl;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
......@@ -28,11 +29,16 @@ import eu.medsea.mimeutil.MimeUtil;
*
* @author ruecker
*/
@CycleComponent
public class FileSystemConnector extends AbstractRepositoryConnector<FileSystemConnectorConfiguration> {
public FileSystemConnector(FileSystemConnectorConfiguration conf) {
super(conf);
}
public FileSystemConnector() {
}
public boolean login(String username, String password) {
// login is not need to access local file system, so everything we get is
......@@ -263,4 +269,8 @@ public class FileSystemConnector extends AbstractRepositoryConnector<FileSystemC
}
throw new RepositoryException("Unable to determine local path! ('" + path + "')");
}
public boolean isLoggedIn() {
return true;
}
}
......@@ -16,6 +16,7 @@ import java.io.File;
import java.io.IOException;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
......@@ -81,7 +82,9 @@ public class FileSystemConnectorConfiguration extends RepositoryConnectorConfigu
@Override
public RepositoryConnector createConnector() {
return new FileSystemConnector(this);
RepositoryConnector connector = CycleComponentFactory.getCycleComponentInstance(FileSystemConnector.class, RepositoryConnector.class);
connector.setConfiguration(this);
return connector;
}
}
......@@ -32,10 +32,13 @@ import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.Interceptors;
import org.activiti.cycle.impl.RepositoryArtifactImpl;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.connector.AbstractRepositoryConnector;
import org.activiti.cycle.impl.connector.ConnectorLoginInterceptor;
import org.activiti.cycle.impl.connector.signavio.util.SignavioJsonHelper;
import org.activiti.cycle.impl.connector.util.RestClientLogHelper;
import org.json.JSONArray;
......@@ -64,6 +67,8 @@ import de.hpi.bpmn2_0.transformation.Json2XmlConverter;
* @author christian.lipphardt@camunda.com
* @author ruecker
*/
@CycleComponent
@Interceptors({ConnectorLoginInterceptor.class})
public class SignavioConnector extends AbstractRepositoryConnector<SignavioConnectorConfiguration> {
private static Logger log = Logger.getLogger(SignavioConnector.class.getName());
......@@ -82,16 +87,13 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
private boolean loggedIn = false;
public SignavioConnector() {
}
public SignavioConnector(SignavioConnectorConfiguration signavioConfiguration) {
super(signavioConfiguration);
}
protected void checkLoggedIn() {
if (!loggedIn && getConfiguration().isLoginRequired()) {
throw new RepositoryAuthenticationException("Not logged in.", getConfiguration().getId());
}
}
public Client initClient() {
// TODO: Check timeout on client and re-create it
......@@ -304,7 +306,6 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public RepositoryNodeCollection getChildren(String id) throws RepositoryNodeNotFoundException {
checkLoggedIn();
try {
ArrayList<RepositoryNode> nodes = new ArrayList<RepositoryNode>();
if (getConfiguration() instanceof OryxConnectorConfiguration) {
......@@ -425,7 +426,6 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public RepositoryFolder getRepositoryFolder(String id) {
checkLoggedIn();
try {
Response directoryResponse = getJsonResponse(getConfiguration().getDirectoryUrl(id));
JsonRepresentation jsonData = new JsonRepresentation(directoryResponse.getEntity());
......@@ -449,7 +449,6 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public RepositoryArtifact getRepositoryArtifact(String id) {
checkLoggedIn();
JsonRepresentation jsonData = null;
JSONObject jsonObject = null;
......@@ -472,7 +471,6 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public RepositoryFolder createFolder(String parentFolderId, String name) throws RepositoryNodeNotFoundException {
checkLoggedIn();
try {
Form createFolderForm = new Form();
createFolderForm.add("name", name);
......@@ -496,7 +494,6 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public void deleteArtifact(String artifactId) {
checkLoggedIn();
try {
Request jsonRequest = new Request(Method.DELETE, new Reference(getConfiguration().getModelUrl(artifactId)));
jsonRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON));
......@@ -510,7 +507,6 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public void deleteFolder(String subFolderId) {
checkLoggedIn();
try {
Request jsonRequest = new Request(Method.DELETE, new Reference(getConfiguration().getDirectoryUrl(subFolderId)));
jsonRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON));
......@@ -561,14 +557,12 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException {
checkLoggedIn();
// TODO: Add handling of different artifact types!
return createArtifactFromJSON(parentFolderId, artifactName, artifactType, artifactContent.asString());
}
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException {
checkLoggedIn();
// TODO: Add handling of different content representations, e.g. BPMN 2.0
// Import
return createArtifactFromJSON(parentFolderId, artifactName, artifactType, artifactContent.asString());
......@@ -696,13 +690,15 @@ public class SignavioConnector extends AbstractRepositoryConnector<SignavioConne
}
public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException {
checkLoggedIn();
throw new RepositoryException("Moving artifacts is not (yet) supported by the Signavio Connector");
}
public void updateContent(String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException {
checkLoggedIn();
throw new RepositoryException("Moving artifacts is not (yet) supported by the Signavio Connector");
}
public boolean isLoggedIn() {
return loggedIn || !getConfiguration().isLoginRequired();
}
}
......@@ -16,6 +16,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
......@@ -117,7 +118,7 @@ public class SignavioConnectorConfiguration extends PasswordEnabledRepositoryCon
url = url.substring(0, url.length() - 5);
return url;
}
public String getDirectoryIdFromUrl(String href) {
return retrieveIdFromUrl(href, "/" + DIRECTORY_URL_SUFFIX);
}
......@@ -139,7 +140,7 @@ public class SignavioConnectorConfiguration extends PasswordEnabledRepositoryCon
if (id.startsWith("/")) {
// don't encode this one!
id = id.substring(1);
}
}
return getRepositoryBackendUrl() + MODEL_URL_SUFFIX + "/" + encode(id);
}
......@@ -167,7 +168,6 @@ public class SignavioConnectorConfiguration extends PasswordEnabledRepositoryCon
// + id + "'", ex);
// }
public String getDirectoryUrl(String id) {
if (id.startsWith("/")) {
// don't encode this one!
......@@ -227,7 +227,9 @@ public class SignavioConnectorConfiguration extends PasswordEnabledRepositoryCon
@Override
public RepositoryConnector createConnector() {
return new SignavioConnector(this);
RepositoryConnector connector = CycleComponentFactory.getCycleComponentInstance(SignavioConnector.class, RepositoryConnector.class);
connector.setConfiguration(this);
return connector;
}
public boolean isLoginRequired() {
......
......@@ -15,6 +15,7 @@ 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.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.service.CycleServiceFactory;
import org.activiti.cycle.service.CycleTagService;
......@@ -137,4 +138,13 @@ public class TagConnector implements RepositoryConnector {
public void beginTransaction() {
}
public boolean isLoggedIn() {
return true;
}
public void setConfiguration(RepositoryConnectorConfiguration configuration) {
// does not need configuration
}
}
......@@ -6,8 +6,9 @@ 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.components.RuntimeConnectorList;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.conf.RepositoryConfigurationHandler;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
......@@ -17,7 +18,6 @@ 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}.
......@@ -49,7 +49,7 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService
}
protected String getCurrentUserId() {
return CycleSessionContext.getFromCurrentContext("cuid", String.class);
return CycleSessionContext.get("cuid", String.class);
}
public Map<String, String> getRepositoryConnectorConfiguration(String connectorConfigurationId) {
......@@ -181,8 +181,8 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService
cycleConfigurationDao.saveConfiguration(configurationContainer);
// update runtime connectors:
RuntimeConnectorList runtimeConnectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
runtimeConnectorList.connectors = null;
RuntimeConnectorList runtimeConnectorList = CycleSessionContext.get(RuntimeConnectorList.class);
runtimeConnectorList.discardConnectors();
} catch (Exception e) {
throw new RepositoryException("Error while storing config for user " + e.getMessage(), e);
......@@ -222,8 +222,8 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService
cycleConfigurationDao.saveConfiguration(configurationContainer);
// update runtime connectors:
RuntimeConnectorList runtimeConnectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
runtimeConnectorList.connectors = null;
RuntimeConnectorList runtimeConnectorList = CycleSessionContext.get(RuntimeConnectorList.class);
runtimeConnectorList.discardConnectors();
} catch (Exception e) {
throw new RepositoryException("Error while deleting config for user " + e.getMessage(), e);
......
......@@ -6,7 +6,6 @@ import java.util.Map;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.Content;
import org.activiti.cycle.CycleSessionContext;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryConnector;
......@@ -15,6 +14,8 @@ import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.components.RuntimeConnectorList;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
......@@ -70,8 +71,8 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
}
protected List<RepositoryConnector> getRuntimeRepositoryConnectors() {
RuntimeConnectorList connectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
return connectorList.connectors;
RuntimeConnectorList connectorList = CycleSessionContext.get(RuntimeConnectorList.class);
return connectorList.getConnectors();
}
/**
......
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 {
}
package org.activiti.cycle.incubator.connector.svn;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
......@@ -31,7 +32,8 @@ public class SvnConnectorConfiguration extends PasswordEnabledRepositoryConnecto
* @return
*/
public RepositoryConnector createConnector() {
SvnRepositoryConnector theConnector = new SvnRepositoryConnector(this);
RepositoryConnector theConnector = CycleComponentFactory.getCycleComponentInstance(SvnRepositoryConnector.class, RepositoryConnector.class);
theConnector.setConfiguration(this);
return theConnector;
}
......
......@@ -17,7 +17,6 @@ import java.util.logging.Logger;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryAuthenticationException;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.RepositoryFolder;
......@@ -25,10 +24,13 @@ import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.TransactionalRepositoryConnector;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.Interceptors;
import org.activiti.cycle.impl.RepositoryArtifactImpl;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.connector.AbstractRepositoryConnector;
import org.activiti.cycle.impl.connector.ConnectorLoginInterceptor;
import org.activiti.cycle.impl.connector.util.ConnectorPathUtils;
import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
import org.tigris.subversion.svnclientadapter.ISVNDirEntry;
......@@ -52,6 +54,8 @@ import org.tigris.subversion.svnclientadapter.svnkit.SvnKitClientAdapterFactory;
* IMPLEMENTATION NOTE: we perform lazy-initialization of the actual client
* adapter. Make sure to always call getSvnClientAdapter().
*/
@CycleComponent
@Interceptors({ ConnectorLoginInterceptor.class })
public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConnectorConfiguration> implements TransactionalRepositoryConnector {
private static Logger log = Logger.getLogger(SvnRepositoryConnector.class.getName());
......@@ -66,18 +70,17 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
private boolean autocommit = false;
private final ReentrantLock transactionLock = new ReentrantLock();
private boolean loggedIn;
static {
setupFactories();
}
public SvnRepositoryConnector(SvnConnectorConfiguration configuration) {
super(configuration);
validateConfig();
public SvnRepositoryConnector() {
}
protected void validateConfig() {
String repositoryPath = getConfiguration().getRepositoryPath();
if (repositoryPath == null) {
......@@ -89,12 +92,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
}
protected void checkLoggedIn() {
if (!loggedIn) {
throw new RepositoryAuthenticationException("Not logged in.", getConfiguration().getId());
}
}
protected static void setupFactories() {
try {
......@@ -118,7 +115,7 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public boolean login(String username, String password) {
public boolean login(String username, String password) {
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
clientAdapter.setUsername(username);
......@@ -134,7 +131,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public RepositoryArtifact getRepositoryArtifact(String id) throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
try {
......@@ -155,7 +151,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public RepositoryFolder getRepositoryFolder(String id) throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
try {
......@@ -175,7 +170,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public RepositoryNodeCollection getChildren(String id) throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
List<RepositoryNode> nodeList = new ArrayList<RepositoryNode>();
......@@ -220,7 +214,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
File temporaryFileStrore = null;
// begin transaction if not active
......@@ -256,12 +249,10 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException {
checkLoggedIn();
return createArtifact(parentFolderId, artifactName, artifactType, artifactContent);
}
public RepositoryFolder createFolder(String parentFolderId, String name) throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
File temporaryFileStrore = null;
// begin transaction if not active
......@@ -298,7 +289,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException {
checkLoggedIn();
// assure that clientadapter is properly initialized
getSvnClientAdapter();
File temporaryFileStrore = null;
......@@ -339,12 +329,10 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public void updateContent(String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException {
checkLoggedIn();
updateContent(artifactId, content);
}
public void deleteArtifact(String artifactId) throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
......@@ -361,7 +349,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public void deleteFolder(String folderId) throws RepositoryNodeNotFoundException {
checkLoggedIn();
ISVNClientAdapter clientAdapter = getSvnClientAdapter();
try {
......@@ -614,8 +601,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public void commitTransaction(String comment) {
checkLoggedIn();
transactionLock.lock();
if (!transactionActive) {
......@@ -645,7 +630,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public void rollbackTransaction() {
checkLoggedIn();
transactionLock.lock();
if (!transactionActive)
return;
......@@ -673,7 +657,6 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
public void beginTransaction() {
checkLoggedIn();
// do not autocommit on transactions coming in via the public API.
beginTransaction(false);
}
......@@ -711,4 +694,8 @@ public class SvnRepositoryConnector extends AbstractRepositoryConnector<SvnConne
}
}
public boolean isLoggedIn() {
return loggedIn;
}
}
......@@ -4,6 +4,9 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.Interceptors;
import org.activiti.cycle.impl.connector.ConnectorLoginInterceptor;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.VFS;
......@@ -14,6 +17,8 @@ import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent
@Interceptors({ ConnectorLoginInterceptor.class })
public class SftpRepositoryConnector extends VfsConnector {
private static Logger log = Logger.getLogger(SftpRepositoryConnector.class.getName());
......@@ -22,6 +27,9 @@ public class SftpRepositoryConnector extends VfsConnector {
super(configuration);
}
public SftpRepositoryConnector() {
}
protected void validateConfiguration() {
if (getConfiguration().getProtocol() == null)
throw new RepositoryException("No protocol specified");
......
......@@ -19,6 +19,7 @@ import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.impl.RepositoryArtifactImpl;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
import org.activiti.cycle.impl.connector.AbstractRepositoryConnector;
import org.activiti.cycle.impl.connector.util.ConnectorPathUtils;
import org.activiti.cycle.impl.connector.util.ConnectorStreamUtils;
......@@ -51,17 +52,15 @@ public abstract class VfsConnector extends AbstractRepositoryConnector<VfsConnec
protected boolean loggedIn;
protected void checkLoggedIn() {
if (!loggedIn) {
throw new RepositoryAuthenticationException("Not logged in.", getConfiguration().getId());
}
}
public VfsConnector(VfsConnectorConfiguration configuration) {
super(configuration);
validateConfiguration();
}
public VfsConnector() {
}
public RepositoryArtifact getRepositoryArtifact(String id) throws RepositoryNodeNotFoundException {
checkRepository();
......@@ -293,7 +292,6 @@ public abstract class VfsConnector extends AbstractRepositoryConnector<VfsConnec
}
private void checkRepository() {
checkLoggedIn();
getFileSystemManager();
if (connectionString == null)
throw new RepositoryException("You need to login first.");
......@@ -309,6 +307,16 @@ public abstract class VfsConnector extends AbstractRepositoryConnector<VfsConnec
}
}
public boolean isLoggedIn() {
return loggedIn;
}
@Override
public void setConfiguration(RepositoryConnectorConfiguration configuration) {
super.setConfiguration(configuration);
validateConfiguration();
}
protected abstract void validateConfiguration();
public abstract FileSystemManager getFileSystemManager();
......
package org.activiti.cycle.incubator.connector.vfs;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
......@@ -33,7 +34,9 @@ public class VfsConnectorConfiguration extends PasswordEnabledRepositoryConnecto
public RepositoryConnector createConnector() {
if (protocol.equals("sftp")) {
return new SftpRepositoryConnector(this);
RepositoryConnector connectorInstance = CycleComponentFactory.getCycleComponentInstance(SftpRepositoryConnector.class, RepositoryConnector.class);
connectorInstance.setConfiguration(this);
return connectorInstance;
}
throw new RepositoryException("No connector found for protocol " + protocol);
......
......@@ -23,7 +23,7 @@ import org.activiti.cycle.impl.conf.RepositoryConnectorConfiguration;
* manipulation of RepositoryConnectorConfiguraitons is supported, using a
* String-based interface.
* <p />
* Retreive an instance of this Service by
* Retrieve an instance of this Service by
* {@link CycleServiceFactory#getConfigurationService()}
*
* @see CycleService
......@@ -78,8 +78,7 @@ public interface CycleConfigurationService {
public Map<String, List<String>> getConfiguredRepositoryConnectors();
/**
* Returns the {@link ConfigurationContainer} for the user with
* 'currentUserId'.
* Returns the {@link ConfigurationContainer} for the current user.
*/
public ConfigurationContainer getConfigurationContainer();
......
......@@ -35,26 +35,6 @@ import org.activiti.cycle.RepositoryNodeNotFoundException;
*/
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 RepositoryConnector getConnectorById(String id) {
for (RepositoryConnector connector : connectors) {
if (connector.getConfiguration().getId().equals(id))
return connector;
}
return null;
}
}
public void addArtifactLink(RepositoryArtifactLink link);
......
......@@ -9,6 +9,7 @@ import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.TransactionalRepositoryConnector;
import org.activiti.cycle.impl.conf.ConfigurationContainer;
import org.activiti.cycle.impl.plugin.PluginFinder;
import org.activiti.cycle.incubator.connector.svn.SvnConnectorConfiguration;
......@@ -31,18 +32,18 @@ public class TestSvnRepositoryConnector {
private static ConfigurationContainer userConfiguration;
private static SvnRepositoryConnector connector;
private static TransactionalRepositoryConnector connector;
@BeforeClass
public static void createConnector() {
userConfiguration = new ConfigurationContainer("daniel");
userConfiguration.addRepositoryConnectorConfiguration(new SvnConnectorConfiguration("svn", REPO_LOCATION, "/tmp"));
connector = (SvnRepositoryConnector) userConfiguration.getConnector("svn");
connector = (TransactionalRepositoryConnector) userConfiguration.getConnector("svn");
// TODO: Should be done in Bootstrapping
PluginFinder.checkPluginInitialization();
// connector.login("guest", "");
connector.login("guest", "");
}
@Test
......@@ -52,7 +53,6 @@ public class TestSvnRepositoryConnector {
for (RepositoryNode node : result.asList()) {
System.out.println(node.getNodeId());
}
try {
result = connector.getChildren("nonExistentPath");
Assert.fail();
......
package org.activiti.rest.api.cycle.session;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.CycleSessionContext;
import org.activiti.cycle.CycleComponentFactory;
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.components.RuntimeConnectorList;
import org.activiti.cycle.context.CycleSessionContext;
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.service.CycleServiceFactory;
import org.activiti.cycle.service.CycleRepositoryService.RuntimeConnectorList;
import org.activiti.rest.util.ActivitiRequest;
/**
* Initializes the Cycle Http-Session.
*
* @author daniel.meyer@camunda.com
*/
public class CycleHttpSession {
public static interface CycleRequestFilter {
public void doFilter(ActivitiRequest req);
}
public static Set<CycleRequestFilter> requestFilters = new HashSet<CycleRequestFilter>();
static {
requestFilters.add(new ConnectorLoginRequestFilter());
}
......@@ -36,29 +40,13 @@ public class CycleHttpSession {
// TODO: find a better place for this ?
PluginFinder.registerServletContext(httpSession.getServletContext());
CycleComponentFactory.registerServletContext(httpSession.getServletContext());
// Makes the HttpSession available as CycleSessionContext
CycleSessionContext.setCurrentContext(new HttpSessionContext(httpSession));
CycleSessionContext.setInCurrentContext("cuid", cuid);
// load list of runtime connectors
// 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 = CycleServiceFactory.getConfigurationService().getConfigurationContainer();
List<RepositoryConnector> connectors = container.getConnectorList();
// add tag connector hard coded for the moment (at the first node in the
// tree)
connectors.add(0, new TagConnectorConfiguration().createConnector());
connectorList.connectors = connectors;
}
CycleSessionContext.setContext(new HttpSessionContext(httpSession));
// make the current user id available in the session context
CycleSessionContext.set("cuid", cuid);
// invoke request filters
for (CycleRequestFilter requestFilter : requestFilters) {
requestFilter.doFilter(req);
......@@ -68,7 +56,7 @@ public class CycleHttpSession {
public static void tryConnectorLogin(ActivitiRequest req, String connectorId) {
RepositoryConnector connector = null;
// locate connector-instance:
RuntimeConnectorList connectorList = CycleSessionContext.getFromCurrentContext(RuntimeConnectorList.class);
RuntimeConnectorList connectorList = CycleSessionContext.get(RuntimeConnectorList.class);
connector = connectorList.getConnectorById(connectorId);
if (connector == null) {
throw new RuntimeException("Cannot login to repository with id '" + connectorId + "', no such repository.");
......@@ -86,7 +74,7 @@ public class CycleHttpSession {
}
// TODO : get from cookie
// try to login:
try {
CycleServiceFactory.getRepositoryService().login(username, password, connectorId);
......@@ -97,7 +85,7 @@ public class CycleHttpSession {
}
public static void closeSession() {
CycleSessionContext.clearCurrentContext();
CycleSessionContext.clearContext();
}
}
......@@ -2,19 +2,23 @@ package org.activiti.rest.api.cycle.session;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.CycleSessionContext.Context;
import org.activiti.cycle.context.CycleContext;
/**
* Wrapper for {@link HttpSession} Context
*
* @author daniel.meyer@camunda.com
*/
public class HttpSessionContext implements CycleContext {
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);
session.setAttribute(key, value);
}
public Object get(String key) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册