You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2013/10/18 14:50:11 UTC

svn commit: r1533428 - in /ace/site/trunk: content/dev-doc/adding-custom-artifact-types.mdtext content/user-doc/getting-started.mdtext content/user-doc/user-guide.mdtext templates/sidenav.html templates/skeleton.html

Author: marrs
Date: Fri Oct 18 12:50:11 2013
New Revision: 1533428

URL: http://svn.apache.org/r1533428
Log:
Added the user guide to the navigation. Added a page about adding new artifact types to ACE.

Added:
    ace/site/trunk/content/dev-doc/adding-custom-artifact-types.mdtext
Modified:
    ace/site/trunk/content/user-doc/getting-started.mdtext
    ace/site/trunk/content/user-doc/user-guide.mdtext
    ace/site/trunk/templates/sidenav.html
    ace/site/trunk/templates/skeleton.html

Added: ace/site/trunk/content/dev-doc/adding-custom-artifact-types.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/dev-doc/adding-custom-artifact-types.mdtext?rev=1533428&view=auto
==============================================================================
--- ace/site/trunk/content/dev-doc/adding-custom-artifact-types.mdtext (added)
+++ ace/site/trunk/content/dev-doc/adding-custom-artifact-types.mdtext Fri Oct 18 12:50:11 2013
@@ -0,0 +1,204 @@
+Title: Adding custom artifact types
+
+Out of the box, ACE comes with support for bundles and configuration files that follow the Auto Configuration specification. However, it is possible to extend ACE with support for new types of artifacts. Doing so requires you to do three things:
+
+1. Write a resource processor, according to the Deployment Admin specification.
+2. Write an ArtifactRecognizer service implementation.
+3. Write an ArtifactHelper service implementation.
+
+This document explains how to write each of these, and how to subsequently deploy them appropriately.
+
+# Writing a resource processor
+
+A resource processor implements the ResourceProcessor interface as defined in the Deployment Admin specification (OSGi Compendium 114.10). It describes in detail the contract that needs to be implemented and also contains an example. If you want to get started quickly, you can use the following code:
+
+	:::java
+	public class Processor implements ResourceProcessor {
+	    private volatile DeploymentSession m_session;
+	    private String m_deploymentPackageName;
+	    private List<String> m_toInstall;
+	    private List<String> m_toRemove;
+
+	    /**
+	     * Sets up the necessary environment for a deployment session.
+	     */
+	    private void startSession(DeploymentSession session) {
+	        if (m_session != null) {
+	            throw new IllegalArgumentException("This resource processor is currently processing another deployment session, installing deploymentpackage" + m_session.getTargetDeploymentPackage().getName());
+	        }
+	        m_session = session;
+	        m_toInstall = new ArrayList<String>();
+	        m_toRemove = new ArrayList<String>();
+	        String fromSource = session.getSourceDeploymentPackage().getName();
+	        String fromTarget = session.getTargetDeploymentPackage().getName();
+	        if (fromSource.equals("")) {
+	            m_deploymentPackageName = fromTarget;
+	        }
+	        else {
+	            m_deploymentPackageName = fromSource;
+	        }
+	    }
+
+	    /**
+	     * Ends a deployment session.
+	     */
+	    private void endSession() {
+	        m_session = null;
+	        m_deploymentPackageName = null;
+	        m_toInstall = null;
+	        m_toRemove = null;
+	    }
+
+	    private void ensureSession()  {
+	        if (m_session == null) {
+	            throw new IllegalStateException("This resource processor is currently not part of a deployment session.");
+	        }
+	    }
+
+	    public void begin(DeploymentSession session) {
+	        startSession(session);
+	    }
+
+	    public void process(String name, InputStream stream) throws ResourceProcessorException {
+	        ensureSession();
+	        m_toInstall.add(name);
+	    }
+
+	    public void dropped(String resource) throws ResourceProcessorException {
+	        ensureSession();
+	        m_toRemove.add(resource);
+	    }
+
+	    public void dropAllResources() throws ResourceProcessorException {
+	        ensureSession();
+	        m_toRemove.addAll(Collections.EMPTY_LIST /* should be a list of all current resources */);
+	    }
+
+	    public void prepare() throws ResourceProcessorException {
+	        ensureSession();
+	    }
+
+	    public void commit() {
+	        ensureSession();
+	        while (!m_toInstall.isEmpty()) {
+	        	System.out.println("installing: " + m_toInstall.remove(0));
+	        }
+	        while (!m_toRemove.isEmpty()) {
+	        	System.out.println("removing: " + m_toRemove.remove(0));
+	        }
+	        endSession();
+	    }
+
+	    public void rollback() {
+	        // nothing special to do.
+	        ensureSession();
+	        endSession();
+	    }
+
+	    public void cancel() {
+	        ensureSession();
+	        // Nothing to do: we have no long-running operation, we only read the stream.
+	    }
+	}
+
+This should be enough to get you started, but the code takes a few shortcuts so please do take some time to read the specification and implement each method correctly.
+
+The next step then is to publish this processor as an OSGi service. Don't forget to add the SERVICE_PID property and set its value, because that is how the processor is later recognized. Package everything up in an OSGi bundle and make sure to include these two headers in its manifest:
+
+	Deployment-ProvidesResourceProcessor: org.apache.ace.resourceprocessor.custom
+	DeploymentPackage-Customizer: true
+
+The first one should match the PID you used earlier.
+
+# Writing an ArtifactHelper and ArtifactRecognizer
+
+These services can usually just be implemented by the same class. The artifact recognizer is used to identify an artifact as being of this specific type. How it does that is up to the implementation. It might do something as simple as look at the file extension, but a lot of recognizers will also inspect (part of) the actual file. The artifact helper then contains all kinds of methods to help ACE deal with this specific type of artifact. The API documentation of these two interfaces explains the methods in detail. Again, let's get started with an implementation of both for a very simple artifact: a file with a specific extension:
+
+	:::java
+	public class CustomArtifactHelper implements ArtifactRecognizer, ArtifactHelper {
+	    public static final String KEY_FILENAME = "filename";
+	    public static final String MIMETYPE = "application/vnd.apache.ace.custom";
+	    public static final String PROCESSOR = "org.apache.ace.resourceprocessor.custom";
+
+		@Override
+		public boolean canUse(ArtifactObject object) {
+	        return (object == null) ? false : MIMETYPE.equals(object.getMimetype());
+		}
+
+		@Override
+		public ArtifactPreprocessor getPreprocessor() {
+			return null;
+		}
+
+		@Override
+		public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties) {
+	        return "(" + ArtifactObject.KEY_ARTIFACT_NAME + "=" + obj.getAttribute(ArtifactObject.KEY_ARTIFACT_NAME) + ")";
+		}
+
+		@Override
+		public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties) {
+	        return Integer.MAX_VALUE;
+		}
+
+		@Override
+		public Comparator<ArtifactObject> getComparator() {
+			return null;
+		}
+
+		@Override
+		public Map<String, String> checkAttributes(Map<String, String> attributes) {
+			return attributes;
+		}
+
+	    public String[] getDefiningKeys() {
+	        return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+	    }
+
+	    public String[] getMandatoryAttributes() {
+	        return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+	    }
+
+		@Override
+		public String recognize(ArtifactResource artifact) {
+			// here we can examine the stream to check the contents of the artifact
+			// for this demo, our check is just for the extension of the URL, which is
+			// a bit simplistic
+			if (artifact.getURL().toExternalForm().endsWith(".custom")) {
+				return MIMETYPE;
+			}
+			return null;
+		}
+
+		@Override
+		public Map<String, String> extractMetaData(ArtifactResource artifact) throws IllegalArgumentException {
+	        Map<String, String> result = new HashMap<String, String>();
+	        result.put(ArtifactObject.KEY_PROCESSOR_PID, PROCESSOR);
+	        result.put(ArtifactObject.KEY_MIMETYPE, MIMETYPE);
+	        String name = new File(artifact.getURL().getFile()).getName();
+	        result.put(ArtifactObject.KEY_ARTIFACT_NAME, name);
+	        result.put(KEY_FILENAME, name);
+	        return result;
+		}
+
+		@Override
+		public boolean canHandle(String mimetype) {
+			return MIMETYPE.equals(mimetype);
+		}
+
+		@Override
+		public String getExtension(ArtifactResource artifact) {
+			return ".custom";
+		}
+	}
+
+Again, this is no production code, but it should get you started quickly. This code will recognize artifacts that have the ".custom" file extension. No effort is done here to look at the contents of the file, to keep the example simple. Publish this instance as both an ArtifactHelper and an ArtifactRecognizer and make sure to add a service property for the mime type: ArtifactObject.KEY_MIMETYPE, CustomArtifactHelper.MIMETYPE
+
+Wrap it up in a bundle, and you're ready to use your custom artifact in ACE.
+
+# Installing everything in ACE
+
+To add the new artifact type to ACE, you first have to take the bundle that contained the ArtifactHelper and ArtifactRecognizer service and add that to ACE. The bundle should be part of the ACE client. If you use the "all in one" server, add it to that.
+
+The second step is to upload the resource processor to ACE. You can do that like you upload any other bundle. Just add it to the artifact column. After adding it, it will not show up in the column, but ACE will send it to a target if that target needs an artifact of this type.
+
+Should you ever discover that you made a mistake in your resource processor, you can simply upload a newer one. Just make sure you bump the version and ACE will ensure that everybody gets this latest version.

