001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.runtime.model.impl;
018
019import java.io.BufferedWriter;
020import java.io.File;
021import java.io.FileWriter;
022import java.io.IOException;
023import java.io.OutputStream;
024import java.io.OutputStreamWriter;
025import java.io.StringWriter;
026import java.io.Writer;
027import java.net.URL;
028
029import javax.xml.parsers.DocumentBuilderFactory;
030import javax.xml.parsers.ParserConfigurationException;
031
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.apache.xml.serialize.Method;
035import org.apache.xml.serialize.OutputFormat;
036import org.apache.xml.serialize.XMLSerializer;
037import org.nuxeo.runtime.Version;
038import org.nuxeo.runtime.api.Framework;
039import org.nuxeo.runtime.model.ComponentName;
040import org.nuxeo.runtime.model.ExtensionPoint;
041import org.nuxeo.runtime.model.RegistrationInfo;
042import org.w3c.dom.Document;
043import org.w3c.dom.Element;
044
045/**
046 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
047 */
048// use by reflection from DevFrameworkBootstrap
049public class ComponentRegistrySerializer {
050
051    private final static Log log = LogFactory.getLog(ComponentRegistrySerializer.class);
052
053    public static void writeIndex(File file) throws IOException {
054        BufferedWriter writer = new BufferedWriter(new FileWriter(file));
055        try {
056            writeIndex(writer);
057        } finally {
058            writer.close();
059        }
060    }
061
062    public static void writeIndex(Writer writer) throws IOException {
063        ComponentManagerImpl mgr = (ComponentManagerImpl) Framework.getRuntime().getComponentManager();
064        for (RegistrationInfo ri : mgr.getRegistrations()) {
065            ComponentName name = ri.getName();
066            if (name == null) {
067                log.error("BUG: Found component with null name");
068                continue;
069            }
070            String src = getComponentSrc(ri);
071            if (src == null) {
072                src = "";
073            }
074
075            String bundle = ri.getBundle();
076            if (bundle == null) {
077                bundle = ri.getContext().getBundle().getSymbolicName();
078            }
079            if (bundle == null) {
080                bundle = "";
081            }
082
083            String cname = name.getName();
084            writer.write("c:");
085            writer.write(cname);
086            writer.write(":");
087            writer.write(bundle);
088            writer.write(":");
089            writer.write(src);
090            writer.write("\n");
091
092            // write services
093            String[] services = ri.getProvidedServiceNames();
094            if (services != null && services.length > 0) {
095                for (String service : services) {
096                    writer.write("s:");
097                    writer.write(cname);
098                    writer.write(":");
099                    writer.write(service);
100                    writer.write("\n");
101                }
102            }
103
104            // write services
105            ExtensionPoint[] xpoints = ri.getExtensionPoints();
106            if (xpoints != null && xpoints.length > 0) {
107                for (ExtensionPoint xpoint : xpoints) {
108                    writer.write("x:");
109                    writer.write(cname);
110                    writer.write(":");
111                    writer.write(xpoint.getName());
112                    writer.write("\n");
113                }
114            }
115        }
116    }
117
118    private static String getComponentSrc(RegistrationInfo ri) {
119        URL url = ri.getXmlFileUrl();
120        if (url != null) {
121            String src;
122            String path = url.toExternalForm();
123            int i = path.lastIndexOf('!');
124            if (i > 0) {
125                String jar = path.substring(0, i);
126                path = path.substring(i + 1);
127                int s = jar.lastIndexOf('/');
128                if (s > -1) {
129                    jar = jar.substring(s + 1);
130                }
131                src = jar + "!" + path;
132            } else {
133                int s = path.lastIndexOf('/');
134                if (s != -1) {
135                    src = path.substring(s + 1);
136                } else {
137                    src = path;
138                }
139            }
140            return src;
141        }
142        return null;
143    }
144
145    public static Document toDocument() {
146        ComponentManagerImpl mgr = (ComponentManagerImpl) Framework.getRuntime().getComponentManager();
147        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
148        Document doc;
149        try {
150            doc = factory.newDocumentBuilder().newDocument();
151        } catch (ParserConfigurationException e) {
152            throw new RuntimeException(e);
153        }
154        Element root = doc.createElement("components");
155        doc.appendChild(root);
156
157        for (RegistrationInfo ri : mgr.getRegistrations()) {
158            ComponentName name = ri.getName();
159            if (name == null) {
160                log.error("BUG: Found component with null name");
161                continue;
162            }
163
164            Element comp = doc.createElement("component");
165            comp.setAttribute("name", name.getName());
166            String impl = ri.getImplementation();
167            if (impl != null && impl.length() > 0) {
168                comp.setAttribute("class", impl);
169            }
170            String bundle = ri.getBundle();
171            if (bundle == null) {
172                bundle = ri.getContext().getBundle().getSymbolicName();
173            }
174            if (bundle != null) {
175                comp.setAttribute("bundle", bundle);
176            }
177            Version v = ri.getVersion();
178            if (v != null) {
179                comp.setAttribute("version", v.toString());
180            }
181            root.appendChild(comp);
182
183            // write source if known
184            String src = getComponentSrc(ri);
185            if (src != null) {
186                comp.setAttribute("src", src);
187            }
188
189            // write documentation
190            String docText = ri.getDocumentation();
191            if (docText != null) {
192                docText = docText.trim();
193                Element docu = doc.createElement("documentation");
194                docu.setTextContent(docText);
195                comp.appendChild(docu);
196            }
197
198            // write services
199            String[] services = ri.getProvidedServiceNames();
200            if (services != null && services.length > 0) {
201                Element svcsEl = doc.createElement("services");
202                for (String service : services) {
203                    Element svcEl = doc.createElement("service");
204                    svcEl.setAttribute("class", service);
205                    svcsEl.appendChild(svcEl);
206                }
207                comp.appendChild(svcsEl);
208            }
209
210            // write extension points
211            ExtensionPoint[] xps = ri.getExtensionPoints();
212            if (xps != null && xps.length > 0) {
213                Element xpsEl = doc.createElement("extension-points");
214                for (ExtensionPoint xp : xps) {
215                    Element xpEl = doc.createElement("extension-point");
216                    xpEl.setAttribute("name", xp.getName());
217                    docText = xp.getDocumentation();
218                    if (docText != null) {
219                        xpEl.setTextContent(docText.trim());
220                    }
221                    xpsEl.appendChild(xpEl);
222                }
223                comp.appendChild(xpsEl);
224            }
225        }
226        return doc;
227    }
228
229    public static void toXML(OutputStream out) throws IOException {
230        toXML(out, "UTF-8");
231    }
232
233    public static void toXML(OutputStream out, String encoding) throws IOException {
234        OutputStreamWriter writer = new OutputStreamWriter(out, encoding);
235        toXML(writer, encoding);
236    }
237
238    public static void toXML(Writer out) throws IOException {
239        toXML(out, "UTF-8");
240    }
241
242    public static void toXML(Writer out, String encoding) throws IOException {
243        Document doc = toDocument();
244        OutputFormat format = new OutputFormat(Method.XML, encoding, true);
245        format.setIndent(2);
246        XMLSerializer serializer = new XMLSerializer(out, format);
247        serializer.serialize(doc);
248        out.flush();
249    }
250
251    public static String toXML() throws IOException {
252        StringWriter writer = new StringWriter();
253        toXML(writer);
254        return writer.toString();
255    }
256
257}