diff --git a/src/oca/java/build.sh b/src/oca/java/build.sh
new file mode 100755
index 0000000000..62938917da
--- /dev/null
+++ b/src/oca/java/build.sh
@@ -0,0 +1,105 @@
+#!/bin/bash
+
+# -------------------------------------------------------------------------- #
+# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
+# #
+# 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. #
+#--------------------------------------------------------------------------- #
+
+#-------------------------------------------------------------------------------
+# DIR DEFINITIONS
+#-------------------------------------------------------------------------------
+
+DOC_DIR="./doc"
+BIN_DIR="./bin"
+JAR_DIR="./jar/org.opennebula.client.jar"
+LIB_DIR="./lib"
+#-------------------------------------------------------------------------------
+# COMMAND LINE PARSING
+#-------------------------------------------------------------------------------
+usage() {
+ echo
+ echo "Usage: build.sh [-d ] [-h] [-s]"
+ echo
+ echo "-d: build the documentation"
+ echo "-s: compile the examples"
+ echo "-h: prints this help"
+}
+#-------------------------------------------------------------------------------
+
+TEMP_OPT=`getopt -o hsd -n 'build.sh' -- "$@"`
+
+eval set -- "$TEMP_OPT"
+
+DO_DOC="no"
+DO_EXA="no"
+
+while true ; do
+ case "$1" in
+ -h) usage; exit 0;;
+ -d) DO_DOC="yes"; shift ;;
+ -s) DO_EXA="yes"; shift ;;
+ --) shift ; break ;;
+ *) usage; exit 1 ;;
+ esac
+done
+
+#-------------------------------------------------------------------------------
+# BUILD FUNCTIONS
+#-------------------------------------------------------------------------------
+
+do_documentation()
+{
+ echo "Generating javadocs..."
+
+ rm -rf $DOC_DIR > /dev/null 2>&1
+ mkdir -p $DOC_DIR
+ javadoc -quiet -classpath $LIB_DIR"/*" -d $DOC_DIR \
+ -sourcepath ./src/ \
+ -subpackages org.opennebula \
+ -windowtitle 'OpenNebula Cloud API' \
+ -doctitle 'OpenNebula Cloud API Specification' \
+ -header 'OpenNebula
Java API' \
+ -bottom 'Visit OpenNebula.org
Copyright 2002-2010 ©
+OpenNebula Project Leads (OpenNebula.org).'
+}
+
+do_jar()
+{
+ rm -rf $BIN_DIR > /dev/null 2>&1
+ mkdir -p $BIN_DIR
+
+ echo "Compiling java files into class files..."
+ javac -d $BIN_DIR -cp $LIB_DIR"/*" `find src -name *.java`
+
+ if [ $? -eq 0 ]; then
+ echo "Packaging class files in a jar..."
+ jar cf $JAR_DIR -C $BIN_DIR org
+ fi
+}
+
+do_examples()
+{
+ echo "Compiling OpenNebula Cloud API Examples..."
+}
+
+do_jar
+
+if [ "$DO_DOC" = "yes" ] ; then
+ do_documentation
+fi
+
+if [ "$DO_EXA" = "yes" ] ; then
+ do_examples
+fi
diff --git a/src/oca/java/share/examples/SessionInit.class b/src/oca/java/share/examples/SessionInit.class
new file mode 100644
index 0000000000..77ffc19899
Binary files /dev/null and b/src/oca/java/share/examples/SessionInit.class differ
diff --git a/src/oca/java/src/org/opennebula/client/Client.java b/src/oca/java/src/org/opennebula/client/Client.java
new file mode 100644
index 0000000000..1fea68b32d
--- /dev/null
+++ b/src/oca/java/src/org/opennebula/client/Client.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)
+ *
+ * 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.opennebula.client;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.client.XmlRpcClient;
+import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
+
+
+/**
+ * This class represents the connection with the core and handles the
+ * xml-rpc calls.
+ *
+ */
+public class Client {
+
+ //--------------------------------------------------------------------------
+ // PUBLIC INTERFACE
+ //--------------------------------------------------------------------------
+
+ /**
+ * Creates a new xml-rpc client with default options:
+ * the auth. file will be assumed to be at $ONE_AUTH, and
+ * the endpoint will be set to $ONE_XMLRPC.
+ *
+ * It is the equivalent of Client(null, null).
+ *
+ * @throws Exception if one authorization file cannot be located.
+ */
+ public Client() throws Exception
+ {
+ setOneAuth(null);
+ setOneEndPoint(null);
+ }
+
+ /**
+ * Creates a new xml-rpc client with specified options.
+ *
+ * @param secret A string containing the ONE user:password tuple.
+ * Can be null
+ * @param endpoint Where the rpc server is listening, must be something
+ * like "http://localhost:2633/RPC2". Can be null
+ * @throws Exception if the authorization options are invalid
+ */
+ public Client(String secret, String endpoint) throws Exception
+ {
+ setOneAuth(secret);
+ setOneEndPoint(endpoint);
+ }
+
+ /**
+ * Performs an XML-RPC call.
+ *
+ * @param action ONE action
+ * @param args ONE arguments
+ * @return The server's xml-rpc response encapsulated
+ */
+ public OneResponse call(String action, Object...args)
+ {
+ boolean success = false;
+ String msg = null;
+
+ try
+ {
+ Object[] params = new Object[args.length + 1];
+
+ params[0] = oneAuth;
+
+ for(int i=0; i 1)
+ {
+ try
+ {
+ msg = (String) result[1];
+ }
+ catch (ClassCastException e)
+ {
+ // The result may be an Integer
+ msg = ((Integer) result[1]).toString();
+ }
+ }
+
+
+ }
+ catch (XmlRpcException e)
+ {
+ msg = e.getMessage();
+ }
+
+ return new OneResponse(success, msg);
+ }
+
+ //--------------------------------------------------------------------------
+ // PRIVATE ATTRIBUTES AND METHODS
+ //--------------------------------------------------------------------------
+
+ private String oneAuth;
+ private String oneEndPoint;
+
+ private XmlRpcClient client;
+
+ private void setOneAuth(String secret) throws Exception
+ {
+ String oneSecret = secret;
+
+ try
+ {
+ if(oneSecret == null)
+ {
+ String oneAuthEnv = System.getenv("ONE_AUTH");
+ File authFile;
+
+ if ( oneAuthEnv != null && oneAuthEnv.length() != 0)
+ {
+ authFile = new File(oneAuthEnv);
+ }
+ else
+ {
+ authFile = new File(System.getenv("HOME")+"/.one/one_auth");
+ }
+
+ oneSecret =
+ (new BufferedReader(new FileReader(authFile))).readLine();
+ }
+
+ String[] token = oneSecret.split(":");
+
+ if(token.length != 2 )
+ {
+ throw new Exception("Wrong format for authorization string: "
+ + oneSecret);
+ }
+
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] digest = md.digest(token[1].getBytes());
+
+ String hash = "";
+
+ for(byte aux : digest)
+ {
+ int b = aux & 0xff;
+
+ if (Integer.toHexString(b).length() == 1)
+ {
+ hash += "0";
+ }
+
+ hash += Integer.toHexString(b);
+ }
+
+ oneAuth = token[0] + ":" + hash;
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new Exception("ONE_AUTH file not present");
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new Exception("Error initializing MessageDigest with SHA-1");
+ }
+ }
+
+ private void setOneEndPoint(String endpoint) throws Exception
+ {
+ oneEndPoint = "http://localhost:2633/RPC2";
+
+ if(endpoint != null)
+ {
+ oneEndPoint = endpoint;
+ }
+ else
+ {
+ String oneXmlRpcEnv = System.getenv("ONE_XMLRPC");
+
+ if ( oneXmlRpcEnv != null && oneXmlRpcEnv.length() != 0 )
+ {
+ oneEndPoint = oneXmlRpcEnv;
+ }
+ }
+
+ XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
+
+ try
+ {
+ config.setServerURL(new URL(oneEndPoint));
+ }
+ catch (MalformedURLException e)
+ {
+ throw new Exception("The URL "+oneEndPoint+" is malformed.");
+ }
+
+ client = new XmlRpcClient();
+ client.setConfig(config);
+ }
+}
diff --git a/src/oca/java/src/org/opennebula/client/OneResponse.java b/src/oca/java/src/org/opennebula/client/OneResponse.java
new file mode 100644
index 0000000000..98201ec769
--- /dev/null
+++ b/src/oca/java/src/org/opennebula/client/OneResponse.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)
+ *
+ * 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.opennebula.client;
+
+/**
+ * This class encapsulates OpenNebula's XML-RPC responses. Each response
+ * carries a boolean indicating if it is an error. It can also contain a
+ * success message, or an error message.
+ */
+public class OneResponse {
+ /**
+ * Creates a new response.
+ *
+ * @param success Indicates if the call was successful, and if
+ * the message is an error or an information string.
+ * @param message String containing the response message, or
+ * the error message.
+ */
+ public OneResponse(boolean success, String message)
+ {
+ this.success = success;
+ this.msg = message;
+ }
+
+ /**
+ * Returns true if the call resulted in error.
+ *
+ * @return True if the call resulted in error.
+ */
+ public boolean isError()
+ {
+ return !success;
+ }
+
+ /**
+ * Returns a string containing the error message, or null
+ * if the response isn't an error.
+ *
+ * @return A string containing the error message, or null
+ * if the response isn't an error.
+ */
+ public String getErrorMessage()
+ {
+ return success ? null : msg;
+ }
+
+ /**
+ * Returns a string containing the response information, or
+ * null if the response was an error. Note that the success
+ * message could be also null.
+ *
+ * @return A string containing the response information, or
+ * null if the response was an error. Note that the success
+ * message could be also null.
+ */
+ public String getMessage()
+ {
+ return success ? msg : null;
+ }
+
+ // ------------------------------------------------------------------------
+ // PRIVATE ATTRIBUTES
+ // ------------------------------------------------------------------------
+
+ private boolean success;
+ private String msg;
+}
diff --git a/src/oca/java/src/org/opennebula/client/Pool.java b/src/oca/java/src/org/opennebula/client/Pool.java
new file mode 100644
index 0000000000..8762ce5088
--- /dev/null
+++ b/src/oca/java/src/org/opennebula/client/Pool.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)
+ *
+ * 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.opennebula.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+/**
+ * Represents a generic OpenNebula Pool in XML format
+ * and provides the basic functionality to handle the Pool elements.
+ */
+public abstract class Pool{
+
+ protected Client client;
+
+ protected String elementName;
+ protected NodeList poolElements;
+
+ /**
+ * Sets the Pool attributes.
+ * @param elementName Name of the PoolElement's xml element
+ * @param client XML-RPC client which will handle calls
+ */
+ protected Pool(String elementName, Client client)
+ {
+ this.elementName = elementName;
+ this.client = client;
+ }
+
+ /**
+ * The factory method returns a suitable PoolElement object from
+ * an XML node. Each Pool must implement the corresponding factory method.
+ *
+ * @param node XML Dom node to build the PoolElement from
+ * @return The corresponding PoolElement
+ */
+ public abstract PoolElement factory(Node node);
+
+ /**
+ * After a *pool.info call, this method builds the internal xml
+ * representation of the pool.
+ * @param info The XML-RPC *pool.info response
+ */
+ public void processInfo(OneResponse info)
+ {
+ if (info.isError())
+ {
+ return;
+ }
+
+ try
+ {
+ DocumentBuilder builder;
+ Document doc;
+ Element xml;
+
+ builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ doc = builder.parse(
+ new ByteArrayInputStream(info.getMessage().getBytes()));
+ xml = doc.getDocumentElement();
+
+ poolElements = xml.getElementsByTagName(elementName);
+ }
+ catch (ParserConfigurationException e) {}
+ catch (SAXException e) {}
+ catch (IOException e) {}
+ }
+
+ /**
+ * Returns the indexth element in the pool. If index is greater than or
+ * equal to the number of elements in the pool, this returns null.
+ *
+ * @param index Index of the element.
+ * @return The element at the indexth position in the pool, or
+ * null if that is not a valid index.
+ */
+ public PoolElement item(int index)
+ {
+ PoolElement the_element = null;
+
+ if (poolElements != null)
+ {
+ Node node =poolElements.item(index);
+
+ if (node != null)
+ {
+ the_element = factory(node);
+ }
+ }
+
+ return the_element;
+ }
+
+ /**
+ * The number of elements in the pool.
+ * @return The number of elements in the pool.
+ */
+ public int getLength()
+ {
+ return poolElements == null ? 0 : poolElements.getLength();
+ }
+}
\ No newline at end of file
diff --git a/src/oca/java/src/org/opennebula/client/PoolElement.java b/src/oca/java/src/org/opennebula/client/PoolElement.java
new file mode 100644
index 0000000000..cc93e948fd
--- /dev/null
+++ b/src/oca/java/src/org/opennebula/client/PoolElement.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org)
+ *
+ * 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.opennebula.client;
+
+import java.io.ByteArrayInputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Represents a generic element of a Pool in
+ * XML format.
+ *
+ */
+public abstract class PoolElement {
+
+ protected static XPath xpath;
+
+ protected int id;
+ protected Node xml;
+
+ protected Client client;
+
+ /**
+ * Creates a new PoolElement with the specified attributes.
+ * @param id Id of the element.
+ * @param client XML-RPC Client.
+ * @param root Name of the xml's root element.
+ */
+ protected PoolElement(int id, Client client)
+ {
+ if(xpath == null)
+ {
+ XPathFactory factory = XPathFactory.newInstance();
+ xpath = factory.newXPath();
+ }
+
+ this.id = id;
+ this.client = client;
+ }
+
+ /**
+ * Creates a new PoolElement from the xml provided.
+ *
+ * @param client XML-RPC Client.
+ * @param xmlElement XML representation of the element.
+ * @param root Name of the xml's root element.
+ */
+ protected PoolElement(Node xmlElement, Client client)
+ {
+ if(xpath == null)
+ {
+ XPathFactory factory = XPathFactory.newInstance();
+ xpath = factory.newXPath();
+ }
+
+ this.xml = xmlElement;
+ this.client = client;
+ this.id = Integer.parseInt(xpath("id"));
+ }
+
+ /**
+ * After a *.info call, this method builds the internal xml
+ * representation of the pool.
+ * @param info The XML-RPC *.info response
+ */
+ protected void processInfo(OneResponse info)
+ {
+ if (info.isError())
+ {
+ return;
+ }
+
+ try
+ {
+ DocumentBuilder builder =
+ DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document doc = builder.parse(
+ new ByteArrayInputStream(info.getMessage().getBytes()));
+
+ xml = doc.getDocumentElement();
+ }
+ catch (Exception e) {}
+ }
+
+ /**
+ * Returns the element's ID.
+ * @return the element's ID.
+ */
+ public String getId()
+ {
+ return Integer.toString(id);
+ }
+
+ /**
+ * Returns the element's name.
+ * @return the element's name.
+ */
+ public String getName()
+ {
+ return xpath("name");
+ }
+
+ /**
+ * Performs an xpath evaluation for the "state" expression.
+ * @return The value of the STATE element.
+ */
+ public int state()
+ {
+ String state = xpath("state");
+
+ return state != null ? Integer.parseInt( state ) : -1;
+ }
+
+ /**
+ * Evaluates an XPath expression and returns the result as a String.
+ * If the internal xml representation is not built, returns null. The
+ * subclass method info() must be called before.
+ *
+ * @param expression The XPath expression.
+ * @return The String that is the result of evaluating the
+ * expression and converting the result to a String. Null if
+ * the internal xml representation is not built.
+ */
+ public String xpath(String expression)
+ {
+ String result = null;
+
+ try
+ {
+ result = xpath.evaluate(expression.toUpperCase(), xml);
+ }
+ catch (XPathExpressionException e) {}
+
+ return result;
+ }
+}