Modified: ace/site/trunk/content/user-doc/getting-started.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/user-doc/getting-started.mdtext?rev=1533428&r1=1533427&r2=1533428&view=diff
==============================================================================
--- ace/site/trunk/content/user-doc/getting-started.mdtext (original)
+++ ace/site/trunk/content/user-doc/getting-started.mdtext Fri Oct 18 12:50:11 2013
@@ -6,39 +6,17 @@ This guide shows the core functionality 
 
 To start using ACE, you must first launch a server. If you're a developer, you can do that inside Eclipse, as explained [here](/dev-doc/getting-started.html). Otherwise, you need to download a distribution of the server, unpack it, and start it up:
 
-### Version 0.8.1
-
-1. Download a binary distribution of the server from the [download](/downloads.html) page.
-1. Unpack the archive somewhere on your filesystem.
-
-### Version 1.0 (comming soon)
-
 1. Download the binary distribution called `apache-ace-<version>-bin.zip` from the [download](/downloads.html) page.
 1. Unpack the archive somewhere on your filesystem.
 
 ## Start the ACE server
 
-### Version 0.8.1
-
-1. Open a terminal and navigate into the root of the distribution.
-1. Start the server using `run.sh` (on Linux and Mac OS X) or `run.bat` (on Windows).
-
-### Version 1.0
-
 1. Open a terminal and navigate nto the root of the distribution.
 1. Navigate to the sub directory `server-allinone`.
 1. Start the server using `java -jar server-allinone.jar`
 
 ## Start an ACE target
 
