提交 0419f2b6 编写于 作者: M meyerd

Activiti Cycle: code cleanup, finished implementation of the cycle component...

Activiti Cycle: code cleanup, finished implementation of the cycle component infrastructure, added some javadoc for the annotations.
上级 5957d052
/* 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 org.activiti.cycle.action.DownloadContentAction;
import org.activiti.cycle.action.ParameterizedAction;
import org.activiti.cycle.action.RepositoryArtifactOpenLinkAction;
/**
* The type specifies the type of an artifact, e.g. Signavio model, jpdl process
* model, text file, word document, ...
*
* Linked to this type {@link ContentRepresentationDefinition}s for the GUI and
* {@link ArtifactAction}s are defined.
*
* TODO: Think about hierarchy
*
* @author bernd.ruecker@camunda.com
*/
public interface ArtifactType {
public String getId();
public MimeType getMimeType();
/**
* list of {@link ContentRepresentation} in the configured order
*/
public List<ContentRepresentation> getContentRepresentations();
public ContentRepresentation getContentRepresentation(String id);
public ContentRepresentation getDefaultContentRepresentation();
public ContentProvider getContentProvider(String contentRepresentationId);
public List<ParameterizedAction> getParameterizedActions();
public ParameterizedAction getParameterizedAction(String name);
public List<RepositoryArtifactOpenLinkAction> createOpenLinkActions(RepositoryConnector connector, RepositoryArtifact artifact);
public List<DownloadContentAction> getDownloadContentActions();
public Long getRevision();
}
package org.activiti.cycle;
/**
* A content provider can create content, normaly nevessary for a
* {@link ContentRepresentation} for a special {@link RepositoryArtifact}
*
* @author bernd.ruecker@camunda.com
*/
public interface ContentProvider {
public Content createContent(RepositoryConnector connector, RepositoryArtifact artifact);
}
......@@ -2,7 +2,6 @@ package org.activiti.cycle;
import java.io.Serializable;
import org.activiti.cycle.impl.mimetype.Mimetypes;
/**
* TODO: javadoc
......@@ -32,8 +31,7 @@ public interface ContentRepresentation extends Serializable {
public Content getContent(RepositoryArtifact artifact);
/**
* The {@link MimeType} of the returned content. Note: this is not necesarily
* the same mimetype as {@link #getRepositoryArtifactType().getMimeType()}.
* The {@link MimeType} of the returned content.
*/
public MimeType getRepresentationMimeType();
......
......@@ -4,10 +4,14 @@ import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
......@@ -22,6 +26,8 @@ import org.activiti.cycle.action.ParameterizedAction;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.ExcludesCycleComponents;
import org.activiti.cycle.annotations.Interceptors;
import org.activiti.cycle.annotations.ListAfterComponents;
import org.activiti.cycle.annotations.ListBeforeComponents;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType;
......@@ -37,6 +43,8 @@ import org.scannotation.WarUrlFinder;
/**
* Factory for cycle components. Components are classes annotated by
* {@link CycleComponent}.
*
* @author daniel.meyer@camunda.com
*/
public abstract class CycleComponentFactory {
......@@ -108,8 +116,9 @@ public abstract class CycleComponentFactory {
private Object getComponentInstance(CycleComponentDescriptor descriptor) {
guaranteeInitialization();
if (descriptor == null)
if (descriptor == null) {
throw new IllegalArgumentException("Descriptor must not be null");
}
// try to restore from context:
Object instance = restoreFormContext(descriptor);
......@@ -173,8 +182,9 @@ public abstract class CycleComponentFactory {
private Object decorateInstance(Object instanceToDecorate, Class< ? > type) {
Interceptors interceptors = type.getAnnotation(Interceptors.class);
if (interceptors == null)
if (interceptors == null) {
return instanceToDecorate;
}
Class< ? extends Interceptor>[] interceptorClasses = interceptors.value();
if (interceptorClasses.length == 0) {
return instanceToDecorate;
......@@ -185,7 +195,6 @@ public abstract class CycleComponentFactory {
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();
......@@ -219,7 +228,6 @@ public abstract class CycleComponentFactory {
componentTypes.add(CreateUrlAction.class);
componentTypes.add(ParameterizedAction.class);
componentTypes.add(DownloadContentAction.class);
componentTypes.add(ContentProvider.class);
componentTypes.add(ContentRepresentation.class);
componentTypes.add(ContentArtifactTypeTransformation.class);
componentTypes.add(ContentMimeTypeTransformation.class);
......@@ -249,12 +257,11 @@ public abstract class CycleComponentFactory {
// look for cycle components
Set<String> componentClassNames = db.getAnnotationIndex().get(CycleComponent.class.getName());
// TODO: check correct classpath handling
if (componentClassNames==null || componentClassNames.size()==0) {
logger.log(Level.WARNING, "Cannot find any Cycle plugins having annotation " + CycleComponent.class.getName());
}
else {
if (componentClassNames == null || componentClassNames.size() == 0) {
logger.log(Level.WARNING, "Cannot find any Cycle plugins having annotation " + CycleComponent.class.getName());
} else {
for (String componentClassName : componentClassNames) {
Class< ? > cycleComponentClass;
try {
......@@ -267,19 +274,26 @@ public abstract class CycleComponentFactory {
}
}
private String registerComponent(Class< ? > cycleComponentClass) {
public static String getComponentName(Class< ? > cycleComponentClass) {
CycleComponent componentAnnotation = cycleComponentClass.getAnnotation(CycleComponent.class);
String name = componentAnnotation.value();
if (name == null)
if (name == null) {
name = componentAnnotation.name();
}
if (name == null || name.length() == 0) {
name = cycleComponentClass.getCanonicalName();
}
return name;
}
private String registerComponent(Class< ? > cycleComponentClass) {
String name = getComponentName(cycleComponentClass);
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.");
}
CycleComponent componentAnnotation = cycleComponentClass.getAnnotation(CycleComponent.class);
// init component descriptor:
CycleComponentDescriptor componentDescriptor = new CycleComponentDescriptor(name, componentAnnotation.context(), cycleComponentClass);
descriptorRegistry.put(name, componentDescriptor);
......@@ -402,4 +416,5 @@ public abstract class CycleComponentFactory {
}
components.removeAll(excludedComponents);
}
}
package org.activiti.cycle.annotations;
import java.awt.Desktop.Action;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.MimeType;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.action.CreateUrlAction;
import org.activiti.cycle.action.DownloadContentAction;
import org.activiti.cycle.action.ParameterizedAction;
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.transform.ContentArtifactTypeTransformation;
import org.activiti.cycle.transform.ContentMimeTypeTransformation;
/**
* An ActivitiCycle component. Components can use services such as
* {@link Interceptors}, {@link CycleConfigParameter}s ...
* Annotation for qualifying cycle components. Cycle components are ordinary
* java classes annotated with {@link CycleComponent}. Cycle components are
* discovered and managed by the {@link CycleComponentFactory}.
* <p>
* <strong>Component Name</strong> <br>
* A component has a name, which is added as a parameter to this annotation, see
* {@link #name()}. If no name is provided, the class name of the component is
* used.
* </p>
* <p>
* <strong>Component Type</strong> <br>
* While cycle components are ordinary java classes some components play a
* special role in cycle. An example of such a component is a
* {@link RepositoryConnector}. If such an interface is implemented, we call the
* implemented interface the <em>type</em> of a cycle component. The following
* is a list of supported component types:
* <ul>
* <li> {@link RepositoryConnector}</li>
* <li> {@link Action} ( {@link CreateUrlAction}, {@link ParameterizedAction},
* {@link DownloadContentAction})</li>
* <li> {@link ContentRepresentation}</li>
* <li> {@link ContentArtifactTypeTransformation}</li>
* <li> {@link ContentMimeTypeTransformation}</li>
* <li> {@link MimeType}</li>
* <li> {@link RepositoryArtifactType}</li>
* </ul>
* </p>
* <p>
* <strong>Component Context</strong> <br>
* Cycle uses a simple contextual component model. Instances of components are
* stored in a {@link CycleContext}. Two different cycle contexts are supported:
* <ul>
* <li> {@link CycleContextType#SESSION} and the corresponding
* {@link CycleSessionContext}: the session context is a usersession-scoped
* context of which one instance per usersession is managed. Components residing
* within this context are instantiated once per user session, i.e. each
* usersession has its own instances of such components.</li>
* <li> {@link CycleContextType#APPLICATION} and the corresponding
* {@link CycleApplicationContext}: the application context is a globally
* visible context, used as a singleton-space.</li>
* </ul>
* The context of a cycle component is specified using the {@link #context()}
* field of this annotation.
* </p>
*
*
* @see CycleComponentFactory
* @see CycleContextType
* @see Interceptors
*
* @author daniel.meyer@camunda.com
*/
......@@ -17,13 +78,19 @@ import org.activiti.cycle.context.CycleContextType;
@Target({ ElementType.TYPE })
public @interface CycleComponent {
/**
* @see #name()
*/
String value() default "";
/**
* The name of a component. If left blank, the classname of the annotated
* class is used.
*/
String name() default "";
/**
* Optional parameter: if a {@link CycleContextType} is set, cycle will store
* instances of the corresponding component in the corresponding context.
* Optional parameter: used to set the context of the annotated component.
*/
CycleContextType context() default CycleContextType.NONE;
......
......@@ -46,6 +46,7 @@ public @interface ExcludesCycleComponents {
/**
* Classes of the components to exclude
*/
@SuppressWarnings("rawtypes")
Class[] classes() default {};
}
......@@ -5,16 +5,34 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.impl.Interceptor;
/**
* Annotate ActivityCycle components with this
* @author meyerd
* Annotation for specifying a list of interceptors for a cycle component.
* Interceptors are classes implementing the {@link Interceptor} interface.
*
* <p>
* <strong>Note:</strong> the {@link CycleComponentFactory} generates proxies
* using the built-in java proxy mechanisms. Cycle component implementors must
* therefore ensure that components annotated using this annotation implement at
* least one interface which can be proxied. This is true for cycle components
* with a special <em>component type</em> (see {@link CycleComponent}). Also
* make sure not to cast instances of such components to the implementation type
* but to the interface. If a component implements multiple interfaces, all of
* the interfaces are proxied.
* </p>
*
* @see CycleComponent
* @see CycleComponentFactory
* @see Interceptor
*
* @author daniel.meyer@camunda.com
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Target({ ElementType.TYPE })
public @interface Interceptors {
Class<? extends Interceptor>[] value();
Class< ? extends Interceptor>[] value();
}
package org.activiti.cycle.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.action.Action;
import org.activiti.cycle.action.DownloadContentAction;
import org.activiti.cycle.action.ParameterizedAction;
/**
* Annotation used to define a sorting on components. Component instances are
* listed in various places, for example in the UI. Putting this annotation on a
* component is a <strong>hint</strong> for the cycle component infrastructure
* to attempt to list instances of this component <em>after</em> instances of
* the components referenced using this annotation. If this annotation is set
* for a cycle component and no parameters are given, cycle will try to list the
* corresponding component instances as first items in the list.
*
* <p>
* Note: the sorting on components using {@link ListBeforeComponents} and
* {@link ListAfterComponents} is only supported above the service layer, ie. on
* component lists returned by a cycle service.
* </p>
*
* <p>
* <strong>Note:</strong> the sorting on components is currently only supported
* for some component types:
* <ul>
* <li>{@link Action} (which subsumes {@link ParameterizedAction},
* {@link DownloadContentAction} etc...)</li>
* <li> {@link ContentRepresentation}</li>
* </ul>
* </p>
*
* @author daniel.meyer@camunda.com
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface ListAfterComponents {
String[] value() default {};
String[] names() default {};
@SuppressWarnings("rawtypes")
Class[] classes() default {};
}
package org.activiti.cycle.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.action.Action;
import org.activiti.cycle.action.DownloadContentAction;
import org.activiti.cycle.action.ParameterizedAction;
/**
* Annotation used to define a sorting on components. Component instances are
* listed in various places, for example in the UI. Putting this annotation on a
* component is a <strong>hint</strong> for the cycle component infrastructure
* to attempt to list instances of this component <em>before</em> instances of
* the components referenced using this annotation. If this annotation is set
* for a cycle component and no parameters are given, cycle will try to list the
* corresponding component instances as first items in the list.
*
* <p>
* <strong>Note:</strong> the sorting on components using
* {@link ListBeforeComponents} and {@link ListAfterComponents} is only
* supported above the service layer, ie. on component lists returned by a cycle
* service.
* </p>
*
* <p>
* <strong>Note:</strong> the sorting on components is currently only supported
* for some component types:
* <ul>
* <li>{@link Action} (which subsumes {@link ParameterizedAction},
* {@link DownloadContentAction} etc...)</li>
* <li> {@link ContentRepresentation}</li>
* </ul>
* </p>
*
* @author daniel.meyer@camunda.com
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface ListBeforeComponents {
String[] value() default {};
String[] names() default {};
@SuppressWarnings("rawtypes")
Class[] classes() default {};
}
......@@ -15,7 +15,6 @@ package org.activiti.cycle.impl;
import java.io.Serializable;
import java.util.logging.Logger;
import org.activiti.cycle.ArtifactType;
/**
* The file action defines an action you can execute upon a file / artifact
......
package org.activiti.cycle.impl;
import java.io.IOException;
import java.io.StringWriter;
import java.util.logging.Logger;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.activiti.cycle.Content;
import org.activiti.cycle.ContentProvider;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.restlet.ext.xml.DomRepresentation;
/**
*
* @author bernd.ruecker
*/
public abstract class ContentProviderImpl implements ContentProvider {
protected Logger log = Logger.getLogger(this.getClass().getName());
public abstract void addValueToContent(Content content, RepositoryConnector connector, RepositoryArtifact artifact);
public Content createContent(RepositoryConnector connector, RepositoryArtifact artifact) {
Content c = new Content();
addValueToContent(c, connector, artifact);
if (c.isNull()) {
throw new RepositoryException("No content created for artifact " + artifact.getGlobalUniqueId() + " ' by provider '" + this.getClass().getName()
+ "' (was null). Please check provider or artifact.");
}
return c;
}
/**
* helper method to transform XML to String if required by any
* {@link ContentProvider}
*/
public String getXmlAsString(DOMSource xmlData) throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException,
IOException {
StringWriter stringWriter = new StringWriter();
StreamResult streamResult = new StreamResult(stringWriter);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.transform(xmlData, streamResult);
return stringWriter.toString();
}
public String getXmlAsString(DomRepresentation xmlData) throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException,
IOException {
return getXmlAsString(xmlData.getDomSource());
}
}
package org.activiti.cycle.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.annotations.ListAfterComponents;
import org.activiti.cycle.annotations.ListBeforeComponents;
/**
* Cycle component comparator used to determine a sorting on cycle components.
*
* @author daniel.meyer@camunda.com
*/
@SuppressWarnings("rawtypes")
public class CycleComponentComparator implements Comparator {
private Class< ? > getComponentClass(Object o) {
// TODO: naive: this does not work for decorated components.
return o.getClass();
}
private List<String> getBeforeComponentNames(Class< ? > o) {
List<String> componentNames = new ArrayList<String>();
ListBeforeComponents listBeforeComponents = o.getAnnotation(ListBeforeComponents.class);
if (listBeforeComponents != null) {
componentNames.addAll(Arrays.asList(listBeforeComponents.value()));
componentNames.addAll(Arrays.asList(listBeforeComponents.names()));
Class[] classes = listBeforeComponents.classes();
for (Class clazz : classes) {
componentNames.add(clazz.getCanonicalName());
}
}
return componentNames;
}
private List<String> getAfterComponentNames(Class< ? > o) {
List<String> componentNames = new ArrayList<String>();
ListBeforeComponents listAfterComponents = o.getAnnotation(ListBeforeComponents.class);
if (listAfterComponents != null) {
componentNames.addAll(Arrays.asList(listAfterComponents.value()));
componentNames.addAll(Arrays.asList(listAfterComponents.names()));
Class[] classes = listAfterComponents.classes();
for (Class clazz : classes) {
componentNames.add(clazz.getCanonicalName());
}
}
return componentNames;
}
private boolean isAfterAll(Class< ? > componentClass) {
ListAfterComponents annotation = componentClass.getAnnotation(ListAfterComponents.class);
if (annotation != null) {
if (annotation.value().length != 0) {
return false;
}
if (annotation.names().length != 0) {
return false;
}
if (annotation.classes().length != 0) {
return false;
}
return true;
}
return false;
}
private boolean isBeforeAll(Class< ? > componentClass) {
ListBeforeComponents annotation = componentClass.getAnnotation(ListBeforeComponents.class);
if (annotation != null) {
if (annotation.value().length != 0) {
return false;
}
if (annotation.names().length != 0) {
return false;
}
if (annotation.classes().length != 0) {
return false;
}
return true;
}
return false;
}
public int compare(Object o1, Object o2) {
if (o1 == o2 || o1.equals(o2)) {
return 0;
}
Class< ? > o1ComponentClass = getComponentClass(o1);
if (isBeforeAll(o1ComponentClass)) {
return -1;
}
if (isAfterAll(o1ComponentClass)) {
return 1;
}
Class< ? > o2ComponentClass = getComponentClass(o2);
if (isBeforeAll(o2ComponentClass)) {
return 1;
}
if (isAfterAll(o2ComponentClass)) {
return -1;
}
String o1ComponentName = CycleComponentFactory.getComponentName(o1ComponentClass);
List<String> o1BeforeComponentNames = getBeforeComponentNames(o1ComponentClass);
List<String> o1AfterComponentNames = getAfterComponentNames(o1ComponentClass);
String o2ComponentName = CycleComponentFactory.getComponentName(o2ComponentClass);
List<String> o2BeforeComponentNames = getBeforeComponentNames(o2ComponentClass);
List<String> o2AfterComponentNames = getAfterComponentNames(o2ComponentClass);
if (o1ComponentName.equals(o2ComponentName)) {
// TODO: what do we do with two instances of the same component?
return -1;
}
if (o1BeforeComponentNames.contains(o2ComponentName) || o2AfterComponentNames.contains(o1ComponentName)) {
return -1;
}
if (o2BeforeComponentNames.contains(o1ComponentName) || o1AfterComponentNames.contains(o2ComponentName)) {
return 1;
}
return o1.toString().compareTo(o2.toString());
}
}
......@@ -25,18 +25,28 @@ public class CycleComponentInvocationHandler implements InvocationHandler {
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// before method invocation
for (Interceptor interceptor : interceptorInstances) {
interceptor.interceptMethodCall(method, instance, args);
interceptor.beforeInvoke(method, instance, args); // throws exception
}
Object invocationResult = null;
try {
return method.invoke(instance, args);
invocationResult = method.invoke(instance, args);
} catch (Exception e) {
// catch the InvocationTargetException and throw the actual exception
// instead.
if (e instanceof InvocationTargetException) {
throw ((InvocationTargetException) e).getTargetException();
}
throw e;
}
// after method invocation
for (Interceptor interceptor : interceptorInstances) {
interceptor.afterInvoke(method, instance, invocationResult, args);
}
return invocationResult;
}
}
......@@ -2,13 +2,50 @@ package org.activiti.cycle.impl;
import java.lang.reflect.Method;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.Interceptors;
/**
* Generic interceptor interface.
* Interceptor for cycle components. Supports a "before" and an "after" -
* interceptor. Declared using the {@link Interceptors} annotation.
*
* @see CycleComponent
* @see CycleComponentFactory
* @see Interceptors
*
* @author daniel.meyer@camunda.com
*/
public interface Interceptor {
void interceptMethodCall(Method m, Object object, Object... args);
/**
* Interceptor-method called before the method-invocation. Implementors can
* also block the method invocation by throwing an exception.
*
* @param m
* the Method to be invoked
* @param object
* the proxied object, the method is invoked on.
* @param args
* array of parameter objects for the method invocation (can be null)
*/
void beforeInvoke(Method m, Object object, Object... args); // TODO: throws
// Exception?
/**
* Interceptor-method called after the method-invocation.
*
* @param m
* the Method to be invoked
* @param object
* the object, the method is invoked on.
* @param invocationResult
* the object returned by the method invocation (can be null).
* @param args
* array of parameter objects for the method invocation (can be
* null).
*/
void afterInvoke(Method m, Object object, Object invocationResult, Object... args); // TODO:
// throws
// Exception?
}
......@@ -54,4 +54,8 @@ public abstract class ParameterizedActionImpl extends AbstractArtifactActionImpl
return value;
}
@Override
public String toString() {
return getId();
}
}
package org.activiti.cycle.impl.connector;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
......@@ -16,77 +15,48 @@ import org.activiti.cycle.service.CycleServiceFactory;
public abstract class AbstractRepositoryConnector<T extends RepositoryConnectorConfiguration> implements RepositoryConnector {
protected Logger log = Logger.getLogger(this.getClass().getName());
protected Logger log = Logger.getLogger(this.getClass().getName());
private T configuration;
private T configuration;
public AbstractRepositoryConnector(T configuration) {
this.configuration = configuration;
}
public AbstractRepositoryConnector(T configuration) {
this.configuration = configuration;
}
public AbstractRepositoryConnector() {
}
public T getConfiguration() {
return configuration;
}
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
// * artifact.
// */
// public Content getContent(String artifactId, String representationName) throws RepositoryNodeNotFoundException {
// RepositoryArtifact artifact = getRepositoryArtifact(artifactId);
// return artifact.getArtifactType().getContentProvider(representationName).createContent(this, artifact);
// }
/**
* As a default a connector doesn't provide any preview picture
*/
public Content getRepositoryArtifactPreview(String artifactId) throws RepositoryNodeNotFoundException {
return null;
}
/**
* As a default a connector doesn't provide any preview picture
*/
public Content getRepositoryArtifactPreview(String artifactId) throws RepositoryNodeNotFoundException {
return null;
}
/**
* Typical basic implementation for execute a {@link ParameterizedAction} by
* loading the {@link RepositoryArtifact}, query the action via the
* {@link ArtifactType} and execute it by handing over "this" as parameter
* for the connector
*/
public void executeParameterizedAction(String artifactId, String actionId, Map<String, Object> parameters) throws Exception {
RepositoryArtifact artifact = getRepositoryArtifact(artifactId);
CyclePluginService pluginService = CycleServiceFactory.getCyclePluginService();
Set<ParameterizedAction> actions = pluginService.getParameterizedActions(artifact);
for (ParameterizedAction parameterizedAction : actions) {
if(!parameterizedAction.getId().equals(actionId)) {
/**
* Typical basic implementation for execute a {@link ParameterizedAction} by
* loading the {@link RepositoryArtifact}, query the action via the
* {@link ArtifactType} and execute it by handing over "this" as parameter for
* the connector
*/
public void executeParameterizedAction(String artifactId, String actionId, Map<String, Object> parameters) throws Exception {
RepositoryArtifact artifact = getRepositoryArtifact(artifactId);
CyclePluginService pluginService = CycleServiceFactory.getCyclePluginService();
List<ParameterizedAction> actions = pluginService.getParameterizedActions(artifact);
for (ParameterizedAction parameterizedAction : actions) {
if (!parameterizedAction.getId().equals(actionId)) {
continue;
}
parameterizedAction.execute(this, artifact, parameters);
}
}
// /**
// * Basic implementation returning all registered {@link ArtifactType}s from
// * the {@link RepositoryConnectorConfiguration}
// */
// public List<ArtifactType> getSupportedArtifactTypes(String folderId) {
// return getConfiguration().getArtifactTypes();
// }
// public ArtifactType getArtifactType(String id) {
// for (ArtifactType type : getConfiguration().getArtifactTypes()) {
// if (type.getId().equals(id)) {
// return type;
// }
// }
// throw new RepositoryException("ArtifactType with id '" + id + "' doesn't exist. Possible types are: "
// + getConfiguration().getArtifactTypes());
// }
}
}
......@@ -13,23 +13,31 @@ import org.activiti.cycle.impl.Interceptor;
*/
public class ConnectorLoginInterceptor implements Interceptor {
public void interceptMethodCall(Method m, Object object, Object... args) {
public void beforeInvoke(Method m, Object object, Object... args) {
RepositoryConnector connector = (RepositoryConnector) object;
if ("setConfiguration".equals(m.getName())) {
// let the invocation of the "setConfiguration"-method pass
return;
}
if ("getConfiguration".equals(m.getName())) {
// let the invocation of the "getConfiguration"-method pass
return;
}
if ("login".equals(m.getName())) {
// TODO: Why always return true? When is it really logged in?
// let the invocation of the "login"-method pass
return;
}
// for all other methods, check whether the connector is logged in.
if (!connector.isLoggedIn()) {
// the connector is not logged in, block invocation
throw new RepositoryAuthenticationException("Connector '" + connector.getConfiguration().getName() + "' is not logged in ", connector.getConfiguration()
.getId());
}
}
public void afterInvoke(Method m, Object object, Object invocationResult, Object... args) {
// do nothing
}
}
......@@ -15,7 +15,6 @@ package org.activiti.cycle.impl.connector.fs;
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;
......
package org.activiti.cycle.impl.connector.fs.provider;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.ContentProviderImpl;
import org.activiti.cycle.impl.connector.fs.FileSystemConnector;
import org.activiti.cycle.impl.util.IoUtils;
public class FileBinaryContentProvider extends ContentProviderImpl {
@Override
public void addValueToContent(Content content, RepositoryConnector connector, RepositoryArtifact artifact) {
String fileName = ((FileSystemConnector) connector).getConfiguration().getBasePath() + artifact.getNodeId();
File file = new File(fileName);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
content.setValue(IoUtils.readBytes(fis));
} catch (FileNotFoundException fnfe) {
throw new RepositoryException("Unable to find artifact " + artifact, fnfe);
} catch (IOException ioe) {
throw new RepositoryException("Error while accessing artifact " + artifact, ioe);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
// log but ignore exception on closing
log.log(Level.WARNING, "Couldn't close file '" + fileName + "'. Ignoring.", ex);
}
}
}
}
}
package org.activiti.cycle.impl.connector.fs.provider;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.ContentProviderImpl;
import org.activiti.cycle.impl.connector.fs.FileSystemConnector;
public class TextFileContentProvider extends ContentProviderImpl {
@Override
public void addValueToContent(Content content, RepositoryConnector connector, RepositoryArtifact artifact) {
String fileName = ((FileSystemConnector) connector).getConfiguration().getBasePath() + artifact.getNodeId();
File file = new File(fileName);
try{
content.setValue(new FileInputStream(file));
} catch (FileNotFoundException fnfe) {
throw new RepositoryException("Unable to find artifact " + artifact, fnfe);
}
}
}
package org.activiti.cycle.impl.connector.fs.provider;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.dom.DOMSource;
import org.activiti.cycle.Content;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.impl.ContentProviderImpl;
import org.activiti.cycle.impl.connector.fs.FileSystemConnector;
import org.w3c.dom.Document;
public class XmlFileContentProvider extends ContentProviderImpl {
@Override
public void addValueToContent(Content content, RepositoryConnector connector, RepositoryArtifact artifact) {
String fileName = ((FileSystemConnector) connector).getConfiguration().getBasePath() + artifact.getNodeId();
File file = new File(fileName);
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
content.setValue(getXmlAsString(new DOMSource(doc)));
} catch (Exception e) {
throw new RepositoryException("Error while retrieving artifact " + artifact + " as xml content", e);
}
}
}
......@@ -15,7 +15,6 @@ package org.activiti.cycle.impl.connector.signavio;
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;
......
......@@ -19,16 +19,12 @@ import org.activiti.cycle.Content;
import org.activiti.cycle.MimeType;
import org.activiti.cycle.RenderInfo;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.components.RuntimeConnectorList;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioBpmn20ArtifactType;
import org.activiti.cycle.impl.mimetype.PngMimeType;
public abstract class AbstractPngProvider extends SignavioContentRepresentationProvider {
......
......@@ -2,6 +2,7 @@ package org.activiti.cycle.impl.connector.signavio.provider;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.ListBeforeComponents;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioBpmn20ArtifactType;
......@@ -12,6 +13,7 @@ import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.Signavi
* @author meyerd
*/
@CycleComponent(context = CycleContextType.APPLICATION)
@ListBeforeComponents
public class BpmnProcessPngProvider extends AbstractPngProvider {
public RepositoryArtifactType getRepositoryArtifactType() {
......
......@@ -2,6 +2,7 @@ package org.activiti.cycle.impl.connector.signavio.provider;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.ListBeforeComponents;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioDefaultArtifactType;
......@@ -12,6 +13,7 @@ import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.Signavi
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
@ListBeforeComponents
public class DefaultPngProvider extends AbstractPngProvider {
public RepositoryArtifactType getRepositoryArtifactType() {
......
......@@ -4,7 +4,6 @@ import java.util.ArrayList;
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.CycleTagContent;
......@@ -44,9 +43,6 @@ public class TagConnector implements RepositoryConnector {
public void commitPendingChanges(String comment) {
}
public List<ArtifactType> getSupportedArtifactTypes(String folderId) {
return new ArrayList<ArtifactType>();
}
public boolean login(String username, String password) {
return true;
......
......@@ -2,7 +2,6 @@ package org.activiti.cycle.impl.service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
......@@ -13,8 +12,8 @@ import org.activiti.cycle.MimeType;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.impl.CycleComponentComparator;
import org.activiti.cycle.impl.artifacttype.RepositoryArtifactTypes;
import org.activiti.cycle.impl.connector.signavio.provider.AbstractPngProvider;
import org.activiti.cycle.impl.mimetype.Mimetypes;
import org.activiti.cycle.impl.representation.ContentRepresentations;
import org.activiti.cycle.impl.transform.Transformations;
......@@ -26,6 +25,7 @@ import org.activiti.cycle.transform.ContentTransformationException;
*
* @author daniel.meyer@camunda.com
*/
@SuppressWarnings("unchecked")
public class CycleContentServiceImpl implements CycleContentService {
public Set<MimeType> getAvailableMimeTypes() {
......@@ -62,28 +62,10 @@ public class CycleContentServiceImpl implements CycleContentService {
}
private void sortContentReprsentations(List<ContentRepresentation> sortedList) {
// TODO: sort contentRepresentations according to name AND annotations
// TODO: move to better suited place
// for the moment: sort alphabetically and make sure that "PNG" is the first
// tab:
Collections.sort(sortedList, new Comparator<ContentRepresentation>() {
public int compare(ContentRepresentation o1, ContentRepresentation o2) {
if (o1.equals(o2)) {
return 0;
}
if (AbstractPngProvider.class.isAssignableFrom(o1.getClass())) {
return -1;
}
if (AbstractPngProvider.class.isAssignableFrom(o2.getClass())) {
return 1;
}
return o1.getId().compareTo(o2.getId());
}
});
Collections.sort(sortedList, new CycleComponentComparator());
}
private void removeExcludedContentRepresentations(Set represenations) {
private void removeExcludedContentRepresentations(Set<?> represenations) {
CycleComponentFactory.removeExcludedComponents(represenations);
}
......
package org.activiti.cycle.impl.service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.action.Action;
import org.activiti.cycle.action.ArtifactAwareParameterizedAction;
import org.activiti.cycle.action.CreateUrlAction;
import org.activiti.cycle.action.DownloadContentAction;
import org.activiti.cycle.action.ParameterizedAction;
import org.activiti.cycle.action.RepositoryArtifactOpenLinkAction;
import org.activiti.cycle.annotations.ExcludesCycleComponents;
import org.activiti.cycle.components.RuntimeConnectorList;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.CycleComponentComparator;
import org.activiti.cycle.impl.action.Actions;
import org.activiti.cycle.service.CyclePluginService;
import com.sun.xml.xsom.impl.scd.Axis;
/**
* Default Implementation of the {@link CyclePluginService}
*
......@@ -42,26 +43,23 @@ public class CyclePluginServiceImpl implements CyclePluginService {
return CycleApplicationContext.get(Actions.class).getDownloadContentActions(type);
}
public Set<ParameterizedAction> getParameterizedActions(RepositoryArtifact artifact) {
public List<ParameterizedAction> getParameterizedActions(RepositoryArtifact artifact) {
Set<ParameterizedAction> actions = getParameterizedActions(artifact.getArtifactType());
removeNonApplicableActions(actions, artifact);
removeExcludedActions(actions);
sortActions(actions, artifact);
return actions;
return sortActions(actions, artifact);
}
public Set<CreateUrlAction> getCreateUrlActions(RepositoryArtifact artifact) {
public List<CreateUrlAction> getCreateUrlActions(RepositoryArtifact artifact) {
Set<CreateUrlAction> actions = getCreateUrlActions(artifact.getArtifactType());
removeExcludedActions(actions);
sortActions(actions, artifact);
return actions;
return sortActions(actions, artifact);
}
public Set<DownloadContentAction> getDownloadContentActions(RepositoryArtifact artifact) {
public List<DownloadContentAction> getDownloadContentActions(RepositoryArtifact artifact) {
Set<DownloadContentAction> actions = getDownloadContentActions(artifact.getArtifactType());
removeExcludedActions(actions);
sortActions(actions, artifact);
return actions;
return sortActions(actions, artifact);
}
private void removeNonApplicableActions(Set<ParameterizedAction> actions, RepositoryArtifact forArtifact) {
......@@ -77,8 +75,11 @@ public class CyclePluginServiceImpl implements CyclePluginService {
actions.removeAll(nonApplicableActions);
}
private void sortActions(Set actions, RepositoryArtifact artifact) {
// TODO
@SuppressWarnings("unchecked")
private <T> List<T> sortActions(Collection<T> actions, RepositoryArtifact artifact) {
ArrayList<T> sortedList = new ArrayList<T>(actions);
Collections.sort(sortedList, new CycleComponentComparator());
return sortedList;
}
private void removeExcludedActions(Set actions) {
......
......@@ -3,14 +3,10 @@ package org.activiti.cycle.impl.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.Content;
import org.activiti.cycle.MimeType;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.RepositoryFolder;
......@@ -18,19 +14,14 @@ 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.CycleApplicationContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.artifacttype.RepositoryArtifactTypes;
import org.activiti.cycle.impl.conf.PasswordEnabledRepositoryConnectorConfiguration;
import org.activiti.cycle.impl.connector.util.TransactionalConnectorUtils;
import org.activiti.cycle.impl.db.CycleLinkDao;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.mimetype.Mimetypes;
import org.activiti.cycle.impl.transform.Transformations;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.transform.ContentTransformationException;
/**
* @author bernd.ruecker@camunda.com
......
package org.activiti.cycle.service;
import java.util.List;
import java.util.Set;
import org.activiti.cycle.ContentProvider;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.action.Action;
......@@ -25,12 +25,12 @@ public interface CyclePluginService {
public Set<DownloadContentAction> getDownloadContentActions(RepositoryArtifactType type);
public Set<ParameterizedAction> getParameterizedActions(RepositoryArtifact artifact);
public List<ParameterizedAction> getParameterizedActions(RepositoryArtifact artifact);
public Set<CreateUrlAction> getCreateUrlActions(RepositoryArtifact artifact);
public List<CreateUrlAction> getCreateUrlActions(RepositoryArtifact artifact);
public Set<DownloadContentAction> getDownloadContentActions(RepositoryArtifact artifact);
public List<DownloadContentAction> getDownloadContentActions(RepositoryArtifact artifact);
public Set<RepositoryArtifactOpenLinkAction> getArtifactOpenLinkActions(RepositoryArtifact artifact);
public Set<RepositoryArtifactOpenLinkAction> getArtifactOpenLinkActions(RepositoryArtifact artifact);
}
......@@ -14,22 +14,14 @@ package org.activiti.cycle.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.activiti.cycle.ArtifactType;
import org.activiti.cycle.Content;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.MimeType;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.impl.artifacttype.RepositoryArtifactTypes;
import org.activiti.cycle.impl.mimetype.Mimetypes;
import org.activiti.cycle.transform.ContentTransformationException;
/**
* Cycle service used for accessing repositories.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册