Commit of the iPOJO Webconsole plugin
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@789599 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/pom.xml b/ipojo/pom.xml
index b3500aa..f393973 100644
--- a/ipojo/pom.xml
+++ b/ipojo/pom.xml
@@ -30,7 +30,7 @@
<name>Apache Felix iPOJO</name>
<version>1.3.0-SNAPSHOT</version>
<packaging>pom</packaging>
-
+
<modules>
<module>metadata</module>
<module>manipulator</module>
@@ -48,8 +48,8 @@
<module>online-manipulator</module>
<module>junit4osgi</module>
</modules>
-
-
+
+
<profiles>
<profile>
<id>java5</id>
@@ -59,6 +59,7 @@
<modules>
<module>annotations</module>
<module>handler/jmx</module>
+ <module>webconsole-plugin</module>
</modules>
</profile>
<profile>
@@ -69,6 +70,7 @@
<modules>
<module>annotations</module>
<module>handler/jmx</module>
+ <module>webconsole-plugin</module>
</modules>
</profile>
<profile>
@@ -84,7 +86,7 @@
</modules>
</profile>
</profiles>
-
+
<build>
<plugins>
<plugin>
@@ -101,7 +103,7 @@
</plugins>
</build>
-
+
<reporting>
<plugins>
<plugin>
diff --git a/ipojo/webconsole-plugin/LICENSE b/ipojo/webconsole-plugin/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/ipojo/webconsole-plugin/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/ipojo/webconsole-plugin/NOTICE b/ipojo/webconsole-plugin/NOTICE
new file mode 100644
index 0000000..c0ac7a1
--- /dev/null
+++ b/ipojo/webconsole-plugin/NOTICE
@@ -0,0 +1,22 @@
+Apache Felix iPOJO Webconsole Plugins
+Copyright 2008-2009 The Apache Software Foundation
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+II. Used Software
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2007).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+III. License Summary
+- Apache License 2.0
diff --git a/ipojo/webconsole-plugin/metadata.xml b/ipojo/webconsole-plugin/metadata.xml
new file mode 100644
index 0000000..f2ac6a6
--- /dev/null
+++ b/ipojo/webconsole-plugin/metadata.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<ipojo>
+ <instance component="org.apache.felix.org.apache.felix.ipojo.webconsole.IPOJOServlet"/>
+</ipojo>
\ No newline at end of file
diff --git a/ipojo/webconsole-plugin/pom.xml b/ipojo/webconsole-plugin/pom.xml
new file mode 100644
index 0000000..511cd10
--- /dev/null
+++ b/ipojo/webconsole-plugin/pom.xml
@@ -0,0 +1,83 @@
+<!--
+ 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.webconsole</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ <name>iPOJO WebConsole Plugins</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.3</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ org.apache.felix.org.apache.felix.ipojo.webconsole
+ </Private-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.webconsole</artifactId>
+ <version>1.2.11-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.annotations</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ipojo/webconsole-plugin/src/main/java/org/apache/felix/org/apache/felix/ipojo/webconsole/IPOJOServlet.java b/ipojo/webconsole-plugin/src/main/java/org/apache/felix/org/apache/felix/ipojo/webconsole/IPOJOServlet.java
new file mode 100644
index 0000000..76b011c
--- /dev/null
+++ b/ipojo/webconsole-plugin/src/main/java/org/apache/felix/org/apache/felix/ipojo/webconsole/IPOJOServlet.java
@@ -0,0 +1,843 @@
+/*
+ * 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.felix.org.apache.felix.ipojo.webconsole;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.HandlerFactory;
+import org.apache.felix.ipojo.annotations.Component;
+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.ServiceProperty;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.architecture.InstanceDescription;
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.apache.felix.ipojo.handlers.dependency.DependencyDescription;
+import org.apache.felix.ipojo.handlers.dependency.DependencyHandlerDescription;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedService;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceDescription;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandlerDescription;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * iPOJO Plugin for the web console.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Component(immediate = true)
+@Provides(specifications = { Servlet.class })
+public class IPOJOServlet extends AbstractWebConsolePlugin {
+
+ /**
+ * Factory constant.
+ */
+ public static final String FACTORY = "factory";
+
+ /**
+ * Instance constant.
+ */
+ public static final String INSTANCE = "instance";
+
+ /**
+ * Handler constant.
+ */
+ public static final String HANDLER = "handler";
+
+ /**
+ * All constant.
+ */
+ public static final String ALL = "all";
+
+ /**
+ * UUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Label used by the web console.
+ */
+ @ServiceProperty(name = "felix.webconsole.label")
+ private String m_label = "ipojo";
+
+ /**
+ * Title used by the web console.
+ */
+ @ServiceProperty(name = "felix.webconsole.title")
+ private String m_title = "iPOJO";
+
+ /**
+ * List of available Architecture service.
+ */
+ @Requires(optional = true, specification = "org.apache.felix.ipojo.architecture.Architecture")
+ private List<Architecture> m_archs;
+
+ /**
+ * List of available Factories.
+ */
+ @Requires(optional = true, specification = "org.apache.felix.ipojo.Factory")
+ private List<Factory> m_factories;
+
+ /**
+ * List of available Handler Factories.
+ */
+ @Requires(optional = true, specification = "org.apache.felix.ipojo.HandlerFactory")
+ private List<HandlerFactory> m_handlers;
+
+ /**
+ * Creates a IPOJOServlet.
+ * This method activates the plugin.
+ * @param bc the bundle context
+ */
+ public IPOJOServlet(BundleContext bc) {
+ activate(bc);
+ }
+
+ /**
+ * Stop method.
+ * This method deactivates the plugin.
+ */
+ @Invalidate
+ public void stop() {
+ deactivate();
+ }
+
+
+ /**
+ * Gets the plugin label.
+ * @return the label
+ * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#getLabel()
+ */
+ public String getLabel() {
+ return m_label;
+ }
+
+ /**
+ * Gets the plugin title.
+ * @return the title
+ * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#getTitle()
+ */
+ public String getTitle() {
+ return m_title;
+ }
+
+ /**
+ * Gets the number of valid instances.
+ * @return the number of valid instances.
+ */
+ private int getValidCount() {
+ int i = 0;
+ for (Architecture a : m_archs) {
+ if (a.getInstanceDescription().getState() == ComponentInstance.VALID) {
+ i ++;
+ }
+ }
+ return i;
+ }
+
+ /**
+ * Gets the number of invalid instances.
+ * @return the number of invalid instances.
+ */
+ private int getInvalidCount() {
+ int i = 0;
+ for (Architecture a : m_archs) {
+ if (a.getInstanceDescription().getState() == ComponentInstance.INVALID) {
+ i ++;
+ }
+ }
+ return i;
+ }
+
+ /**
+ * Gets the HTML content of the plugin.
+ * @param req the request
+ * @param res the response
+ * @throws ServletException if the content cannot be computed
+ * @throws IOException if an IO Exception occurs
+ * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ protected void renderContent(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+
+ PrintWriter writer = res.getWriter();
+ // Set the fable plugin_table sortable.
+ writer.write("<script type=\"text/javascript\"> "
+ + "function setSortable() { \n"
+ + "$(document).ready(function() { \n"
+ + "$(\"#plugin_table\").tablesorter(); \n"
+ + "})};\n"
+ + "setSortable();"
+ + "</script>");
+ // Status Line
+ writer.write("<div class=\"fullwidth\"><div class=\"statusline\">"
+ + m_archs.size() + " instances in total, "
+ + getValidCount() + " valid instances, "
+ + getInvalidCount() + " invalid instances."
+ + "</div></div>");
+ // Button Line
+ writer.write("<form action=\"ipojo\" method=\"get\">"
+ + "<div class=\"fullwidth\">"
+ + "<div class=\"buttons\">"
+ + "<button style=\"margin-left: 30px;\" name=\"" + INSTANCE + "\" value=\"all\" type=\"submit\">Instances</button>"
+ + "<button style=\"margin-left: 30px;\" name=\"" + FACTORY + "\" value=\"all\" type=\"submit\">Factories</button>"
+ + "<button style=\"margin-left: 30px;\" name=\"" + HANDLER + "\" value=\"all\" type=\"submit\">Handlers</button>"
+ + "</div>"
+ + "</div>"
+ + "</form>");
+
+ // Compute the request and select the content to return
+ RequestInfo ri = new RequestInfo(req);
+ if (ri.m_type.equals(FACTORY)) {
+ if (ri.m_all) {
+ printFactoryList(writer);
+ } else {
+ printFactoryDetail(writer, ri.m_name);
+ }
+ }
+
+ if (ri.m_type.equals(INSTANCE)) {
+ if (ri.m_all) {
+ printInstanceList(writer);
+ } else {
+ printInstanceDetail(writer, ri.m_name);
+ }
+ }
+
+ if (ri.m_type.equals(HANDLER)) {
+ if (ri.m_all) {
+ printHandlerList(writer);
+ }
+ }
+
+ // Button Line
+ writer.write("<form action=\"ipojo\" method=\"get\">"
+ + "<div class=\"fullwidth\">"
+ + "<div class=\"buttons\">"
+ + "<button style=\"margin-left: 30px;\" name=\"" + INSTANCE + "\" value=\"all\" type=\"submit\">Instances</button>"
+ + "<button style=\"margin-left: 30px;\" name=\"" + FACTORY + "\" value=\"all\" type=\"submit\">Factories</button>"
+ + "<button style=\"margin-left: 30px;\" name=\"" + HANDLER + "\" value=\"all\" type=\"submit\">Handlers</button>"
+ + "</div>"
+ + "</div>"
+ + "</form>");
+
+ // Status Line
+ writer.write("<div class=\"fullwidth\"><div class=\"statusline\">"
+ + m_archs.size() + " instances in total, "
+ + getValidCount() + " valid instances, "
+ + getInvalidCount() + " invalid instances."
+ + "</div></div>");
+
+ }
+
+ /**
+ * Gets a Factory Detail page.
+ * This page contains all versions of the factories.
+ * @param pw the writer
+ * @param name the name of the factory
+ */
+ private void printFactoryDetail(PrintWriter pw, String name) {
+ List<ComponentTypeDescription> fs = new ArrayList<ComponentTypeDescription>();
+ for (Factory f : this.m_factories) {
+ if (f.getName().equals(name)) {
+ fs.add(f.getComponentDescription());
+ }
+ }
+
+ pw.write("<div class=\"table\">");
+ if (fs.isEmpty()) {
+ pw.write("<b>Factory not found</b><br>The factory " + name + " does not exist or is private");
+ } else {
+ for (ComponentTypeDescription factory : fs) {
+ pw.write("<table class=\"tablelayout\" border=\"0\"><tbody>");
+ addEntry(pw, "Factory Name", factory.getName());
+ if (factory.getVersion() != null) {
+ addEntry(pw, "Factory Version", factory.getVersion());
+ }
+ addEntry(pw, "State", getFactoryState(factory.getFactory().getState()));
+
+ addEntry(pw, " ", " ");
+ if (factory.getprovidedServiceSpecification() != null && factory.getprovidedServiceSpecification().length != 0) {
+ addEntry(pw, "Provided Service Specification", Arrays.toString(factory.getprovidedServiceSpecification()));
+ }
+ if (factory.getProperties() != null && factory.getProperties().length != 0) {
+ addEntry(pw, "Properties", getProperties(factory.getProperties()));
+ }
+
+ addEntry(pw, " ", " ");
+ addEntry(pw, "Required Handlers", factory.getFactory().getRequiredHandlers().toString());
+ addEntry(pw, "Missing Handlers", factory.getFactory().getMissingHandlers().toString());
+ addEntry(pw, " ", " ");
+ addEntry(pw, "Created Instances", getInstanceList(factory.getName()));
+
+ addEntry(pw, " ", " ");
+ addEntry(pw, "Architecture",
+ "<div style=\"overflow: auto; width:800px; border: 1px solid #666; background-color: #ccc; padding: 8px;\"><pre>"
+ + factory.getDescription().toString()
+ + "</pre></div>");
+ pw.write("</tbody></table>");
+ }
+ }
+ pw.write("</div>");
+ }
+
+
+ /**
+ * Gets component type properties HTML table.
+ * @param properties the properties to display
+ * @return the HTML code of the table
+ */
+ private String getProperties(PropertyDescription[] properties) {
+ String s = "<table class=\"tablelayout\" style=\"border-top: 1px solid #6181A9;\">"
+ + "<thead style=\"border-top: 1px solid #6181A9;\">"
+ + "<tr>"
+ + "<th>Property Name</th>"
+ + "<th>Property Type</th>"
+ + "<th>Mandatory</th>"
+ + "<th>Immutable</th>"
+ + "<th>Value</th>"
+ + "</tr>"
+ + "</thead>"
+ + "<tbody>";
+ for (PropertyDescription pd : properties) {
+ String name = pd.getName();
+ String type = pd.getType();
+ boolean mandatory = pd.isMandatory();
+ boolean immutable = pd.isImmutable();
+ String value = pd.getValue();
+ s += "<tr>"
+ + "<td>" + name + "</td>"
+ + "<td>" + type + "</td>"
+ + "<td>" + "" + mandatory + "</td>"
+ + "<td>" + "" + immutable + "</td>"
+ + "<td>" + (value == null ? "<i>No Value</i>" : value) + "</td>"
+ + "</tr>";
+ }
+ s += "</tbody></table>";
+ return s;
+ }
+
+ /**
+ * Gets the instance list page.
+ * @param pw the writer
+ */
+ private void printInstanceList(PrintWriter pw) {
+ pw.write("<div class=\"table\">"
+ + "<table id=\"plugin_table\" class=\"tablelayout\">"
+ + "<thead>"
+ + "<tr>"
+ + "<th class=\"col_Name header headerSortDown\">Instance Name</th>"
+ + "<th class=\"col_Factory header \">Factory Name</th>"
+ + "<th class=\"col_State header \">State</th>"
+ + "</tr>"
+ + "</thead>"
+ + "<tbody>");
+
+ for (Architecture arch : m_archs) {
+ InstanceDescription id = arch.getInstanceDescription();
+ String name = id.getName();
+ String factory = id.getComponentDescription().getName();
+ String state = getInstanceState(id.getState());
+
+ pw.write("<tr>"
+ + "<td>" + getInstanceLink(name) + "</td>"
+ + "<td>" + factory + "</td>"
+ + "<td>" + state + "</td>"
+ + "</tr>");
+
+ }
+
+ pw.write("</tbody></table>");
+ }
+
+ /**
+ * Adds a line into a key / value table.
+ * @param pw the writer
+ * @param header the key
+ * @param value the value (may be HTML code)
+ */
+ private void addEntry(PrintWriter pw, String header, String value) {
+ pw.write(addEntry(header, value));
+
+ }
+
+ /**
+ * Gets the HTML code of a key / value table row.
+ * @param header the key
+ * @param value the value (may be HTML code)
+ * @return the HTML code of the line
+ */
+ private String addEntry(String header, String value) {
+ return "<tr>"
+ + "<td class=\"aligntop\" nowrap=\"true\" style=\"border: 0px none;\">" + header + "</td>"
+ + "<td class=\"aligntop\" style=\"border: 0px none ;\">" + value + "</td>"
+ + "</tr>";
+ }
+
+ /**
+ * Gets the factory link if the factory exists.
+ * @param id the factory name
+ * @return the HTML link targetting the detail of the factory or just the factory name.
+ */
+ private String getFactoryLinkIfPossible(InstanceDescription id) {
+ String n = id.getComponentDescription().getName();
+ System.out.println("Look for " + n);
+ for (Factory f : m_factories) {
+ if (f.getName().equals(n)) {
+ return "<a href=\"ipojo?factory=" + n + "\">" + n + "</a>";
+ }
+ }
+
+ return n; // No link
+ }
+
+ /**
+ * Gets the list of invalid handler.
+ * @param hl the handler description list.
+ * @return the list of invalid handlers.
+ */
+ private String getInvalidHandlerList(HandlerDescription[] hl) {
+ List<String> list = new ArrayList<String>();
+ for (HandlerDescription hd : hl) {
+ if (! hd.isValid()) {
+ list.add(hd.getHandlerName());
+ }
+ }
+ return list.toString();
+ }
+
+ /**
+ * Gets the page containing instance detail.
+ * @param pw the writer
+ * @param name the instance name
+ */
+ private void printInstanceDetail(PrintWriter pw, String name) {
+ InstanceDescription desc = getInstanceDescriptionByName(name);
+ pw.write("<div class=\"table\">");
+ if (desc == null) {
+ pw.write("<b>Instance not found</b><br>The instance " + name + " does not exist or does not expose its architecture");
+ } else {
+ pw.write("<table class=\"tablelayout\" border=\"0\"><tbody>");
+ addEntry(pw, "Instance Name", desc.getName());
+ addEntry(pw, "Factory", getFactoryLinkIfPossible(desc));
+ if (desc.getState() == ComponentInstance.INVALID) {
+ addEntry(pw, "Invalid Handlers", getInvalidHandlerList(desc.getHandlers()));
+ }
+ addEntry(pw, " ", " ");
+ addEntry(pw, "Provided Services", getProvidedServiceDetail(desc.getHandlerDescription("org.apache.felix.ipojo:provides")));
+ addEntry(pw, "Required Services", getRequiredServiceDetail(desc.getHandlerDescription("org.apache.felix.ipojo:requires")));
+
+ addEntry(pw, " ", " ");
+ addEntry(pw, "Architecture",
+ "<div style=\"overflow: auto; width:800px; border: 1px solid #666; background-color: #ccc; padding: 8px;\"><pre>"
+ + desc.getDescription().toString()
+ + "</pre></div>");
+ pw.write("</tbody></table>");
+ }
+ pw.write("</div>");
+ }
+
+ /**
+ * Gets the HTML link targeting this instance.
+ * @param name the instance name
+ * @return the HTML link targetting the instance detail
+ */
+ private String getInstanceLink(String name) {
+ return "<a href=\"ipojo?instance=" + name + "\">" + name + "</a>";
+ }
+
+ /**
+ * Gets the HTML list of service properties.
+ * @param properties the properties
+ * @return the HTML code containing the service properties.
+ */
+ private String getServiceProperties(Properties properties) {
+ String s = "<ul>";
+ Enumeration<Object> e = properties.keys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ String value = properties.get(key).toString();
+ s += "<li>" + key + " = " + value + "</li>";
+ }
+ s += "</ul>";
+ return s;
+ }
+
+ /**
+ * Gets the instance list created by the given factory.
+ * @param factory the factory name
+ * @return the HTML list containing the created instances
+ */
+ private String getInstanceList(String factory) {
+ String s = "<ul>";
+ for (Architecture arch : m_archs) {
+ String n = arch.getInstanceDescription().getComponentDescription().getName();
+ if (factory.equals(n)) {
+ s += "<li>" + getInstanceLink(arch.getInstanceDescription().getName()) + "</li>";
+ }
+ }
+ s += "</ul>";
+ return s;
+ }
+
+ /**
+ * Gets the HTML list containing service references.
+ * If the service is provided by an iPOJO instance, the link is inserted.
+ * @param refs the references.
+ * @return the HTML list
+ */
+ private String getServiceReferenceList(List<ServiceReference> refs) {
+ String s = "<ul>";
+ for (ServiceReference ref : refs) {
+ s += "<li>";
+ if (ref.getProperty("instance.name") == null) {
+ s += ref.getProperty(Constants.SERVICE_ID);
+ } else {
+ s += "<a href=\"ipojo?instance="
+ + ref.getProperty("instance.name") + "\">"
+ + ref.getProperty("instance.name") + " (" + ref.getProperty(Constants.SERVICE_ID) + ")</a>";
+ }
+ s += "</li>";
+ }
+ s += "</ul>";
+ return s;
+ }
+
+ /**
+ * Gets provided service details.
+ * @param hd the provided service handler description or <code>null</code> if not found.
+ * @return the details about provided services
+ */
+ private String getProvidedServiceDetail(HandlerDescription hd) {
+ if (hd == null) {
+ return "No provided services";
+ }
+
+ String r = "";
+ ProvidedServiceHandlerDescription desc = (ProvidedServiceHandlerDescription) hd;
+
+ for (ProvidedServiceDescription ps : desc.getProvidedServices()) {
+ r += "<table border=\"0\"><tbody>";
+ r += addEntry("Specification", Arrays.toString(ps.getServiceSpecifications()));
+ r += addEntry("State", getProvidedServiceState(ps.getState()));
+ if (ps.getServiceReference() != null) {
+ r += addEntry("Service Id", ((Long) ps.getServiceReference().getProperty(Constants.SERVICE_ID)).toString());
+ }
+ r += addEntry("Service Properties", getServiceProperties(ps.getProperties()));
+
+ r += "</tbody></table>";
+ r += "<hr style=\"color: #CCCCCC;'\"/>";
+ }
+
+ return r;
+
+ }
+
+ /**
+ * Gets required service details.
+ * @param hd the required service handler description or <code>null</code> if not found.
+ * @return the details about required services
+ */
+ private String getRequiredServiceDetail(
+ HandlerDescription hd) {
+ if (hd == null) {
+ return "No required services";
+ }
+ String r = "";
+ DependencyHandlerDescription desc = (DependencyHandlerDescription) hd;
+ for (DependencyDescription dep : desc.getDependencies()) {
+ r += "<table border=\"0\" style=\"margin-bottom:5px\"><tbody>";
+ r += addEntry("Specification", dep.getSpecification());
+ r += addEntry("Id", "" + dep.getId());
+ r += addEntry("State", getDependencyState(dep.getState()));
+ r += addEntry("Binding Policy" , getDependencyBindingPolicy(dep.getPolicy()));
+ r += addEntry("Optional", "" + dep.isOptional());
+ r += addEntry("Aggregate", "" + dep.isMultiple());
+ if (dep.getFilter() != null) {
+ r += addEntry("Filter", "" + dep.getFilter());
+ }
+ if (dep.getComparator() != null) {
+ r += addEntry("Comparator", "" + dep.getComparator());
+ }
+ r += addEntry("Matching Service", getServiceReferenceList(dep.getServiceReferences()));
+ r += addEntry("Used Service", getServiceReferenceList(dep.getUsedServices()));
+
+ r += "</tbody></table>";
+ r += "<hr style=\"color: #CCCCCC;'\"/>";
+
+ }
+
+ return r;
+ }
+
+ /**
+ * Gets the instance description by name.
+ * @param name the instance name
+ * @return the instance description or <code>null</code> if not found
+ */
+ private InstanceDescription getInstanceDescriptionByName(String name) {
+ for (Architecture arch : m_archs) {
+ if (name.equals(arch.getInstanceDescription().getName())) {
+ return arch.getInstanceDescription();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Prints the factory list.
+ * @param pw the writer.
+ */
+ private void printFactoryList(PrintWriter pw) {
+ pw.write("<div class=\"table\">"
+ + "<table id=\"plugin_table\" class=\"tablelayout\">"
+ + "<thead>"
+ + "<tr>"
+ + "<th class=\"col_Name header headerSortDown\">Factory Name</th>"
+ + "<th class=\"col_Bundle header \">Bundle</th>"
+ + "<th class=\"col_State header \">State</th>"
+ + "</tr>"
+ + "</thead>"
+ + "<tbody>");
+
+
+
+ for (Factory factory : m_factories) {
+ String name = factory.getName();
+ String version = factory.getVersion();
+ String state = getFactoryState(factory.getState());
+ String bundle = factory.getBundleContext().getBundle().getSymbolicName()
+ + " (" + factory.getBundleContext().getBundle().getBundleId() + ")";
+ pw.write("<tr>"
+ + "<td><a href=\"ipojo?factory=" + name + "\">"
+ + (version == null ? name : name + " (" + version + ")")
+ + "</a></td>" //TODO Link
+ + "<td>" + bundle + "</td>"
+ + "<td>" + state + "</td>"
+ + "</tr>");
+
+ }
+
+ pw.write("</tbody></table>");
+ }
+
+ /**
+ * Print the handler list.
+ * @param pw the writer.
+ */
+ private void printHandlerList(PrintWriter pw) {
+ pw.write("<div class=\"table\">"
+ + "<table id=\"plugin_table\" class=\"tablelayout\">"
+ + "<thead>"
+ + "<tr>"
+ + "<th class=\"col_Name header headerSortDown\">Handler Name</th>"
+ + "<th class=\"col_Type header \">Handler Type</th>"
+ + "<th class=\"col_Bundle header \">Bundle</th>"
+ + "<th class=\"col_State header \">State</th>"
+ + "<th class=\"col_MissingHandler header \">Missing Handler</th>"
+ + "</tr>"
+ + "</thead>"
+ + "<tbody>");
+
+
+
+ for (HandlerFactory hf : m_handlers) {
+ String name = hf.getHandlerName();
+ String type = hf.getType();
+ String state = getFactoryState(hf.getState());
+ String bundle = hf.getBundleContext().getBundle().getSymbolicName()
+ + " (" + hf.getBundleContext().getBundle().getBundleId() + ")";
+ String missing = hf.getMissingHandlers().isEmpty() ? "<i>no missing handlers</i>" : hf.getMissingHandlers().toString();
+ pw.write("<tr>"
+ + "<td>" + name + "</td>"
+ + "<td>" + type + "</td>"
+ + "<td>" + bundle + "</td>"
+ + "<td>" + state + "</td>"
+ + "<td>" + missing + "</td>"
+ + "</tr>");
+
+ }
+
+ pw.write("</tbody></table>");
+ }
+
+ /**
+ * Gets the instance state as a String.
+ * @param state the state.
+ * @return the String form of the state.
+ */
+ private String getInstanceState(int state) {
+ switch(state) {
+ case ComponentInstance.VALID :
+ return "valid";
+ case ComponentInstance.INVALID :
+ return "invalid";
+ case ComponentInstance.DISPOSED :
+ return "disposed";
+ case ComponentInstance.STOPPED :
+ return "stopped";
+ default :
+ return "unknown";
+ }
+ }
+
+ /**
+ * Gets the factory state as a String.
+ * @param state the state.
+ * @return the String form of the state.
+ */
+ private String getFactoryState(int state) {
+ switch(state) {
+ case Factory.VALID :
+ return "valid";
+ case Factory.INVALID :
+ return "invalid";
+ default :
+ return "unknown";
+ }
+ }
+
+ /**
+ * Gets the dependency state as a String.
+ * @param state the state.
+ * @return the String form of the state.
+ */
+ private String getDependencyState(int state) {
+ switch(state) {
+ case DependencyModel.RESOLVED :
+ return "resolved";
+ case DependencyModel.UNRESOLVED :
+ return "unresolved";
+ case DependencyModel.BROKEN :
+ return "broken";
+ default :
+ return "unknown (" + state + ")";
+ }
+ }
+
+ /**
+ * Gets the dependency binding policy as a String.
+ * @param policy the policy.
+ * @return the String form of the policy.
+ */
+ private String getDependencyBindingPolicy(int policy) {
+ switch(policy) {
+ case DependencyModel.DYNAMIC_BINDING_POLICY :
+ return "dynamic";
+ case DependencyModel.DYNAMIC_PRIORITY_BINDING_POLICY :
+ return "dynamic-priority";
+ case DependencyModel.STATIC_BINDING_POLICY :
+ return "static";
+ default :
+ return "unknown (" + policy + ")";
+ }
+ }
+
+ /**
+ * Gets the provided service state as a String.
+ * @param state the state.
+ * @return the String form of the state.
+ */
+ private String getProvidedServiceState(int state) {
+ switch(state) {
+ case ProvidedService.REGISTERED :
+ return "registered";
+ case ProvidedService.UNREGISTERED :
+ return "unregistered";
+ default :
+ return "unknown (" + state + ")";
+ }
+ }
+
+ private final class RequestInfo {
+ /**
+ * Name of the required element.
+ */
+ public final String m_name;
+ /**
+ * Type of the required element.
+ */
+ public final String m_type;
+ /**
+ * Is 'all' elements of the type required.
+ */
+ public final boolean m_all;
+
+ /**
+ * Creates a RequestInfo.
+ * This constructor parses the parameter of the request.
+ * @param request the request
+ */
+ protected RequestInfo(final HttpServletRequest request) {
+ String factory = request.getParameter(FACTORY);
+ String instance = request.getParameter(INSTANCE);
+ String handler = request.getParameter(HANDLER);
+
+ if (factory != null) {
+ m_type = FACTORY;
+ m_name = factory;
+ } else if (instance != null) {
+ m_type = INSTANCE;
+ m_name = instance;
+ } else if (handler != null) {
+ m_type = HANDLER;
+ m_name = handler;
+ } else {
+ m_type = INSTANCE;
+ m_name = ALL;
+ }
+
+ if (ALL.equals(m_name)) {
+ m_all = true;
+ } else {
+ m_all = false;
+ }
+
+ request.setAttribute(IPOJOServlet.class.getName(), this);
+ }
+
+ /**
+ * toString method.
+ * @return the String form of the request.
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "Request: " + m_type + "=" + m_name;
+ }
+
+ }
+
+}