-### Version 0.8.1
-
-1. Open a terminal and navigate into the root of the distribution.
-1. Navigate to the sub directory `ace-launcher/target`.
-1. Start the agent using `java -jar org.apache.ace.launcher*.jar`
-
-### Version 1.0
-
 1. Open a terminal and navigate into the root of the distribution.
 1. Navigate to the sub directory `target`.
 1. Start the target using `java -jar target.jar`

Modified: ace/site/trunk/content/user-doc/user-guide.mdtext
URL: http://svn.apache.org/viewvc/ace/site/trunk/content/user-doc/user-guide.mdtext?rev=1533428&r1=1533427&r2=1533428&view=diff
==============================================================================
--- ace/site/trunk/content/user-doc/user-guide.mdtext (original)
+++ ace/site/trunk/content/user-doc/user-guide.mdtext Fri Oct 18 12:50:11 2013
@@ -50,7 +50,7 @@ To upload one or more artifacts, you cli
 
 Once artifacts are uploaded, they appear in the Artifacts column. For each artifact, you can edit its properties by double clicking on it. In addition, you can unlink an artifact from a feature, which will be discussed later on, and remove an artifact. **Note**: removing an artifact will only remove it from the server's metadata, *not* from the OBR. 
 
-If you try to upload an artifact that is not recognized by ACE, an error is displayed noting that that particular artifact is not uploaded. Adding support for new types of artifacts in ACE is discussed in [this article](/dev-doc/adding-artifact-recognizers.html).
+If you try to upload an artifact that is not recognized by ACE, an error is displayed noting that that particular artifact is not uploaded. Adding support for new types of artifacts in ACE is discussed in [this article](/dev-doc/adding-custom-artifact-types.html).
 
 **NOTE**: All changes made through the Web UI need to be stored explicitly by pressing the "Store" button, otherwise they will not be visible to the ACE server. In case you want to revert all changes, you can use the "Revert" button. This will ignore all changes and retrieve the latest state from the server. In case there are no local changes, you can still retrieve the latest state from the server using the "Retrieve" button.
 

Modified: ace/site/trunk/templates/sidenav.html
URL: http://svn.apache.org/viewvc/ace/site/trunk/templates/sidenav.html?rev=1533428&r1=1533427&r2=1533428&view=diff
==============================================================================
--- ace/site/trunk/templates/sidenav.html (original)
+++ ace/site/trunk/templates/sidenav.html Fri Oct 18 12:50:11 2013
@@ -14,7 +14,7 @@
     <a href="/downloads.html">Downloads</a>
   </li>
   <li class="dropdown">
