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.geronimo.system.main;
018    
019    import java.io.PrintStream;
020    import java.net.InetSocketAddress;
021    import java.util.ArrayList;
022    import java.util.Collections;
023    import java.util.HashMap;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.Set;
028    
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    import org.apache.geronimo.gbean.AbstractName;
032    import org.apache.geronimo.gbean.AbstractNameQuery;
033    import org.apache.geronimo.gbean.GAttributeInfo;
034    import org.apache.geronimo.gbean.GBeanData;
035    import org.apache.geronimo.gbean.GBeanInfo;
036    import org.apache.geronimo.kernel.Kernel;
037    import org.apache.geronimo.kernel.management.State;
038    
039    /**
040     * @version $Rev: 562021 $ $Date: 2007-08-02 01:51:18 -0400 (Thu, 02 Aug 2007) $
041     */
042    public class StartupMonitorUtil {
043        private final static Log log = LogFactory.getLog(StartupMonitor.class.getName());
044    
045        public static synchronized void wrapUp(PrintStream out, Kernel kernel) {
046            List apps = new ArrayList();  // type = String (message)
047            List webs = new ArrayList();  // type = WebAppInfo
048            List ports = new ArrayList(); // type = AddressHolder
049            Map failed = new HashMap();   // key = AbstractName, value = String (message)
050            String serverInfo = null;
051            try {
052                Set gbeans = kernel.listGBeans((AbstractNameQuery) null);
053                Map beanInfos = new HashMap(); // key = GBeanInfo, value = List (of attribute names)
054                for (Iterator it = gbeans.iterator(); it.hasNext();) {
055                    AbstractName name = (AbstractName) it.next();
056                    if (isApplicationModule(name)) {
057                        apps.add("    " + decodeModule(name.getNameProperty("j2eeType")) + ": " + name.getNameProperty("name"));
058                    }
059                    if (isWebModule(name)) {
060                        webs.add(kernel.getAttribute(name, "contextPath").toString());
061                    }
062    
063                    int stateValue = kernel.getGBeanState(name);
064                    if (stateValue != State.RUNNING_INDEX) {
065                        GBeanData data = kernel.getGBeanData(name);
066                        State state = State.fromInt(stateValue);
067                        StringBuffer buf = new StringBuffer();
068                        buf.append("(").append(state.getName());
069                        // Since it's not unusual for a failure to be caused by a port binding failure
070                        //    we'll see if there's a likely looking port attribute in the config data
071                        //    for the GBean.  It's a long shot, but hey.
072                        if (data != null && data.getAttributes() != null) {
073                            Map map = data.getAttributes();
074                            for (Iterator it2 = map.keySet().iterator(); it2.hasNext();) {
075                                String att = (String) it2.next();
076                                if (att.equals("port") || att.indexOf("Port") > -1) {
077                                    buf.append(",").append(att).append("=").append(map.get(att));
078                                }
079                            }
080                        }
081                        buf.append(")");
082                        failed.put(name, buf.toString());
083                        continue;
084                    }
085    
086                    // Check if this is ServerInfo
087                    GBeanInfo info = kernel.getGBeanInfo(name);
088                    if (info.getClassName().equals("org.apache.geronimo.system.serverinfo.ServerInfo")) {
089                        serverInfo = (String) kernel.getAttribute(name, "version");
090                    }
091    
092                    // Look for any SocketAddress properties
093                    List list = (List) beanInfos.get(info);
094                    if (list == null) {
095                        list = new ArrayList(3);
096                        beanInfos.put(info, list);
097                        Set atts = info.getAttributes();
098                        for (Iterator it2 = atts.iterator(); it2.hasNext();) {
099                            GAttributeInfo att = (GAttributeInfo) it2.next();
100                            if (att.getType().equals("java.net.InetSocketAddress")) {
101                                list.add(att);
102                            }
103                        }
104                    }
105                    for (int i = 0; i < list.size(); i++) {
106                        GAttributeInfo att = (GAttributeInfo) list.get(i);
107                        try {
108                            InetSocketAddress addr = (InetSocketAddress) kernel.getAttribute(name, att.getName());
109                            if (addr == null) {
110                                log.debug("No value for GBean " + name + " attribute " + att.getName());
111                                continue;
112                            } else if (addr.getAddress() == null || addr.getAddress().getHostAddress() == null) {
113                                log.debug("Null address or host for GBean " + name + " " + att.getName() + ": " + addr.getAddress());
114                            }
115                            String attName = info.getName();
116                            if (list.size() > 1) {
117                                attName += " " + decamelize(att.getName());
118                            } else if (info.getAttribute("name") != null) {
119                                attName += " " + kernel.getAttribute(name, "name");
120                            }
121                            ports.add(new AddressHolder(attName, addr));
122                        } catch (IllegalStateException e) {
123                            // We weren't able to load a port for this service -- that's a bummer
124                        }
125                    }
126                }
127            } catch (Exception e) {
128                e.printStackTrace();
129            }
130    
131            Collections.sort(apps);
132    
133            // Helpful output: list of ports we listen on
134            if (ports.size() > 0) {
135                Collections.sort(ports);
136                System.out.println("  Listening on Ports:");
137                int max = 0;
138                for (int i = 0; i < ports.size(); i++) {
139                    AddressHolder holder = (AddressHolder) ports.get(i);
140                    if (holder.getAddress().getAddress() != null && holder.getAddress().getAddress().getHostAddress() != null)
141                    {
142                        max = Math.max(max, holder.getAddress().getAddress().getHostAddress().length());
143                    }
144                }
145                for (int i = 0; i < ports.size(); i++) {
146                    AddressHolder holder = (AddressHolder) ports.get(i);
147                    StringBuffer buf = new StringBuffer();
148                    buf.append("   ");
149                    if (holder.getAddress().getPort() < 10) {
150                        buf.append(' ');
151                    }
152                    if (holder.getAddress().getPort() < 100) {
153                        buf.append(' ');
154                    }
155                    if (holder.getAddress().getPort() < 1000) {
156                        buf.append(' ');
157                    }
158                    if (holder.getAddress().getPort() < 10000) {
159                        buf.append(' ');
160                    }
161                    buf.append(holder.getAddress().getPort()).append(' ');
162                    String address = holder.getAddress().getAddress() == null || holder.getAddress().getAddress().getHostAddress() == null ? "" :
163                            holder.getAddress().getAddress().getHostAddress();
164                    buf.append(address);
165                    for (int j = address.length(); j <= max; j++) {
166                        buf.append(' ');
167                    }
168                    buf.append(holder.getName());
169                    out.println(buf.toString());
170                }
171                out.println();
172            }
173            // Helpful output: list of applications started
174            if (apps.size() > 0) {
175                out.println("  Started Application Modules:");
176                for (int i = 0; i < apps.size(); i++) {
177                    out.println((String) apps.get(i));
178                }
179                out.println();
180            }
181            // Helpful output: Web URLs
182            if (webs.size() > 0) {
183                Collections.sort(webs);
184                out.println("  Web Applications:");
185                for (int i = 0; i < webs.size(); i++) {
186                    out.println("    " + webs.get(i));
187                }
188                out.println();
189            }
190    
191            // Helpful output: list of GBeans that did not start
192            if (failed.size() > 0) {
193                out.println("  WARNING: Some GBeans were not started successfully:");
194                for (Iterator it = failed.keySet().iterator(); it.hasNext();) {
195                    AbstractName name = (AbstractName) it.next();
196                    String state = (String) failed.get(name);
197                    if (name.getNameProperty("name") != null) {
198                        log.debug("Unable to start " + name + " " + state);
199                        out.println("    " + name.getNameProperty("name") + " " + state);
200                    } else {
201                        out.println("    " + name + " " + state);
202                    }
203                }
204                out.println();
205            }
206    
207            StringBuffer msg = new StringBuffer();
208            msg.append("Geronimo Application Server started");
209            if (serverInfo != null) {
210                msg.append(" (version ").append(serverInfo).append(")");
211            }
212            out.println(msg.toString());
213            out.flush();
214        }
215    
216        private static boolean isApplicationModule(AbstractName abstractName) {
217            String type = abstractName.getNameProperty("j2eeType");
218            String app = abstractName.getNameProperty("J2EEApplication");
219            String name = abstractName.getNameProperty("name");
220            if (type != null && (app == null || app.equals("null"))) {
221                return (type.equals("WebModule") || type.equals("J2EEApplication") || type.equals("EJBModule") || type.equals("AppClientModule") || type.equals("ResourceAdapterModule")) && !name.startsWith("geronimo/system");            
222            }
223            return false;
224        }
225    
226        private static boolean isWebModule(AbstractName abstractName) {
227            String type = abstractName.getNameProperty("j2eeType");
228            return type != null && type.equals("WebModule");
229        }
230    
231        private static String decodeModule(String value) {
232            if (value.equals("WebModule")) {
233                return "WAR";
234            } else if (value.equals("J2EEApplication")) {
235                return "EAR";
236            } else if (value.equals("EJBModule")) {
237                return "JAR";
238            } else if (value.equals("AppClientModule")) {
239                return "CAR";
240            } else if (value.equals("ResourceAdapterModule")) {
241                return "RAR";
242            } else {
243                return "UNK";
244            }
245        }
246    
247        private static String decamelize(String s) {
248            if (s == null || s.equals("")) {
249                return s;
250            }
251            StringBuffer buf = new StringBuffer();
252            buf.append(Character.toUpperCase(s.charAt(0)));
253            for (int i = 1; i < s.length(); i++) {
254                if (Character.isUpperCase(s.charAt(i))) {
255                    if (s.length() > i + 1 && Character.isLowerCase(s.charAt(i + 1))) {
256                        buf.append(" ");
257                    }
258                }
259                buf.append(s.charAt(i));
260            }
261            return buf.toString();
262        }
263    
264        private static class AddressHolder implements Comparable {
265            private String name;
266            private InetSocketAddress address;
267    
268            public AddressHolder(String name, InetSocketAddress address) {
269                this.name = name;
270                this.address = address;
271            }
272    
273            public String getName() {
274                return name;
275            }
276    
277            public void setName(String name) {
278                this.name = name;
279            }
280    
281            public InetSocketAddress getAddress() {
282                return address;
283            }
284    
285            public void setAddress(InetSocketAddress address) {
286                this.address = address;
287            }
288    
289            public int compareTo(Object o) {
290                AddressHolder other = (AddressHolder) o;
291                int value = address.getPort() - other.address.getPort();
292                return value == 0 ? address.getAddress().toString().compareTo(other.address.getAddress().toString()) : value;
293            }
294        }
295    }