001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.jbi.view;
018
019 import java.io.FileWriter;
020 import java.io.PrintWriter;
021 import java.util.ArrayList;
022 import java.util.Collection;
023 import java.util.List;
024
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.apache.servicemix.jbi.container.JBIContainer;
028 import org.apache.servicemix.jbi.event.ContainerAware;
029 import org.apache.servicemix.jbi.framework.ComponentMBeanImpl;
030 import org.apache.servicemix.jbi.framework.Endpoint;
031 import org.apache.servicemix.jbi.framework.Registry;
032
033 /**
034 * Creates a <a href="http://www.graphviz.org/">DOT</a> file showing the various components
035 * and endpoints within ServiceMix
036
037 * @org.apache.xbean.XBean
038 * description="Generates DOT visualisations of the components and endpoints available inside ServiceMix"
039 *
040 * @version $Revision: 564607 $
041 */
042 public class DotViewEndpointListener extends EndpointViewRenderer implements ContainerAware {
043
044 private static final Log LOG = LogFactory.getLog(DotViewEndpointListener.class);
045
046 private JBIContainer container;
047 private String file = "ServiceMixComponents.dot";
048
049
050 public JBIContainer getContainer() {
051 return container;
052 }
053
054 public void setContainer(JBIContainer container) {
055 this.container = container;
056 }
057
058 public String getFile() {
059 return file;
060 }
061
062 public void setFile(String file) {
063 this.file = file;
064 }
065
066 // Implementation methods
067 // -------------------------------------------------------------------------
068
069 protected void doRender() throws Exception {
070 if (LOG.isDebugEnabled()) {
071 LOG.debug("Creating DOT file at: " + file);
072 }
073 PrintWriter writer = new PrintWriter(new FileWriter(file));
074 try {
075 generateFile(writer);
076 } finally {
077 writer.close();
078 }
079 }
080
081 protected void generateFile(PrintWriter writer) throws Exception {
082 writer.println("digraph \"Apache ServiceMix\" {");
083 writer.println();
084 writer.println("node [ shape = box, style = \"rounded,filled\", fontname = \"Helvetica-Oblique\", fontsize = 8 ];");
085 writer.println();
086 writer.println("jbi [ fillcolor = \"#FFFF99\", label=\"Apache ServiceMix: " + container.getName() + "\" ];");
087 writer.println();
088
089 List<String> brokerLinks = new ArrayList<String>();
090 Registry registry = container.getRegistry();
091 Collection<ComponentMBeanImpl> components = registry.getComponents();
092 for (ComponentMBeanImpl component : components) {
093 String name = component.getName();
094 String id = encode(name);
095
096 writer.print(id);
097 writer.print(" [ fillcolor = gray, label = \"");
098 writer.print(name);
099 writer.println("\" ];");
100
101 brokerLinks.add("jbi -> " + id);
102 }
103 writer.println();
104 generateLinks(writer, brokerLinks);
105
106 writer.println();
107
108 List<String> componentEndpointLinks = new ArrayList<String>();
109 Collection<Endpoint> endpointMBeans = registry.getEndpointRegistry().getEndpointMBeans();
110 for (Endpoint endpoint : endpointMBeans) {
111 String key = endpoint.getSubType().toLowerCase() + ":{"
112 + endpoint.getServiceName().getNamespaceURI() + "}"
113 + endpoint.getServiceName().getLocalPart() + ":"
114 + endpoint.getEndpointName();
115 String componentName = encode(endpoint.getComponentName());
116 String id = encode(key);
117 writer.print(id);
118 String epname = formatEndpoint(key);
119 String color = "lightgray";
120 if (epname.startsWith("internal")) {
121 epname = epname.substring(10);
122 color = "#6699ff";
123 } else if (epname.startsWith("external")) {
124 epname = epname.substring(10);
125 color = "#66ccff";
126 } else if (epname.startsWith("dynamic")) {
127 epname = epname.substring(9);
128 color = "#6666ff";
129 } else if (epname.startsWith("linked")) {
130 epname = epname.substring(8);
131 color = "#66ffff";
132 } else {
133 color = "#f3f3f3";
134 }
135 writer.print(" [ fillcolor = \"" + color + "\", label = \"");
136 writer.print(epname);
137 writer.println("\" ];");
138
139 componentEndpointLinks.add(componentName + " -> " + id);
140 }
141 generateLinks(writer, componentEndpointLinks);
142
143 writer.println("}");
144 }
145
146 protected String formatEndpoint(String key) {
147 int i1 = key.indexOf('{');
148 int i2 = key.indexOf('}');
149 int i3 = key.indexOf(':', i2);
150 String type = key.charAt(i1 - 1) == ':' ? key.substring(0, i1 - 1) : null;
151 String uri = key.substring(i1 + 1, i2);
152 String svc = key.substring(i2 + 1, i3);
153 String ep = key.substring(i3 + 1);
154 if (type != null) {
155 return type + "\\n" + uri + "\\n" + svc + "\\n" + ep;
156 } else {
157 return uri + "\\n" + svc + "\\n" + ep;
158 }
159 }
160
161 protected void generateLinks(PrintWriter writer, Collection<String> lines, String style) {
162 for (String line : lines) {
163 writer.print(line);
164 if (style != null) {
165 writer.print(" [" + style + "]");
166 }
167 writer.println(";");
168 }
169 writer.println();
170 }
171
172 protected void generateLinks(PrintWriter writer, Collection<String> lines) {
173 generateLinks(writer, lines, null);
174 }
175
176 /**
177 * Lets strip out any non supported characters
178 */
179 protected String encode(String name) {
180 StringBuffer buffer = new StringBuffer();
181 for (int i = 0; i < name.length(); i++) {
182 char ch = name.charAt(i);
183 if (Character.isLetterOrDigit(ch) || ch == '_') {
184 buffer.append(ch);
185 } else {
186 buffer.append('_');
187 }
188 }
189 return buffer.toString();
190 }
191
192
193 }