-    <a href="#" class="dropdown-toggle" data-toggle="dropdown">User Documentation <b class="caret"></b></a>
+    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Users <b class="caret"></b></a>
     <ul class="dropdown-menu">
       <li>
         <a href="/user-doc/introduction.html">Introduction</a>
@@ -23,6 +23,9 @@
         <a href="/user-doc/getting-started.html">Getting Started</a>
       </li>
       <li>
+        <a href="/user-doc/user-guide.html">User Guide</a>
+      </li>
+      <li>
         <a href="/user-doc/features.html">Features</a>
       </li>
 	    <li>
@@ -40,7 +43,7 @@
     </ul>
   </li>
   <li class="dropdown">
-    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Developer Documentation <b class="caret"></b></a>
+    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Developers <b class="caret"></b></a>
     <ul class="dropdown-menu">
       <li>
         <a href="/dev-doc/getting-started.html">Getting Started</a>
@@ -66,6 +69,9 @@
       <li>
         <a href="/dev-doc/writing-tests.html">Writing unit/integration tests</a>
       </li>
+      <li>
+        <a href="/dev-doc/adding-custom-artifact-types.html">Adding custom artifact types</a>
+      </li>
     </ul>
   </li>
   <li class="dropdown">

Modified: ace/site/trunk/templates/skeleton.html
URL: http://svn.apache.org/viewvc/ace/site/trunk/templates/skeleton.html?rev=1533428&r1=1533427&r2=1533428&view=diff
==============================================================================
--- ace/site/trunk/templates/skeleton.html (original)
+++ ace/site/trunk/templates/skeleton.html Fri Oct 18 12:50:11 2013
@@ -2,44 +2,14 @@
 <html lang="en">
   <head>
     <title>{% block title %}{{ headers.title }}{% endblock %}</title>
-
     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
     <meta property="og:image" content="http://www.apache.org/images/asf_logo.gif" />
-
-  <!--
-    <link rel="stylesheet/less" type="text/css" href="/lib/bootstrap.less">
-    <link href="/css/prettify.css" rel="stylesheet" media="screen">
-    <link href="/css/code.css" rel="stylesheet" media="screen">
-
-    <script src="/js/less-1.2.1.min.js" type="text/javascript"></script>
-    <script src="http://code.jquery.com/jquery-1.7.min.js"></script>
-    <script src="/js/prettify.js"></script>
-    
-    <script src="/js/bootstrap-alert.js"></script>
-    <script src="/js/bootstrap-dropdown.js"></script>
-    <script src="/js/bootstrap-tooltip.js"></script>
-    <script src="/js/bootstrap-alerts.js"></script>
-    <script src="/js/bootstrap-modal.js"></script>
-    <script src="/js/bootstrap-transition.js"></script>
-    <script src="/js/bootstrap-button.js"></script>
-    <script src="/js/bootstrap-popover.js"></script>
-    <script src="/js/bootstrap-twipsy.js"></script>
-    <script src="/js/bootstrap-buttons.js"></script>
-    <script src="/js/bootstrap-scrollspy.js"></script>
-    <script src="/js/bootstrap-typeahead.js"></script>
-    <script src="/js/bootstrap-carousel.js"></script>
-    <script src="/js/bootstrap-tab.js"></script>
-    <script src="/js/bootstrap-collapse.js"></script>
-    <script src="/js/bootstrap-tabs.js"></script>
-  -->
-
     <link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
     <link href="/css/prettify.css" rel="stylesheet" media="screen">
     <link href="/css/code.css" rel="stylesheet" media="screen">
     <script src="http://code.jquery.com/jquery.js"></script>
     <script src="/js/bootstrap.min.js"></script>    
     <script src="/js/prettify.js"></script>
-
     {% if headers.atom %}<link rel="alternate" href="{{ headers.atom.url }}" type="application/atom+xml" title="{{ headers.atom.title }}" />{% endif %}
     {% if headers.base %}<base href="{{ headers.base }}" />{% endif %}
     {% if headers.notice %}<!-- {{ headers.notice }} -->{% endif %}
@@ -48,7 +18,6 @@
     $().dropdown()
     </script>
   </head>
-
   <body style="padding-top: 50px;">
     <div class="navbar navbar-fixed-top">
       <div class="navbar-inner">