diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java new file mode 100644 index 0000000000000000000000000000000000000000..a362f62564f0cb204aa87134b990853da7c515b0 --- /dev/null +++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubEnvironment.java @@ -0,0 +1,34 @@ +package info.kwarc.sally4.mathhubworker.impl; + +import info.kwarc.sally4.docmanager.AlexRoute; + +import java.util.HashMap; + +public class MathHubEnvironment { + + HashMap<String, AlexRoute> workers; + Runnable onEmpty; + + public MathHubEnvironment() { + workers = new HashMap<String, AlexRoute>(); + } + + public void setOnEmpty(Runnable onEmpty) { + this.onEmpty = onEmpty; + } + + public void addWorker(final AlexRoute worker) { + workers.put(worker.getID(), worker); + worker.addOnStopHandler(new Runnable() { + + @Override + public void run() { + workers.remove(worker.getID()); + if (workers.size() == 0 && onEmpty != null) { + onEmpty.run(); + } + } + }); + } + +} diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubWorkerManagerImpl.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubWorkerManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fda12b09496568d04af836eca39d2142076c1ff3 --- /dev/null +++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/impl/MathHubWorkerManagerImpl.java @@ -0,0 +1,82 @@ +package info.kwarc.sally4.mathhubworker.impl; + +import info.kwarc.sally4.core.CamelContextProvider; +import info.kwarc.sally4.docmanager.AlexRoute; +import info.kwarc.sally4.mathhubworker.MathHubWorkerManager; +import info.kwarc.sally4.mathhubworker.routes.MHWManagementRoute; + +import java.util.HashMap; + +import org.apache.camel.CamelContext; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.felix.ipojo.annotations.Component; +import org.apache.felix.ipojo.annotations.Instantiate; +import org.apache.felix.ipojo.annotations.Invalidate; +import org.apache.felix.ipojo.annotations.Provides; +import org.apache.felix.ipojo.annotations.Requires; +import org.apache.felix.ipojo.annotations.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component +@Instantiate +@Provides +public class MathHubWorkerManagerImpl implements MathHubWorkerManager { + Logger log; + + @Requires + CamelContextProvider camelContextProvider; + + HashMap<String, MathHubEnvironment> environments; + + public MathHubWorkerManagerImpl() { + log = LoggerFactory.getLogger(getClass()); + environments = new HashMap<String, MathHubEnvironment>(); + } + + + public void getSettings() { + + } + + @Override + public void addNewWorker(final AlexRoute route) { + if (!environments.containsKey(route.getEnvironmentID())) { + MathHubEnvironment env = new MathHubEnvironment(); + env.setOnEmpty(new Runnable() { + @Override + public void run() { + environments.remove(route.getEnvironmentID()); + } + }); + environments.put(route.getEnvironmentID(), env); + } + + environments.get(route.getEnvironmentID()).addWorker(route); + } + + CamelContext resourceContext; + + @Validate + public void start() { + resourceContext = new DefaultCamelContext(); + resourceContext.addComponent("sallyservlet", camelContextProvider.getComponent("sallyservlet")); + try { + resourceContext.addRoutes(new MHWManagementRoute(this)); + resourceContext.start(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Invalidate + public void stop() { + try { + resourceContext.stop(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/internal/comm/GetLMHWorkers.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/internal/comm/GetLMHWorkers.java new file mode 100644 index 0000000000000000000000000000000000000000..bfeac6839e1a5f5d94ed5c1b20c46440f78b0ba6 --- /dev/null +++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/internal/comm/GetLMHWorkers.java @@ -0,0 +1,5 @@ +package info.kwarc.sally4.mathhubworker.internal.comm; + +public class GetLMHWorkers { + +} diff --git a/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/MHWManagementRoute.java b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/MHWManagementRoute.java new file mode 100644 index 0000000000000000000000000000000000000000..363fe340c5f77b274d4d5c08dea04a189fd93f78 --- /dev/null +++ b/MathHubWorker/src/main/java/info/kwarc/sally4/mathhubworker/routes/MHWManagementRoute.java @@ -0,0 +1,27 @@ +package info.kwarc.sally4.mathhubworker.routes; + +import info.kwarc.sally4.mathhubworker.impl.MathHubWorkerManagerImpl; +import info.kwarc.sally4.processors.FileServeProcessor; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.freemarker.FreemarkerComponent; + +public class MHWManagementRoute extends RouteBuilder { + MathHubWorkerManagerImpl thisManager; + + public MHWManagementRoute(MathHubWorkerManagerImpl thisManager) { + this.thisManager = thisManager; + } + + @Override + public void configure() throws Exception { + getContext().addComponent("freemarker", new FreemarkerComponent()); + from("sallyservlet:///planetary/libs?matchOnUriPrefix=true") + .process(new FileServeProcessor("libs", getClass().getClassLoader() )); + + from("sallyservlet:///planetary/mhwsettings") + .bean(thisManager,"getSettings") + .to("freemarker:templates/mhwsettings.html"); + } + +} diff --git a/MathHubWorker/src/main/resources/libs/mhwsettings.png b/MathHubWorker/src/main/resources/libs/mhwsettings.png new file mode 100644 index 0000000000000000000000000000000000000000..310f39a0af2dbeb5a91ce4617eca569a06d290dd Binary files /dev/null and b/MathHubWorker/src/main/resources/libs/mhwsettings.png differ diff --git a/MathHubWorker/src/main/resources/templates/mhwsettings.html b/MathHubWorker/src/main/resources/templates/mhwsettings.html new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/core/src/main/java/info/kwarc/sally4/core/SallyInteraction.java b/core/src/main/java/info/kwarc/sally4/core/SallyInteraction.java new file mode 100644 index 0000000000000000000000000000000000000000..9a05d26dbffc17c99bcd7629cf268026ba395a0c --- /dev/null +++ b/core/src/main/java/info/kwarc/sally4/core/SallyInteraction.java @@ -0,0 +1,21 @@ +package info.kwarc.sally4.core; + +import java.util.List; + +import org.apache.camel.Exchange; + +public interface SallyInteraction { + + public abstract <T> T getOneInteraction(Object obj, Class<T> expectType, + Exchange context); + + public abstract <T> T getOneInteraction(String channel, Object obj, + Class<T> expectType, Exchange context); + + public abstract <T> List<T> getPossibleInteractions(String channel, + Object obj, Class<T> expectType, Exchange context); + + public abstract <T> List<T> getPossibleInteractions(Object obj, + Class<T> expectType, Exchange context); + +} \ No newline at end of file diff --git a/core/src/main/java/info/kwarc/sally4/core/SallyInteractionResultAcceptor.java b/core/src/main/java/info/kwarc/sally4/core/SallyInteractionResultAcceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..5f3cbf019c22c0f6a88659e90c57c6aa4fb6f6e7 --- /dev/null +++ b/core/src/main/java/info/kwarc/sally4/core/SallyInteractionResultAcceptor.java @@ -0,0 +1,5 @@ +package info.kwarc.sally4.core; + +public interface SallyInteractionResultAcceptor { + public void acceptResult(Object obj); +} \ No newline at end of file diff --git a/core/src/main/java/info/kwarc/sally4/core/SallyService.java b/core/src/main/java/info/kwarc/sally4/core/SallyService.java new file mode 100644 index 0000000000000000000000000000000000000000..11d7bb5945aa6606168df822b008883a1c5ecbaf --- /dev/null +++ b/core/src/main/java/info/kwarc/sally4/core/SallyService.java @@ -0,0 +1,10 @@ +package info.kwarc.sally4.core; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface SallyService { + boolean overwrite() default false; + String channel() default "/what"; +} diff --git a/core/src/main/java/info/kwarc/sally4/core/SallyServiceProvider.java b/core/src/main/java/info/kwarc/sally4/core/SallyServiceProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..3b680f5374bef4cd81a1b674e86468a240454943 --- /dev/null +++ b/core/src/main/java/info/kwarc/sally4/core/SallyServiceProvider.java @@ -0,0 +1,5 @@ +package info.kwarc.sally4.core; + + +public interface SallyServiceProvider { +} diff --git a/core/src/main/java/info/kwarc/sally4/core/impl/SallyInteractionImpl.java b/core/src/main/java/info/kwarc/sally4/core/impl/SallyInteractionImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..f0e7bf3cf2b674e35977b79fb2dbb3ea0818efd5 --- /dev/null +++ b/core/src/main/java/info/kwarc/sally4/core/impl/SallyInteractionImpl.java @@ -0,0 +1,283 @@ +package info.kwarc.sally4.core.impl; + +import info.kwarc.sally4.core.SallyInteraction; +import info.kwarc.sally4.core.SallyInteractionResultAcceptor; +import info.kwarc.sally4.core.SallyService; +import info.kwarc.sally4.core.SallyServiceProvider; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Stack; + +import org.apache.camel.Exchange; +import org.apache.felix.ipojo.annotations.Bind; +import org.apache.felix.ipojo.annotations.Component; +import org.apache.felix.ipojo.annotations.Instantiate; +import org.apache.felix.ipojo.annotations.Invalidate; +import org.apache.felix.ipojo.annotations.Provides; +import org.apache.felix.ipojo.annotations.Unbind; +import org.apache.felix.ipojo.annotations.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component +@Instantiate +@Provides +public class SallyInteractionImpl implements SallyInteraction { + static class ChannelClass { + String channel; + Class<?> cls; + + public ChannelClass(String channel, Class<?> cls) { + this.channel = channel; + this.cls = cls; + } + + public String getChannel() { + return channel; + } + + public Class<?> getCls() { + return cls; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ChannelClass)) { + return false; + } + ChannelClass t = (ChannelClass) obj; + return channel.equals(t.getChannel()) && cls.equals(t.getCls()); + } + + @Override + public int hashCode() { + return cls.hashCode()*5+channel.hashCode()*13; + } + } + + HashMap<ChannelClass, List<MethodExec>> map; + Logger log; + + class MethodExec { + Object obj; + Method m; + + MethodExec(Object obj, Method m) { + this.obj = obj; + this.m = m; + this.m.setAccessible(true); + } + + public void setMethod(Method m) { + this.m = m; + } + + public void setObject(Object obj) { + this.obj = obj; + } + + public Method getMethod() { + return m; + } + + public Object getObject() { + return obj; + } + + public void exec(Object obj2, SallyInteractionResultAcceptor acceptor, Exchange context) { + try { + m.invoke(obj, obj2, acceptor, context); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public SallyInteractionImpl() { + map = new HashMap<SallyInteractionImpl.ChannelClass, List<MethodExec>>(); + log = LoggerFactory.getLogger(this.getClass()); + } + + private void addToMap(SallyService annotation, Class<?> param, Object obj, Method m) { + ChannelClass key = new ChannelClass(annotation.channel(), param); + if (!map.containsKey(key)) + map.put(key, new ArrayList<MethodExec>()); + map.get(key).add(new MethodExec(obj, m)); + } + + private void removeFromMap(SallyService annotation, Class<?> param, Object obj, Method m) { + ChannelClass key = new ChannelClass(annotation.channel(), param); + if (!map.containsKey(key)) + return; + Iterator<MethodExec> iter = map.get(key).iterator(); + while (iter.hasNext()) { + MethodExec exec = iter.next(); + if (exec.getObject() == obj && exec.getMethod() == m) { + iter.remove(); + } + } + } + + private List<MethodExec> getServices(String channel, Class<?> cls) { + ChannelClass key = new ChannelClass(channel, cls); + if (map.containsKey(key)) + return map.get(key); + else + return new LinkedList<SallyInteractionImpl.MethodExec>(); + } + + + @Bind(aggregate=true,optional=true) + public void registerServices(SallyServiceProvider obj) { + log.info("registering SallyServices in "+obj.getClass().getName()); + for (Method m : obj.getClass().getMethods()) { + SallyService serviceAnnotation = m.getAnnotation(SallyService.class); + if (serviceAnnotation == null) + continue; + Class<?>[] parameters = m.getParameterTypes(); + if (parameters.length != 3) { + log.error(String.format("Method %s.%s is not a valid SallyService. Param count != 3", obj.getClass().getName(),m.getName())); + continue; + } + if (!SallyInteractionResultAcceptor.class.isAssignableFrom(parameters[1])) { + log.error(String.format("Method %s.%s is not a valid SallyService. 2nd argument should be assignable to SallyActionAcceptor", obj.getClass().getName(),m.getName())); + continue; + } + if (!Exchange.class.isAssignableFrom(parameters[2])) { + log.error(String.format("Method %s.%s is not a valid SallyService. 3rd argument should be assignable to SallyContext", obj.getClass().getName(),m.getName())); + continue; + } + addToMap(serviceAnnotation, parameters[0], obj, m); + } + } + + @Unbind(aggregate=true,optional=true) + public void unregisterServices(SallyServiceProvider obj) { + log.info("unregistering SallyServices in "+obj.getClass().getName()); + for (Method m : obj.getClass().getMethods()) { + SallyService serviceAnnotation = m.getAnnotation(SallyService.class); + if (serviceAnnotation == null) + continue; + Class<?>[] parameters = m.getParameterTypes(); + if (parameters.length != 3) { + continue; + } + if (!SallyInteractionResultAcceptor.class.isAssignableFrom(parameters[1])) { + continue; + } + if (!Exchange.class.isAssignableFrom(parameters[2])) { + continue; + } + removeFromMap(serviceAnnotation, parameters[0], obj, m); + } + } + + /* (non-Javadoc) + * @see info.kwarc.sally4.pull.SallyInteraction#getOneInteraction(java.lang.Object, java.lang.Class, org.apache.camel.Exchange) + */ + @Override + public <T> T getOneInteraction(Object obj, final Class<T> expectType, Exchange context) { + List<T> response = getPossibleInteractions("/what", obj, expectType, 1, context); + if (response.size()==0) + return null; + return response.get(0); + } + + /* (non-Javadoc) + * @see info.kwarc.sally4.pull.SallyInteraction#getOneInteraction(java.lang.String, java.lang.Object, java.lang.Class, org.apache.camel.Exchange) + */ + @Override + public <T> T getOneInteraction(String channel, Object obj, final Class<T> expectType, Exchange context) { + List<T> response = getPossibleInteractions(channel, obj, expectType, 1, context); + if (response.size()==0) + return null; + return response.get(0); + } + + /* (non-Javadoc) + * @see info.kwarc.sally4.pull.SallyInteraction#getPossibleInteractions(java.lang.String, java.lang.Object, java.lang.Class, org.apache.camel.Exchange) + */ + @Override + public <T> List<T> getPossibleInteractions(String channel, Object obj, final Class<T> expectType, Exchange context) { + return getPossibleInteractions(channel, obj, expectType, 1000000, context); + } + + /* (non-Javadoc) + * @see info.kwarc.sally4.pull.SallyInteraction#getPossibleInteractions(java.lang.Object, java.lang.Class, org.apache.camel.Exchange) + */ + @Override + public <T> List<T> getPossibleInteractions(Object obj, final Class<T> expectType, Exchange context) { + return getPossibleInteractions("/what", obj, expectType, 1000000, context); + } + + private <T> List<T> getPossibleInteractions(String channel, Object obj, final Class<T> expectType, final int limit, Exchange context) { + final ArrayList<T> choices = new ArrayList<T>(); + if (obj == null) + return choices; + HashSet<Object> memoizer = new HashSet<Object>(); + Stack<Object> stack = new Stack<Object>(); + stack.add(obj);memoizer.add(obj); + + SallyInteractionResultAcceptor acceptor = new SallyInteractionResultAcceptor() { + @SuppressWarnings("unchecked") + public void acceptResult(Object obj) { + if (choices.size() >= limit) + return; + if (obj == null) + return; + if (expectType.isAssignableFrom(obj.getClass())) { + choices.add((T) obj); + } else { + + } + } + }; + + while (!stack.empty()) { + Object top = stack.pop(); + if (choices.size() >= limit) + break; + for (MethodExec choice : getServices(channel, top.getClass())) { + if (choices.size() >= limit) + break; + choice.exec(top, acceptor, context); + } + } + return choices; + } + + @Validate + public void start() { + log.info("SallyInteraction started"); + } + + @Invalidate + public void stop() { + log.info("SallyInteraction stopped"); + } + + @Override + public String toString() { + StringBuilder b = new StringBuilder(); + for (ChannelClass ch : map.keySet()) { + for (MethodExec exec : map.get(ch)) { + b.append(ch.getChannel()+" "+ch.getCls().toString()+" "+exec.getObject().toString()+" "+exec.getMethod().getName()+"\n"); + } + } + return b.toString(); + } +} diff --git a/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/DocumentManagementRoute.java b/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/DocumentManagementRoute.java new file mode 100644 index 0000000000000000000000000000000000000000..fd00dff93795d59e12b175ca558873f8955ec104 --- /dev/null +++ b/docmanager/src/main/java/info/kwarc/sally4/docmanager/routes/DocumentManagementRoute.java @@ -0,0 +1,24 @@ +package info.kwarc.sally4.docmanager.routes; + +import info.kwarc.sally4.components.TemplatingComponent; +import info.kwarc.sally4.docmanager.impl.DocumentManagerImpl; + +import org.apache.camel.builder.RouteBuilder; + +public class DocumentManagementRoute extends RouteBuilder { + DocumentManagerImpl manager; + + public DocumentManagementRoute(DocumentManagerImpl manager) { + this.manager = manager; + } + + @Override + public void configure() throws Exception { + getContext().addComponent("freemarker", new TemplatingComponent("templates/", getClass().getClassLoader())); + + from("sallyservlet:///docmanager") + .bean(method(manager, "prepareDocManagement")) + .to("freemarker:test.html"); + } + +} diff --git a/planetary/src/main/java/info/kwarc/sally/comm/planetaryclient/NewService.java b/planetary/src/main/java/info/kwarc/sally/comm/planetaryclient/NewService.java new file mode 100644 index 0000000000000000000000000000000000000000..f6a00423380a0ad106a082bc7841049183244139 --- /dev/null +++ b/planetary/src/main/java/info/kwarc/sally/comm/planetaryclient/NewService.java @@ -0,0 +1,183 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 +// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2014.04.17 at 11:52:15 AM CEST +// + + +package info.kwarc.sally.comm.planetaryclient; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for anonymous complex type. + * + * <p>The following schema fragment specifies the expected content contained within this class. + * + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="id" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="type" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="icon" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="url" type="{http://www.w3.org/2001/XMLSchema}string"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "id", + "type", + "name", + "icon", + "url" +}) +@XmlRootElement(name = "NewService") +public class NewService { + + @XmlElement(required = true) + protected String id; + @XmlElement(required = true) + protected String type; + @XmlElement(required = true) + protected String name; + @XmlElement(required = true) + protected String icon; + @XmlElement(required = true) + protected String url; + + /** + * Gets the value of the id property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setId(String value) { + this.id = value; + } + + /** + * Gets the value of the type property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the icon property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getIcon() { + return icon; + } + + /** + * Sets the value of the icon property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setIcon(String value) { + this.icon = value; + } + + /** + * Gets the value of the url property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getUrl() { + return url; + } + + /** + * Sets the value of the url property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setUrl(String value) { + this.url = value; + } + +}