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 2012/03/20 17:37:32 UTC
svn commit: r1302986 - in
/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest:
LogEventSerializer.java RESTClientServlet.java
RepositoryObjectSerializer.java Workspace.java
Author: marrs
Date: Tue Mar 20 16:37:32 2012
New Revision: 1302986
URL: http://svn.apache.org/viewvc?rev=1302986&view=rev
Log:
ACE-151 enhanced the REST API with more options to query the audit log (now separate from target) and to register and approve changes
Added:
ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/LogEventSerializer.java (with props)
Modified:
ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java
ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RepositoryObjectSerializer.java
ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java
Added: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/LogEventSerializer.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/LogEventSerializer.java?rev=1302986&view=auto
==============================================================================
--- ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/LogEventSerializer.java (added)
+++ ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/LogEventSerializer.java Tue Mar 20 16:37:32 2012
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.ace.client.rest;
+
+import java.lang.reflect.Type;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.ace.log.AuditEvent;
+import org.apache.ace.log.LogEvent;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+public class LogEventSerializer implements JsonSerializer<LogEvent> {
+
+ public JsonElement serialize(LogEvent e, Type typeOfSrc, JsonSerializationContext context) {
+ DateFormat format = SimpleDateFormat.getDateTimeInstance();
+ JsonObject event = new JsonObject();
+ event.addProperty("logId", e.getLogID());
+ event.addProperty("id", e.getID());
+ event.addProperty("time", format.format(new Date(e.getTime())));
+ event.addProperty("type", toAuditEventType(e.getType()));
+ JsonObject eventProperties = new JsonObject();
+ Dictionary p = e.getProperties();
+ Enumeration keyEnumeration = p.keys();
+ while (keyEnumeration.hasMoreElements()) {
+ Object key = keyEnumeration.nextElement();
+ eventProperties.addProperty(key.toString(), p.get(key).toString());
+ }
+ event.add("properties", eventProperties);
+ return event;
+ }
+
+ private String toAuditEventType(int type) {
+ switch (type) {
+ case AuditEvent.BUNDLE_INSTALLED: return "bundle installed";
+ case AuditEvent.BUNDLE_RESOLVED: return "bundle resolved";
+ case AuditEvent.BUNDLE_STARTED: return "bundle started";
+ case AuditEvent.BUNDLE_STOPPED: return "bundle stopped";
+ case AuditEvent.BUNDLE_UNRESOLVED: return "bundle unresolved";
+ case AuditEvent.BUNDLE_UPDATED: return "bundle updated";
+ case AuditEvent.BUNDLE_UNINSTALLED: return "bundle uninstalled";
+ case AuditEvent.BUNDLE_STARTING: return "bundle starting";
+ case AuditEvent.BUNDLE_STOPPING: return "bundle stopping";
+ case AuditEvent.FRAMEWORK_INFO: return "framework info";
+ case AuditEvent.FRAMEWORK_WARNING: return "framework warning";
+ case AuditEvent.FRAMEWORK_ERROR: return "framework error";
+ case AuditEvent.FRAMEWORK_REFRESH: return "framework refresh";
+ case AuditEvent.FRAMEWORK_STARTED: return "framework started";
+ case AuditEvent.FRAMEWORK_STARTLEVEL: return "framework startlevel";
+ case AuditEvent.DEPLOYMENTADMIN_INSTALL: return "deployment admin install";
+ case AuditEvent.DEPLOYMENTADMIN_UNINSTALL: return "deployment admin uninstall";
+ case AuditEvent.DEPLOYMENTADMIN_COMPLETE: return "deployment admin complete";
+ case AuditEvent.DEPLOYMENTCONTROL_INSTALL: return "deployment control install";
+ default: return Integer.toString(type);
+ }
+ }
+}
Propchange: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/LogEventSerializer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java?rev=1302986&r1=1302985&r2=1302986&view=diff
==============================================================================
--- ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java (original)
+++ ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RESTClientServlet.java Tue Mar 20 16:37:32 2012
@@ -34,6 +34,8 @@ import javax.servlet.http.HttpServletRes
import org.apache.ace.client.repository.RepositoryObject;
import org.apache.ace.client.repository.SessionFactory;
+import org.apache.ace.client.repository.stateful.StatefulTargetObject;
+import org.apache.ace.log.LogEvent;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.osgi.service.cm.ConfigurationException;
@@ -48,7 +50,7 @@ import com.google.gson.JsonPrimitive;
* Servlet that offers a REST client API.
*/
public class RESTClientServlet extends HttpServlet implements ManagedService {
- private static final long serialVersionUID = 5210711248294238039L;
+ private static final long serialVersionUID = 5210711248294238039L;
/** Alias that redirects to the latest version automatically. */
private static final String LATEST_FOLDER = "latest";
/** Name of the folder where working copies are kept. */
@@ -67,6 +69,12 @@ public class RESTClientServlet extends H
private static final String KEY_DEPLOYMENT_REPOSITORY_NAME = "deployment.repository.name";
/** Name of the user to log in as. */
private static final String KEY_USER_NAME = "user.name";
+ /** The action name for approving targets. */
+ private static final String ACTION_APPROVE = "approve";
+ /** The action name for registering targets. */
+ private static final String ACTION_REGISTER = "register";
+ /** The action name for reading audit events. */
+ private static final String ACTION_AUDITEVENTS = "auditEvents";
private static long m_sessionID = 1;
@@ -87,6 +95,7 @@ public class RESTClientServlet extends H
public RESTClientServlet() {
m_gson = (new GsonBuilder())
.registerTypeHierarchyAdapter(RepositoryObject.class, new RepositoryObjectSerializer())
+ .registerTypeHierarchyAdapter(LogEvent.class, new LogEventSerializer())
.create();
}
@@ -107,6 +116,18 @@ public class RESTClientServlet extends H
return;
}
}
+ else if (pathElements.length == 2) {
+ JsonArray result = new JsonArray();
+ result.add(new JsonPrimitive(Workspace.ARTIFACT));
+ result.add(new JsonPrimitive(Workspace.ARTIFACT2FEATURE));
+ result.add(new JsonPrimitive(Workspace.FEATURE));
+ result.add(new JsonPrimitive(Workspace.FEATURE2DISTRIBUTION));
+ result.add(new JsonPrimitive(Workspace.DISTRIBUTION));
+ result.add(new JsonPrimitive(Workspace.DISTRIBUTION2TARGET));
+ result.add(new JsonPrimitive(Workspace.TARGET));
+ resp.getWriter().println(m_gson.toJson(result));
+ return;
+ }
else if (pathElements.length == 3) {
if (WORK_FOLDER.equals(pathElements[0])) {
Workspace workspace = getWorkspace(pathElements[1]);
@@ -115,7 +136,7 @@ public class RESTClientServlet extends H
List<RepositoryObject> objects = workspace.getRepositoryObjects(pathElements[2]);
JsonArray result = new JsonArray();
for (RepositoryObject ro : objects) {
- String identity = Workspace.getRepositoryObjectIdentity(ro);
+ String identity = ro.getDefinition();
if (identity != null) {
result.add(new JsonPrimitive(URLEncoder.encode(identity, "UTF-8")));
}
@@ -146,6 +167,61 @@ public class RESTClientServlet extends H
return;
}
}
+ else if (pathElements.length == 5) {
+ if (WORK_FOLDER.equals(pathElements[0])) {
+ Workspace workspace = getWorkspace(pathElements[1]);
+ if (workspace != null) {
+ String entityType = pathElements[2];
+ String entityId = pathElements[3];
+ String action = pathElements[4];
+ RepositoryObject repositoryObject = workspace.getRepositoryObject(entityType, entityId);
+ if (repositoryObject == null) {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Repository object of type " + entityType + " and identity " + entityId + " not found.");
+ return;
+ }
+
+ boolean isTarget = Workspace.TARGET.equals(entityType);
+ if (isTarget && ACTION_APPROVE.equals(action)) {
+ resp.getWriter().println(m_gson.toJson(((StatefulTargetObject) repositoryObject).getStoreState()));
+ return;
+ }
+ else if (isTarget && ACTION_REGISTER.equals(action)) {
+ resp.getWriter().println(m_gson.toJson(((StatefulTargetObject) repositoryObject).getRegistrationState()));
+ return;
+ }
+ else if (isTarget && ACTION_AUDITEVENTS.equals(action)) {
+ StatefulTargetObject target = (StatefulTargetObject) repositoryObject;
+ List<LogEvent> events = target.getAuditEvents();
+ String startValue = req.getParameter("start");
+ String maxValue = req.getParameter("max");
+ int start = (startValue == null) ? 0 : Integer.parseInt(startValue);
+ if (start < 0) {
+ start = 0;
+ }
+ if (start >= events.size()) {
+ start = events.size() - 1;
+ }
+ int max = (maxValue == null) ? 100 : Integer.parseInt(maxValue);
+ if (max < 1) {
+ max = 1;
+ }
+ int end = start + max;
+ if (end > events.size()) {
+ end = events.size();
+ }
+ List<LogEvent> selection = events.subList(start, end);
+ resp.getWriter().println(m_gson.toJson(selection));
+ return;
+ }
+ else {
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unknown action '" + action + "' for " + entityType + "/" + entityId);
+ return;
+ }
+ }
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Could not find workspace: " + pathElements[1]);
+ return;
+ }
+ }
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
@@ -201,7 +277,7 @@ public class RESTClientServlet extends H
try {
RepositoryValueObject data = m_gson.fromJson(req.getReader(), RepositoryValueObject.class);
RepositoryObject object = workspace.addRepositoryObject(pathElements[2], data.attributes, data.tags);
- String identity = Workspace.getRepositoryObjectIdentity(object);
+ String identity = object.getDefinition();
if (identity != null) {
resp.sendRedirect(buildPathFromElements(WORK_FOLDER, pathElements[1], pathElements[2], identity));
}
@@ -218,6 +294,39 @@ public class RESTClientServlet extends H
return;
}
}
+ else if (pathElements.length == 5) {
+ if (WORK_FOLDER.equals(pathElements[0])) {
+ Workspace workspace = getWorkspace(pathElements[1]);
+ if (workspace != null) {
+ String entityType = pathElements[2];
+ String entityId = pathElements[3];
+ RepositoryObject repositoryObject = workspace.getRepositoryObject(entityType, entityId);
+ if (repositoryObject == null) {
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Repository object of type " + entityType + " and identity " + entityId + " not found.");
+ return;
+ }
+
+ // the last element is the "command" to apply...
+ String action = pathElements[4];
+
+ if (Workspace.TARGET.equals(entityType) && ACTION_APPROVE.equals(action)) {
+ StatefulTargetObject sto = workspace.approveTarget(repositoryObject);
+ // Respond with the current store state...
+ resp.getWriter().println(m_gson.toJson(sto.getStoreState()));
+ return;
+ } else if (Workspace.TARGET.equals(entityType) && ACTION_REGISTER.equals(action)) {
+ StatefulTargetObject sto = workspace.registerTarget(repositoryObject);
+ // Respond with the current registration state...
+ resp.getWriter().println(m_gson.toJson(sto.getRegistrationState()));
+ return;
+ }
+
+ resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unknown action for " + pathElements[2]);
+ }
+ resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Could not find workspace: " + pathElements[1]);
+ return;
+ }
+ }
}
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
Modified: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RepositoryObjectSerializer.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RepositoryObjectSerializer.java?rev=1302986&r1=1302985&r2=1302986&view=diff
==============================================================================
--- ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RepositoryObjectSerializer.java (original)
+++ ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/RepositoryObjectSerializer.java Tue Mar 20 16:37:32 2012
@@ -75,7 +75,7 @@ public class RepositoryObjectSerializer
state.addProperty("autoApprove", Boolean.toString(stateful.getAutoApprove()));
JsonArray artifactsFromShop = new JsonArray();
for (ArtifactObject a : stateful.getArtifactsFromShop()) {
- artifactsFromShop.add(new JsonPrimitive(Workspace.getRepositoryObjectIdentity(a)));
+ artifactsFromShop.add(new JsonPrimitive(a.getDefinition()));
}
state.add("artifactsFromShop", artifactsFromShop);
JsonArray artifactsFromDeployment = new JsonArray();
@@ -85,7 +85,6 @@ public class RepositoryObjectSerializer
state.add("artifactsFromDeployment", artifactsFromDeployment);
state.addProperty("lastInstallVersion", stateful.getLastInstallVersion());
state.addProperty("lastInstallSuccess", stateful.getLastInstallSuccess());
- state.add("auditEvents", getAuditEvents(stateful));
/* TODO getLicenses/AssocationsWith might not be that helpful since the data is also available in a different way */
/* TODO some of this tends to show up as attributes as well, so we will need to do some filtering there */
/* TODO some aspects of the state can be manipulated as well, we need to supply methods for that */
Modified: ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java
URL: http://svn.apache.org/viewvc/ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java?rev=1302986&r1=1302985&r2=1302986&view=diff
==============================================================================
--- ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java (original)
+++ ace/trunk/ace-client-rest/src/main/java/org/apache/ace/client/rest/Workspace.java Tue Mar 20 16:37:32 2012
@@ -90,7 +90,7 @@ public class Workspace {
.setService(service, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")")
.setRequired(isRequired)
.setInstanceBound(true)
- );
+ );
}
private void addDependency(Component component, Class service, boolean isRequired) {
@@ -98,7 +98,7 @@ public class Workspace {
.setService(service)
.setRequired(isRequired)
.setInstanceBound(true)
- );
+ );
}
public void init(Component component) {
@@ -125,7 +125,6 @@ public class Workspace {
.addDeploymentRepository(new URL(m_repositoryURL), m_customerName, m_deploymentRepositoryName, true)
);
m_repositoryAdmin.checkout();
-// m_repositoryAdmin.revert();
}
catch (IOException e) {
e.printStackTrace();
@@ -135,6 +134,10 @@ public class Workspace {
public void destroy() {
}
+
+ public void checkout() throws IOException {
+ m_repositoryAdmin.checkout();
+ }
public void commit() throws IOException {
m_repositoryAdmin.commit();
@@ -144,10 +147,6 @@ public class Workspace {
return getObjectRepository(entityType).get(entityId);
}
- public static String getRepositoryObjectIdentity(RepositoryObject object) {
- return object.getDefinition();
- }
-
public List<RepositoryObject> getRepositoryObjects(String entityType) {
List list = getObjectRepository(entityType).get();
if (list != null) {
@@ -203,7 +202,39 @@ public class Workspace {
return getObjectRepository(entityType).create(attributes, tags);
}
}
-
+
+ /**
+ * Approves a given stateful target object.
+ * <p>If the given repository object does <em>not</em> represent a stateful target object, this method will do nothing.</p>
+ *
+ * @param repositoryObject the repository object to approve.
+ * @return the approved stateful target object, can be <code>null</code> only if the given repository object does not represent a {@link StatefulTargetObject}.
+ */
+ public StatefulTargetObject approveTarget(RepositoryObject repositoryObject) {
+ if (!(repositoryObject instanceof StatefulTargetObject)) {
+ return null;
+ }
+ StatefulTargetObject targetObject = (StatefulTargetObject) repositoryObject;
+ targetObject.approve();
+ return targetObject;
+ }
+
+ /**
+ * Registers a given stateful target object.
+ * <p>If the given repository object does <em>not</em> represent a stateful target object, this method will do nothing.</p>
+ *
+ * @param repositoryObject the repository object to register.
+ * @return the registered stateful target object, can be <code>null</code> only if the given repository object does not represent a {@link StatefulTargetObject}.
+ */
+ public StatefulTargetObject registerTarget(RepositoryObject repositoryObject) {
+ if (!(repositoryObject instanceof StatefulTargetObject)) {
+ return null;
+ }
+ StatefulTargetObject targetObject = (StatefulTargetObject) repositoryObject;
+ targetObject.register();
+ return targetObject;
+ }
+
public void updateObjectWithData(String entityType, String entityId, RepositoryValueObject valueObject) {
RepositoryObject repositoryObject = getRepositoryObject(entityType, entityId);
// first handle the attributes